Skip to content

feat: consolidate Tsuki migration onto inbound-only clean Reth (f851224e + component 18adb117) - #20

Merged
dghelm merged 24 commits into
feat/tsuki-hardfork-2from
codex/pr-12-runtime-build-config
Aug 12, 2026
Merged

feat: consolidate Tsuki migration onto inbound-only clean Reth (f851224e + component 18adb117)#20
dghelm merged 24 commits into
feat/tsuki-hardfork-2from
codex/pr-12-runtime-build-config

Conversation

@dghelm

@dghelm dghelm commented Aug 6, 2026

Copy link
Copy Markdown

Summary

Single consolidation PR landing the Tsuki dependency/runtime migration into feat/tsuki-hardfork-2 (Tsuki staging). Supersedes #12 and #17; does not replay #19 wholesale. Per the PR-governance decision memo (run 20260812-013410-open-pr-cleanup).

  • Base: feat/tsuki-hardfork-2  •  Head: d02d669a1303561e233b4571ae8f542180b9eee0 (= reviewed de7dd204 + a codespell comment fix + the zepter feature-propagation fixes; no runtime behavior change)
  • Adopts PR refactor(node): remove composite RPC handle #17's standard RpcHandle / rollup-owned orchestrator model (no composite handle): add_ons_handle returns Reth's standard RpcHandle, and the rollup manager handle is downstream-owned and fixture-accessible.

Dependency tuple (coordinated, atomic)

Layer Source
Clean Reth (Reth PR #1, inbound/downloaded-header-only hook + approved RocksDB PR #2 5235056 by ancestry) DogeOS69/reth@f851224ee9aaf21c76a14e844cbd12d9756f5f3b — 102 pkgs
Component (repin onto f851224e; restores two-arg start_network) DogeOS69/dogeos-reth@18adb1176636b4f3bdc828a15c4622f60d2e5ec7 — 13 pkgs
REVM (unchanged) DogeOS69/dogeos-revm@dcf087684f255131c96c0d20f3291eef9198e990
Official Reth dev pin (unchanged) paradigmxyz/reth@b25f32a977b489f9b84254c7811a2a5a25a81369 — 5 pkgs

Cargo.lock regenerated with zero package/version/edge churn beyond the source repins. The source guard is repinned to the two new canonical sources with negative fixtures that reject the retired ae160090 (PR #3) and c5198f7 (old component) sources.

Legacy geth compatibility (one-way, temporary)

  • Inbound downloaded-header transform (strip the 65-byte signature → canonicalize) retained behind --network.legacy-geth-header-transform (gated on chain identity, not the signer). Signer verification is observability-only; header acceptance is unchanged. The flag defaults off. The current resolver rejects NamedChain::Scroll, but whether built-in DogeOS Mainnet (0xff) is classified that way is not proven. Enforcing and proving None on Mainnet remains a PR feat: Tsuki hardfork — migrate to DogeOS reth/revm forks #5 production-qualification requirement.
  • Outbound served-header transform removed (obsolete under the accepted one-way topology and the cleaned Reth API). The now-dead inbound signature persistence + the network builder's DB field are removed; the block-signature schema/migration is untouched.
  • Bidirectional geth↔Reth migration tests/scripts retired and replaced with the one-way Testnet crossover contract (geth freezes → Reth reaches the frozen final head → Reth sequences; no geth rollback).

Verification (local, from reviewed head de7dd204; head d02d669 adds only a codespell comment fix and the zepter feature-propagation fixes — zepter run check passes locally)

  • Locked fetch + cargo metadata --locked --offline; source guard + 11 negative fixtures; nightly fmt --check: pass.
  • cargo check / clippy -D warnings / build (-p rollup-node --bin rollup-node --locked): pass; both --help smokes exit 0 (new flag present, default false).
  • scroll-network --lib 3/3; scroll-derivation-pipeline --lib 6/6.
  • reth-e2e-test-utils now compiles — the former PR [DOG-396] Publish DogeOS rollup-node images from branches #3 RpcHandleProvider E0405/E0277 blocker is eliminated by dropping the composite-handle layer.
  • Production Dockerfile and compose Dockerfile.test images build and smoke-test (--help).

Known constraints (accepted for staging; block production qualification)

  • Tempo/Alloy E0119 (tempo-alloy, via the anvil dev-dependency) still blocks node/sequencer e2e and make test-docker compilation — reported as blocked, not passed. Separate repair.

  • Issue fix: handle missing payload ID while Reth is syncing from a peer #16 — two distinct Engine-API failure modes, both accepted staging risks and production-qualification blockers:

    • Original: a valid SYNCING forkchoice response with no payload_id is unwrapped and panics.
    • Reproduced: a 60-second Engine timeout during persistence backpressure returned an error, discarded batch 1180, and caused 5,333 subsequent InvalidBatchReorg failures (it did not panic).

    The fix must requeue the pending batch, retry without busy-looping, stay shutdown-responsive, and record no batch outcome until the full action set succeeds.

  • Exact-final-head image + follower/sequencer deployment qualification (frozen-geth-head crossover drill; Mainnet-None proof) remain deployment gates.

  • rust-analyzer flags a Scroll: RecommendedFillers bound in tests/src/docker_compose.rs (unmodified here) that cargo cannot confirm behind the Tempo blocker — flagged for post-Tempo re-check.

Dependency-cascade note

DogeOS69/reth PRs #1/#2 remain open and unmerged; this PR temporarily pins the exact reachable PR #1 head f851224e. If clean Reth is later finalized at a different SHA, repeat the cascade: dogeos-reth repin → rollup-node repin → final image and qualification.

🤖 Generated with Claude Code

lightsing and others added 22 commits August 5, 2026 00:06
Replace the two remaining inner.add_ons_handle.rollup_manager_handle
reads in the node e2e tests with the fixture-owned handle, import
DogeosChainSpecParser from this crate instead of the removed
reth-scroll-cli, and migrate the first two sequencer e2e tests from
reth_scroll_node::test_utils::setup to the setup_engine fixture used by
the rest of the file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commit 98984de dropped the tokio_unstable rustflags while keeping the
ENABLE_CONSOLE_SUBSCRIBER runtime option, so a normally built binary
panicked at startup whenever the option was enabled. Restore the build
cfg so console_subscriber::init() works again.

The clean DogeOS Reth line (ae16009) compiles a tokio task-dump debug
endpoint whenever tokio_unstable is set, and tokio only provides
Handle::dump with its taskdump feature; enable it workspace-wide so the
graph builds. This activates tokio's optional, already-locked backtrace
dependency, adding one dependency edge to Cargo.lock. No package
revisions change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The previous guard exact-checked three anchor packages, dropped
null/path sources before inspecting DogeOS packages, matched retired
forks case-sensitively with fixed .git spellings, and accepted every
official-Reth revision. Rewrite it around a factored jq predicate that
validates every dogeos-*, reth-*, and revm-scroll package, pins each
guarded repository to its exact reviewed source, rejects null/path
sources for guarded families, and normalizes URL spelling before
matching retired forks.

The entry point still runs cargo metadata --locked --offline by
default but now accepts a metadata file, letting
verify_reth_sources_test.sh prove the negative cases (null/path
components, duplicate stale sources, alternate retired-fork spellings,
wrong REVM and official-Reth revisions) without touching Cargo.lock.
The fixture run is wired into the lint workflow next to the positive
check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per review, globally enabling tokio_unstable plus the taskdump feature
turned Reth's unauthenticated /debug/tokio/dump metrics route into a
live, expensive endpoint reachable in the repository's documented
deployment shape, and constrained compilation to Linux aarch64/x86.
Revert the build cfg, the taskdump feature, and its lockfile edge, and
remove the ENABLE_CONSOLE_SUBSCRIBER option together with the
console-subscriber dependency surface. Console support can return once
DogeOS Reth independently gates the task-dump route.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rewrite can_gossip_over_eth_wire through the fixture and orchestrator
event surface: with scroll-wire disabled, deterministically build a
block and assert the follower receives it over eth-wire, extends its
chain, and imports the identical block. The removed
EthWireProvider/eth_wire_block_listener() APIs do not exist at clean
Reth ae16009.

Replace the five removed BlockDataHint::none() calls in the derivation
pipeline tests with BlockDataHint::default(), the pinned type's empty
representation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The workspace requires Rust 1.93 but the integration-test image still
built with 1.91. Bump the builder image, pin cargo-chef to 0.1.71 as in
the main Dockerfile, and fetch git dependencies with the CLI for parity
with the main build. Token plumbing is intentionally not carried over:
the pinned dependency repositories are public.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reth's block-import callback cloned every remote block announcement
into an unbounded queue ahead of the serial rollup consumer, giving a
connected peer an avoidable remote memory-exhaustion path. Replace the
bridge with a bounded channel of 1000 announcements, matching the bound
the retired listener API enforced. Because BlockImport::on_new_block is
synchronous, the bridge now uses try_send: announcements that meet a
full queue are dropped with a rate-limited warning (at most one per
five seconds, with a dropped-count), and a closed queue drops silently
at trace level. Peer attribution and the signed-header transforms are
unchanged. Unit tests cover normal delivery, full-queue drops with drop
accounting, and a dropped receiver.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address two non-blocking review notes on the bounded bridge. Use
Sender::try_reserve to acquire a slot before cloning the announced
block, so a full queue no longer pays for a clone it would immediately
drop. Clarify in the drop warning that the dropped count aggregates
announcements across all peers and the logged peer id is only the most
recent sender (now `latest_peer`), not the sole source.

No behavioral change to delivery, drop, or closed-queue handling; the
existing bridge unit tests still pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move both coordinated provider families atomically to the reviewed
inbound/downloaded-header-only stack:

- 36 DogeOS69/reth entries: ae160090 -> f851224e (Reth PR #1 cleaned to a
  downloaded-header hook plus the approved RocksDB durability layer;
  drops PR #3's composite RPC handle layer);
- 11 DogeOS69/dogeos-reth component entries: c5198f7 -> 18adb117 (the
  provider repin that itself pins f851224e).

Cargo.lock regenerated through Cargo: 102 clean-Reth packages repin to
f851224e and 13 component packages to 18adb117, with no package,
version, or dependency-edge churn. revm-scroll (dcf0876), the official
paradigmxyz/reth dev pin (b25f32a), and all registry crates are
unchanged.

Point the source guard at the two new canonical sources and convert two
negative fixtures to inject the exact retired ae160090 and c5198f7
sources, proving the guard rejects both beside the good graph.

The networking API adaptation to the two-argument start_network and the
optional downloaded-header hook follows in a separate commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reth f851224e scopes the network header transform to downloaded headers
and restores the two-argument start_network. Adapt the rollup network
builder accordingly:

- set NetworkConfig.header_transform to the new Option hook and call the
  two-argument ctx.start_network(network, pool);
- remove the outbound ScrollRequestHeaderTransform (served-response
  transform) and its now-dead signature-serving path;
- since the inbound transform's insert_signatures persistence fed only
  that removed served path, drop the persistence, the network builder's
  Database field/constructor argument, and the now-unused DB imports
  (the block-signature schema/migration is left intact).

Gate the inbound transform behind an explicit temporary control:

- add --network.legacy-geth-header-transform (default false), threaded
  through RollupNodeNetworkArgs and ScrollNetworkBuilder;
- resolve_header_transform installs the hook only when enabled and
  rejects startup on DogeOS Mainnet (NamedChain::Scroll); the decision is
  gated on chain identity, not the signer, since Mainnet and Chikyu both
  configure one. With the flag off the hook is None (baseline path).

The inbound transform still canonicalizes downloaded legacy headers by
stripping the extra_data signature and still verifies the signer, now
explicitly documented as observability-only: it never drops or rejects a
header, exactly as before (the prior signer check only gated the removed
persistence). Live signed NewBlock gossip in the network manager and the
standard RpcHandle add-ons model are unchanged.

Focused adapter tests cover canonicalization with order/cardinality
preservation, the invalid/unauthorized-signature (header-retained)
result, and the enabled-Testnet / rejected-Mainnet / disabled hook
resolution. Their execution shares the known Tempo/Alloy E0119
dev-dependency blocker (anvil -> foundry-primitives -> tempo-alloy).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Under the approved Tsuki Testnet contract the geth-to-Reth transition is
one-directional: geth is retired after the cutover with no rollback or
recovery path. Retire the bidirectional migration artifacts accordingly.

Tests:
- rewrite docker_test_migrate_sequencer from a geth<->Reth alternation
  loop to a single one-way handoff: geth sequences, is frozen at its
  final head, all nodes are proven to reach that frozen head, then Reth
  sequences for the remainder;
- rewrite docker_test_heterogeneous_client_sync_and_sequencer_handoff to
  drop the network-partition step that made geth catch up from Reth and
  the step that returned production to geth, keeping the geth->Reth
  cross-client sync, the one-way handoff, and the Reth follower restart
  recovery.

Scripts/docs:
- remove switch-to-l2geth.sh and revert-l2geth-to-block.sh (geth
  rollback paths) and migrate-sequencer.sh (bidirectional driver);
- rewrite sequencer-migration/README.md to the one-way runbook and point
  the migration Dockerfile at the remaining forward scripts.

These docker tests are gated behind Docker and share the known
Tempo/Alloy E0119 dev-dependency blocker, so they are not executed here;
rustfmt validates their syntax.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dghelm dghelm changed the title feat: expose persistence tuning and harden builds feat: consolidate Tsuki migration onto inbound-only clean Reth (f851224e + component 18adb117) Aug 12, 2026
@dghelm
dghelm changed the base branch from codex/reth2-components to feat/tsuki-hardfork-2 August 12, 2026 20:24
@dghelm
dghelm marked this pull request as ready for review August 12, 2026 20:33
dghelm and others added 2 commits August 12, 2026 15:45
Replace "unparseable" (flagged by codespell as a misspelling of
"unparsable") with a length-based description in the inbound-transform
adapter test; no behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Reth 2 component migration left two feature propagations un-updated,
which zepter flags (the target base's zepter check is green):

- rollup-node-primitives `arbitrary` -> `dogeos-reth-primitives/arbitrary`
  (Cargo.lock gains the required `arbitrary` edge under
  `dogeos-reth-primitives`);
- scroll-network `serde` -> `dogeos-protocol-types/serde`.

`zepter run check` now passes. No default-feature behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dghelm
dghelm force-pushed the codex/pr-12-runtime-build-config branch from 29f9f2f to d02d669 Compare August 12, 2026 21:17
@dghelm
dghelm merged commit 1453ca4 into feat/tsuki-hardfork-2 Aug 12, 2026
7 of 15 checks passed
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.

2 participants