refactor(events): rename the eth log event to chain-log#185
Open
mfw78 wants to merge 4 commits into
Open
Conversation
…config, and sdk Rename the Ethereum contract-event-log concept (eth_getLogs / eth_subscribe "logs") from `log`/`logs` to `chain-log`/`chain-logs` throughout, so it no longer collides with the diagnostics logging pipeline. The block, tick, and message events keep their names. Wire (guest-visible world break, sanctioned pre-1.0): the WIT `log` record becomes `chain-log` and the `logs(list<log>)` event arm becomes `chain-logs(list<chain-log>)`. Record fields, including `log-index`, are unchanged. Config: the subscription `kind = "log"` becomes `kind = "chain-log"`. The manifest discriminator renames to `ChainLog` with a `chain-log` serde tag, so a stale `kind = "log"` manifest fails load with an unknown-kind error naming the valid set (block, chain-log, cron). Runtime: the chain-event subscription source and dispatch path rename (subscribe_chain_logs, ChainLogStream, open_chain_log_streams, dispatch_chain_log, the Subscription::ChainLog arm, and the stream metric label). The diagnostics logging pipeline is untouched. SDK and modules: guest bindings regenerate from the WIT as ChainLog / Event::ChainLogs; the strategy view type becomes ChainLogView and the handler becomes on_chain_logs across twap-monitor, ethflow-watcher, and the backtest harness. Docs: the event-kind nomenclature is swept across the module, overview, sdk, and diagram pages, and the breaking world change is recorded in the migration guide.
Package chain-log deliveries as the native alloy_rpc_types_eth::Log rather than an SDK-invented view. The WIT chain-log record now mirrors the eth_getLogs shape field for field (adding block-hash, block-timestamp, transaction-index, removed; widening the indices to u64; making block-scoped fields optional for pending logs), so a guest reconstructs the alloy log without loss. The chain id moves off each record onto a new chain-logs batch record, since a subscription delivery always shares one chain and the alloy log carries no chain id of its own. The host projects an alloy Log straight into the record with no intermediate; the SDK bind macro emits the inverse conversion at the guest edge, so module glue maps a batch to Vec<Log> and strategies decode sol! events against log.inner. Migrate twap-monitor and ethflow-watcher onto &[Log], the backtest replay harness onto the assemble_log constructor, and extend the WIT and payload-shape docs.
The universal-world snippets in docs 01 and 08 kept the pre-rename chain-log record while pointing the event arm at chain-logs, leaving both files referencing an undefined type and listing stale fields. Reshape the record to match the authoritative wit (optional block-scoped fields plus removed) and add the chain-logs batch record that carries the chain id. Add host-side coverage for project_chain_log on a mined log (every block-scoped field present) and a pending log (each left None), closing the projection's test gap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #184.
Renames the chain-event log kind to
chain-logat full depth (WIT, manifest, generated bindings, runtime dispatch, SDK, docs) so the on-chain event vocabulary no longer collides with the diagnostics logging pipeline, which is untouched.This PR is stacked on #183 (
refactor/modules-tracing-macros) and targets that branch; it carries only the chain-log rename and merges after #183 lands.Changes
WIT (
wit/nexum-host/types.witand mirrored docs):record logrenamed torecord chain-log; event armlogs(list<log>)renamed tochain-logs(list<chain-log>). Fields unchanged, includinglog-index. Theblock,tick,messagearms and theeventenvelope are untouched.Generated bindings (wit-bindgen/wasmtime):
types::Logtotypes::ChainLog;Event::LogstoEvent::ChainLogs.Manifest (
manifest/types.rs):Subscription::LogtoSubscription::ChainLogwith#[serde(rename = "chain-log")]; every in-treemodule.tomlusing the log kind (twap-monitor, ethflow-watcher) updated tokind = "chain-log". A manifest still carrying the retiredkind = "log"now fails to load with an unknown-variant error that names the valid set (block,chain-log,cron).Runtime chain-event path:
subscribe_logstosubscribe_chain_logs;LogStreamtoChainLogStream;open_log_streamstoopen_chain_log_streams;reconnecting_log_tasktoreconnecting_chain_log_task;TaggedLogStreamtoTaggedChainLogStream;log_streamstochain_log_streams;NextEvent::LogtoNextEvent::ChainLog;dispatched_logstodispatched_chain_logs;Supervisor::dispatch_logtodispatch_chain_log;log_subscriptionstochain_log_subscriptions;project_logtoproject_chain_log. Metric and event-kind labels (kind => "log", dispatch-kind"log",StreamPanic("log")) all become"chain-log", and the associated tracing message strings follow the same rename.SDK and modules: strategy view
LogViewtoChainLogView; handleron_logstoon_chain_logs(twap-monitor, ethflow-watcher, shepherd-backtest replay, fixtures, and report); theon_chain_logsparameter and loop variable renamed fromlogs/logtochain_logs/chain_log; moduleEvent::Logsmatch arms becomeEvent::ChainLogs.Untouched diagnostics boundary, deliberately: the entire
host/logs/subtree (LogRecord,LogRouter,RunLogStore,LogSource,LogPipeline,LogPage,LogRetentionLimits),[limits.logs], thenexum:host/loggingWITlog:function andLoggingHost, stdio capture, andcapture_tracingare all unchanged, since separating this vocabulary from the diagnostics one is the point of the rename. Ethereum RPC literals that genuinely meaneth_getLogs/eth_subscribe(logs)(alloy'ssubscribe_logs, theEthGetLogsmethod variant) are kept as-is, since those are the upstream wire names, not ours.Docs updated:
docs/02-modules-events-packaging.md,docs/00-overview.md,docs/01-runtime-environment.md,docs/05-sdk-design.md,docs/07-rpc-namespace-design.md,docs/08-platform-generalisation.md,docs/production.md,docs/diagrams/{diagrams.md, engine-boot.mmd, subscription-dispatch.mmd}, the top-levelREADME.md,docs/operations/e2e-reports/e2e-report.template.md, anddocs/operations/m3-testnet-runbook.md. Dated historical reports (e2e-report-2026-06-18,load-*) and ADR-0009 are left frozen, since they record what happened at the time.Migration note added to
docs/migration/0.1-to-0.2.md, covering the manifest kind change, the rebuild requirement for components built against the old world, and theon_logstoon_chain_logshandler rename.Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo doc --workspace --all-features -- -D warningscargo build --release --target wasm32-wasip2for all 11 in-tree modulescargo test --workspace --all-features(all suites green, no skipped tests)e2e_ethflow_watcher_log_dispatchande2e_twap_monitor_block_dispatchpass end-to-end against in-tree wasms, driving the renamedchain-logssubscription andEvent::ChainLogsdispatch through thedispatch_chain_logpathload_rejects_the_retired_log_kindconfirms a stalekind = "log"manifest fails to load with an error naming the valid kind setwasm-tools component witon a built module confirms the shipped component carries the extendedrecord chain-log(full RPC shape) and the batch-levelrecord chain-logscarryingchain-id, with no old-shapelogsurvivorcargo test -p nexum-runtimecoversproject_chain_log_preserves_mined_logandproject_chain_log_leaves_pending_fields_none, proving the host projection preserves every block-scoped field on a mined log and leaves themNone, not zero-defaulted, on a pending logalloy-rpc-types-ethpulls no new heavyweight dependency into the guest conedocs/01-runtime-environment.mdanddocs/08-platform-generalisation.mdWIT snippets verified consistent with the authoritativewit/nexum-host/types.witNotes for reviewer
This is a guest-visible world break: any component built against the previous WIT world (the
logrecord, thelogsevent arm) no longer links against the current world and must be rebuilt, and any manifest withkind = "log"fails to load. Both are called out in the migration note.The diagnostics logging pipeline is intentionally untouched throughout this diff; if you see a
logtoken survive in the diff, check whether it is diagnostics-side (correct, leave it) or chain-event-side (should have been renamed) before flagging it.Alloy log seam (appended)
The PR gained a second, related change on top of the rename: chain logs now cross the host-guest boundary as the real
alloy_rpc_types_eth::Logtype on both sides, rather than a bespoke payload. The guiding principle is no invented types at the seam: the wire vocabulary is exactly alloy's own RPC vocabulary, so there is no domain-specific log type of ours to keep in sync as alloy'sLogevolves.The seam shape is alloy
Logon the host, converted to the WITchain-logrecord for the wasm boundary, converted back to an alloyLogon the guest. Conversions live only at the two edges,project_chain_logon the host insupervisor.rsandassemble_logon the guest innexum-sdk's neweventsmodule, so every consumer in between (runtime dispatch, module strategies, the backtest replay harness) operates on the same alloyLogtype end to end instead of a bespoke intermediate view.The
chain-logWIT record was extended to the full RPC shape (block-hash,block-number,block-timestamp,transaction-hash,transaction-index,log-index,removed), each field's optionality mirroring alloy's ownOptionsemantics rather than being defaulted away. The chain id was deliberately lifted out of the per-recordchain-logand placed on a new batch-levelchain-logsrecord instead, because alloy'sLogitself carries no chain id and the supervisor already delivers logs per(module, chain, filter), so every log in onedispatch_chain_logbatch shares a single chain by construction; stamping the chain id on each record would have been redundant, and lifting it letproject_chain_logdrop an argument.The dependency verdict on
alloy-rpc-types-eth(workspace pin 2.1,default-features = false,features = ["std"]) is that it is fully usable onwasm32-wasip2and was added only tonexum-sdk; it built clean on the guest target and pulled in only the pure alloy primitives (consensus, eips, trie, serde, network-primitives) already transitively resident in the guest cone via cowprotocol. The measured guest wasm size delta for twap-monitor was 376240 to 376593 bytes, +353 bytes (+0.1 per cent), independently confirmed in review at +351 bytes; negligible, sinceLogis a thin envelope over primitives the guest already carried.Net effect on conversion code is deletion: the host-side projection became lossless and intermediate-free, the guest gained a single conversion home (
assemble_logplus one bind-macro-generatedFrom<chain-log> for events::Log), and each consumer's bespoke view type was deleted outright,ChainLogViewremoved from both twap-monitor and ethflow-watcher, with their raw-bytes decode paths replaced bySolEvent::decode_log(&log.inner)against the real alloy type.An adversarial review pass confirmed the round trip is lossless across every alloy
Logfield with correctOptionsemantics, then raised two non-blocking findings, both since fixed.docs/01-runtime-environment.mdanddocs/08-platform-generalisation.mdstill showed the pre-extensionchain-logWIT snippet and lacked the batch-levelchain-logsrecord; both are now aligned with the authoritativewit/nexum-host/types.wit. The host-sideproject_chain_logprojection had no dedicated test; it is now covered by the two newnexum-runtimetests listed in the Test plan above.AI Assistance: Claude Code (Opus 4.8 implementation and adversarial review, Sonnet 5 PR authoring) used for the full change.