Skip to content

Release readiness (full rerun on the reactive + cold-start main)#15

Merged
KaiCode2 merged 15 commits into
mainfrom
release-readiness-v2
Jun 30, 2026
Merged

Release readiness (full rerun on the reactive + cold-start main)#15
KaiCode2 merged 15 commits into
mainfrom
release-readiness-v2

Conversation

@KaiCode2

Copy link
Copy Markdown
Owner

Supersedes #13. After #14 landed the reactive runtime + cold-start + live AlloySubscriber on main, this is the full release-readiness pass re-run over the combined surface (#13 hardened the older events-API line, which has been superseded). Branched off the post-#14 main; #13's work is carried forward by cherry-pick, then the new surface is hardened. Full gate green (fmt, clippy -D warnings, 43 test binaries / 0 failures, 28 doctests, cargo doc -D warnings), and adversarially reviewed.

Carried forward from #13 (cherry-picked, auto-merged cleanly)

chain_id builder + provider inference + set_chain_id (replaces the Arbitrum-42161 default); SECURITY.md; dated 0.1.0 CHANGELOG + link refs; Cargo.toml exclude of internal phase specs; the honest benchmark reframe (drops the strawman ~500×/~545×/~3,800× multipliers, states parity vs a competent shared-backend/checkpoint-revert baseline, leads with cross-block freshness + the cross_block_freshness.svg chart + mermaid diagrams); the create3/access_list/state_update doc sweep; fetch_minimization + builder_chain_id tests; removed the never-shipped SimulationErrorKind alias; docs/INTERNALS.md.

New-surface hardening (this rerun)

Doc accuracy — the merge left two stale claims, both fixed: the README "Maturity" note (said live transport was consumer-provided while AlloySubscriber ships) and the matching KNOWN_ISSUES entry. Documented cold_start everywhere it was missing (README bullet, lib.rs module map, CHANGELOG, including the serial-account/first-failure-abort cost). Repositioned "Why it exists" toward the out-of-the-box reactive tooling.

Config/contract docshook_backpressure marked reserved/no-op (dispatch is synchronous); journal_depth documented as load-bearing for reorg rollback; StorageBatchFetchFn one-tuple-per-slot contract documented; "scaffold" comments on the fully-implemented Resync/Reorg/Error reports reworded; transport-neutral pending-tx Unsupported message.

Code — best-effort install of rustls' ring CryptoProvider at AlloySubscriber init (avoids a wss:// "no process-level CryptoProvider" panic), with a Cargo comment explaining the rustls dep.

Tests — added the positive InputSource::Backfill assertion (the existing test only covered dedup suppression). Remaining reactive integration-coverage gaps (subscriber→runtime composition, block-header ingest, Decoded report, EventDecoderHandler, custom pending-tx routing) are tracked as honest follow-ups in KNOWN_ISSUES.

Review verdict

No soundness blockers. The reactive runtime's !Send discipline is correct, reorg recovery is pinned by state-equivalence tests, and the README's WS claims match the code. Findings were doc-accuracy/coverage/hygiene, addressed above.

🤖 Generated with Claude Code

KaiCode2 and others added 6 commits June 26, 2026 17:16
Final pre-public-release pass closing the gaps surfaced by the readiness
review. No behavioral regressions; the full CI gate (fmt, clippy -D warnings,
tests, doctests, cargo doc -D warnings, cargo package) stays green.

Engine / API
- chain_id is now configurable instead of hard-defaulting to Arbitrum (42161).
  Add `EvmCacheBuilder::chain_id` (recommended) and `EvmCache::set_chain_id`;
  when unset, infer from the provider via `eth_chainId` and fall back to 1
  (Ethereum mainnet). The inference also upgrades the bare `new`/`at_block`
  constructors. Resolution order: explicit builder value > disk CacheConfig >
  inferred > 1. (Breaking: the in-memory default changed from 42161 to inferred/1.)
- events: `ingest_logs` now tracks `skipped_accounts` so a third-party decoder
  emitting cold `StateUpdate::Account` patches stays visible to reorg purge and
  freshness, matching the "every category" contract.

Documentation accuracy
- Narrow the freshness `Validation::Confirmed`/`Corrected` docs: reconcile covers
  volatile storage slots only, not account balance/nonce/code. Record the scope
  in KNOWN_ISSUES.
- create3: relabel the factory as the ZeframLou/Solmate `CREATE3Factory`
  (LiFi-deployed) and disclaim that it is NOT pcaversaccio's CreateX.
- access_list: drop the AMM (V2/V3 slot-selection) framing from the module and
  struct docs; the builder applies no per-entry selection.
- Fix the StateDiff skip-accessor docs (all four skip categories), the cold
  definition (NotExisting overlay accounts), the cancellation/`# Panics`/empty
  `token_deltas` notes on the freshness optimistic loop, the `load_binary_state`
  read-error logging, and the overlay `block_hash`/ZERO behavior. Add KNOWN_ISSUES
  entries for BLOCKHASH-zero, unbounded `derived_slots`, deep-reorg under-purge,
  and >= 2^255 transfer magnitude.
- Remove the never-shipped `SimulationErrorKind` deprecated alias.

Benchmarks / packaging / community
- Add a README "## Performance" section with measured COW-vs-deep-clone
  `create_snapshot` and overlay-reuse numbers, methodology, and reproduction.
- Cargo.toml: exclude the internal phase specs and CI workflow from the package.
- Add SECURITY.md and a dated CHANGELOG 0.1.0 section.

Tests
- Offline Multicall3 `aggregate3` coverage (input order + allowFailure) by etching
  the real Multicall3 runtime (new fixture), and a `TxConfig.access_list` EIP-2929
  gas-accounting test. New `tests/builder_chain_id.rs` pins the chain_id order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The README "Performance" section led with a copy-on-write `create_snapshot`
vs `create_snapshot_deep_clone` table — an internal implementation A/B a
first-time reader never chooses between. Replace it with the outcomes a searcher
actually cares about, each measured against the fork-per-candidate loop they'd
otherwise write.

Four pillars, two of them exact CI-pinned integer counts:
- **Data-fetch minimization (headline).** New `examples/fetch_minimization_counted.rs`
  and `tests/fetch_minimization.rs`: 500 candidates over a shared 8-slot hot set
  fetch 8 slots once (zero during fan-out) vs 4,000 fork-per-candidate — ~500x
  fewer RPC reads, a deterministic machine-independent count.
- **Candidate-fan-out throughput.** New `benches/fanout.rs`: snapshot-once +
  overlay-per-candidate vs a full independent fork per candidate; per-candidate
  cost falls as N grows (~545x at N=128 over a 32k-slot fork).
- **Reactive sync.** `tests/event_pipeline.rs` pins that `ingest_logs` keeps hot
  slots fresh with zero RPC fetches/block; `examples/reactive_cache.rs` prints it
  (0 during ingest, sampled reconcile as the honesty backstop).
- **Optimistic latency-hiding.** Promote the existing `benches/freshness.rs`
  latency arms (time-to-result vs fetch-then-sim) in the README, labeled with the
  modeled 50ms delay.

Honesty guardrails: both shared-hot-set (~Nx) and disjoint (1x, no win) cases are
stated; wall-clock ratios are labeled machine-dependent and separated from the
exact integer counts; the injected 50ms is called out as modeled, not measured.

The internal COW-vs-deep-clone cost model moves to `docs/INTERNALS.md` (the
`simulation` bench keeps it as a regression guard). `benches/fanout.rs` is
registered in Cargo.toml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An adversarial review of the benchmark reframe flagged a framing gap: the
candidate-throughput baseline (`fork_per_candidate`) is `create_snapshot_deep_clone`,
an in-memory deep copy that does NO fetching — so the ~545× throughput speedup is
snapshot-construction/isolation cost, not RPC avoidance. The "fair baseline" box
implied the baseline cold-fetches, conflating the throughput win (②) with the
separate fetch-count win (①).

Disambiguate in the README Performance section: ① measures the fetch cost (a cold
cache per candidate re-fetches), ② measures the isolation/CPU cost (a full
independent clone per candidate, no RPC) — the two are separate and not
double-counted. All measured numbers are unchanged and verified accurate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Visuals for the value-prop performance story:
- assets/fetch_amplification.svg — the headline: fetches stay flat at 8 while
  fork-per-candidate grows linearly to 4,000 over 500 candidates (~500x).
- assets/fanout_throughput.svg — per-candidate cost (log scale) falls 41→4 µs as
  N grows while fork-per-candidate stays flat near 2.1 ms (~545x at N=128).
  Both are self-contained dark-card SVGs (no external CSS) so they render on
  either GitHub theme; embedded via absolute raw-main URLs so they also resolve
  on crates.io after merge.
- Mermaid state-stack/control-plane flowchart replacing the ASCII diagram in
  "Core concepts" (lib.rs keeps the ASCII for docs.rs), plus a sequence diagram
  of the optimistic verify-and-rerun loop showing time-to-result decoupled from
  RPC validation.

Numbers match the measured benchmarks already cited in the Performance section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… plainly

A red-team of the benchmark baselines (steelmanning what a competent revm /
foundry-fork-db user actually writes) found the headline multipliers were beating
a strawman, not a real peer:
- ~500x fewer fetches: a shared foundry-fork-db SharedBackend caches + dedups, so
  it also fetches each hot slot once within a block (its cache hit path is
  backend.rs:204-242). Within-block ratio is ~1x, not 500x.
- ~545x throughput: the baseline (create_snapshot_deep_clone per candidate) is an
  O(total-state) copy nobody writes; checkpoint/revert isolation (the crate's own
  primitive) is O(touched), so single-threaded the gap is ~1x.
- ~3,800x latency: ~99.97% of it is the injected 50ms sleep the baseline elects to
  pay; a competent loop doesn't block on a fetch before acting.

I also re-measured the parallelism I expected to be the real win: it is only ~1.2x
on these micro-sims (revm is allocation-bound per call, so it contends rather than
scaling with cores) — so I do not headline a core-count multiplier either.

Rewrites the README "Performance" section to say all this plainly (a candor table
showing ~1x where it is ~1x) and lead with what genuinely holds: cross-block
freshness (0 RPC fetches/block — foundry-fork-db's cache is not block-keyed),
point-in-time consistency, modest-but-real parallel fan-out, and the
act-then-validate control plane. benches/fanout.rs now measures sequential vs
parallel (the honest comparison), not deep-clone-per-candidate. The two charts
that visualized the inflated numbers are removed; a new cross_block_freshness.svg
visualizes the one defensible quantitative win. The fetch example prints the
shared-backend caveat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Second readiness pass, now over the combined main (post-#14, which added the
reactive runtime, cold-start, and the live AlloySubscriber). #13's release work
(chain_id builder, SECURITY.md, dated CHANGELOG, Cargo exclude, honest benchmark
reframe, doc sweep, fetch-minimization + builder tests) is carried forward via
cherry-pick; this commit closes the new-surface findings from the rerun review:

Doc accuracy (the merge left stale claims):
- README "Maturity" note: was "live subscription driving remains consumer-provided"
  while the AlloySubscriber ships — rewritten to reflect the default-enabled live
  WS subscriber + cold-start, with the honest remaining caveats.
- KNOWN_ISSUES "event-driven sync" entry updated the same way; added a note on the
  bounded reconnect dedup window and the partial reactive integration-test coverage.
- Documented cold_start (absent everywhere): README bullet, lib.rs module map,
  CHANGELOG entry (incl. the serial-account / first-failure-abort cost).
- Repositioned "Why it exists" toward the out-of-the-box reactive tooling.

Config/contract doc fixes:
- hook_backpressure: documented as reserved/no-op (dispatch is synchronous).
- journal_depth: documented as load-bearing for reorg rollback (not "reserved").
- StorageBatchFetchFn: documented the one-tuple-per-requested-slot contract that
  verify_slots / cold-start rely on.
- "scaffold" doc comments on the fully-implemented Resync/Reorg/Error reports
  reworded to describe what they actually report.
- Pending-tx Unsupported message: made transport-neutral (was "polling mode").

Code:
- reactive-ws: best-effort install of rustls' ring CryptoProvider at AlloySubscriber
  init (avoids a wss:// "no process-level CryptoProvider" panic), with a Cargo
  comment explaining why the rustls dep exists.

Tests:
- Added a positive InputSource::Backfill assertion (the dedup test only covered
  the suppression side); pins the README's backfill-marking claim.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KaiCode2 and others added 9 commits June 29, 2026 13:38
- reactive: correct the `journal_depth` and `ReorgReport` docs — a reorg deeper
  than `journal_depth` (or any reorg when `journal_depth = 0`) recovers only the
  resident span; aged-out blocks are neither rolled back nor purged and the
  freshness loop is the backstop. Emit a `tracing::warn!` when a reorg references
  a block no longer in the journal so the under-recovery is observable, not silent.
- docs: add a KNOWN_ISSUES entry for the journal_depth recovery horizon; refresh
  ROADMAP to reflect the shipped reactive runtime + AlloySubscriber + cold_start
  (new Phase 6 section, corrected the stale "consumer-provided WS/reorg" claims,
  reframed remaining-work toward 1.0).
- examples: add the offline `reactive_runtime` example (handler -> StateUpdate ->
  apply with 0 RPC, then journaled reorg rollback); list it and
  fetch_minimization_counted in the README example tables.
- benchmarks: the README fan-out figure now names the committed 64–1,024 sweep
  instead of an unrun 4,096-candidate batch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- lib.rs: hoist the primary entry points to the crate root for discoverability —
  cache::{EvmCache, EvmCacheBuilder, EvmSnapshot, EvmOverlay, TxConfig,
  CallSimulationResult} and (cfg reactive) reactive::{ReactiveRuntime,
  ReactiveHandler, ReactiveConfig}. Purely additive; the module paths still work.
- examples/cold_start.rs: offline discover-then-verify working-set warming over
  the MockERC20 fixture — a ColdStartPlanner discovers the slots a balanceOf call
  touches, then verifies + injects them via run_cold_start, printing the report.
- cold_start: add a module-level doctest (planner + run_cold_start call shape) and
  a runnable ColdStartPlan doctest.
- README: list the cold_start example in the offline table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add `CallTracer`, a revm `Inspector` that reconstructs the call-frame tree
(`CallTrace`/`CallKind`/`CallStatus`) of a simulation via the
call/call_end/create/create_end hooks (no opcode/step or SLOAD/SSTORE
tracing). Add `InspectorStack<A, B>`, a composing inspector that fans out
every hook to two inner inspectors. Add the public, inspector-generic
`EvmOverlay::call_raw_with_inspector`, which attaches any `Inspector`
(honoring `TxConfig`/`commit`) and returns the raw `ExecutionResult`
(revert/halt is `Ok`, not `Err`) plus the inspector. New types live in
`src/tracing.rs` and are re-exported at the crate root.

Makes the manager-authored acceptance tests in `tests/call_tracer.rs` pass
(C1 single frame, C2 nested subcall, C3 revert attribution, C4 stack
composition).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an ordered multi-transaction bundle execution primitive over cumulative
overlay state, with a revert policy and miner/coinbase payment accounting.

- New `bundle` module: BundleTx, BundleOptions, RevertPolicy (Atomic /
  AllowReverts), GasAccounting (Mainnet / Raw), TxOutcome, BundleResult;
  re-exported at the crate root.
- `EvmOverlay::simulate_bundle`: one outer + per-tx inner checkpoints on a
  single overlay/EVM (no per-tx rebuild). Atomic aborts roll the whole bundle
  back; AllowReverts roll back only whitelisted-index reverts and continue.
  Mainnet accounting subtracts the burned base fee (Σ gas_used×basefee over the
  committed txs) from the beneficiary delta since the simulator disables the
  base fee and revm credits the full gas price; Raw returns the bare delta. All
  saturating.
- `EvmCache::simulate_bundle`: snapshots internally and runs on a transient
  overlay; never mutates the cache.
- `EvmCache::set_basefee(U256)`: installs the block base fee into the next
  snapshot so offline caches can exercise Mainnet accounting.

Tests: manager-authored tests/bundle_simulation.rs (AB1-AB6) pass verbatim,
plus agent-authored tests/bundle_simulation_extra.rs (empty bundle, AllowReverts
atomic-fallback, commit=false isolation, cache non-mutation) and bundle.rs unit
tests for the type defaults.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- examples/bundle_simulation.rs and examples/call_tracer.rs: runnable offline
  demos of simulate_bundle (cumulative state, revert policy, coinbase payment) and
  CallTracer/InspectorStack (nested call-frame tree + transfer capture in one pass).
- fix: drop GasAccounting (Mainnet/Raw). revm's reward_beneficiary already credits
  only the priority fee and burns the base fee in-EVM (EIP-1559), so the beneficiary
  delta IS the honest miner payment; the Mainnet mode was subtracting the base fee a
  second time (under-reporting whenever basefee > 0). coinbase_payment is now the
  bare delta. AB4/AB5 + agent extras + the example updated to the correct semantics.
- docs: ROADMAP Phase 7 (bundle sim + tracer shipped); README example rows;
  KNOWN_ISSUES note on AllowReverts reverted-tx gas; CHANGELOG + spec correction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a 'bundle' entry to the lib.rs module map (it had 'tracing' but not
'bundle') and 'Bundle simulation' + 'Call-frame tracing' bullets to the README
'What it provides today' list, so the Phase 6 capabilities are discoverable from
the crate-level docs, not just the example table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@KaiCode2
KaiCode2 merged commit 1e08dc3 into main Jun 30, 2026
2 checks passed
@KaiCode2
KaiCode2 deleted the release-readiness-v2 branch June 30, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant