Skip to content

Cleanup MIP8 migration code: assume single page-encoded timeline in runloop_monad and statesync - #2551

Open
Chen-Yifan wants to merge 2 commits into
mainfrom
vicky/single-timeline-page-encoded
Open

Chen-Yifan wants to merge 2 commits into
mainfrom
vicky/single-timeline-page-encoded

Conversation

@Chen-Yifan

@Chen-Yifan Chen-Yifan commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

runloop_monad and the statesync client and server now require a single page-encoded db and assert it on entry, instead of carrying an optional secondary timeline and branching on encoding.

  • runloop_monad: drop the secondary_db parameter and the for_each_db dual writes; assert db.is_page_encoded() and no active secondary.
  • statesync client: drop the secondary db and slot storage builder; commit() is page-only, finalize() rolls forward one db. Drop the chain_config parameter from the C ABI and the Rust StateSyncCtx, since the target revision no longer selects an encoding.
  • statesync server: always expand page leaves into slot upserts; the server context asserts a page-encoded TrieDb.
  • runloop C library: open a page-encoded primary only; replace the primary/secondary state root getters with monad_runloop_get_state_root.
  • tests: collapse the pre/post-mip8 typed fixture into one page-encoded fixture and update the hardcoded state roots.

runloop_monad_ethblocks keeps its secondary_db for pre-mip8 replay.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It changes core execution/statesync invariants and a C ABI surface area, so a final human review (plus green CI) is needed to confidently validate correctness and compatibility.

Pull request overview

This PR finishes the “single page-encoded timeline” assumption across runloop_monad and statesync by removing the remaining dual-db/dual-timeline branching and asserting invariants at entry points. It also updates the runloop C ABI and test/fuzz coverage to match the new page-only behavior.

Changes:

  • runloop_monad: drop the secondary DB parameter and remove dual-write for_each_db paths; assert page-encoding + no active secondary timeline.
  • statesync: client/server now operate page-only (server expands page leaves into slot upserts; client finalization requires MIP-8-active target revision) and remove secondary timeline plumbing.
  • tests/fuzz: collapse fixtures to page-only and update hardcoded expected roots; fuzz only the page-encoded path.
File summaries
File Description
cmd/monad/main.cpp Updates runloop/statesync wiring and comments to reflect page-only runloop_monad and page-required statesync server.
category/execution/runloop/runloop_monad.hpp Removes the secondary_db parameter from runloop_monad API and documents the page-only invariant.
category/execution/runloop/runloop_monad.cpp Removes dual-db writes/metadata updates, hardwires commit_block(..., secondary_db=nullptr), and adds entry asserts for page-only + single-timeline.
category/execution/runloop/runloop_interface_monad.h Replaces primary/secondary state-root getters with a single monad_runloop_get_state_root API.
category/execution/runloop/runloop_interface_monad.cpp Opens a page-encoded primary only, removes secondary timeline setup/usage, and implements the unified state-root getter.
category/statesync/statesync_server_context.cpp Asserts the server context is constructed with a page-encoded TrieDb.
category/statesync/statesync_server.cpp Removes slot-vs-page branching; always expands decoded storage pages into slot-format upserts on the wire.
category/statesync/statesync_client_context.hpp Removes secondary timeline members and documents the page-only + MIP-8 target requirement.
category/statesync/statesync_client_context.cpp Enforces page-only + no-secondary invariant and simplifies commit/roll-forward logic to single-timeline.
category/statesync/statesync_client.cpp Simplifies finalize flow to single DB, and asserts target revision is MIP-8 active before comparing state roots.
category/statesync/test/test_statesync.cpp Collapses pre/post-MIP8 fixture into a single page-only fixture; updates expected state roots and removes dual-db helpers.
category/statesync/test/fuzz_statesync.cpp Removes slot-vs-page fuzzing split and fuzzes only the page-encoded path (DEVNET / MIP-8 active).
Review details
  • Files reviewed: 12/12 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Chen-Yifan
Chen-Yifan force-pushed the vicky/single-timeline-page-encoded branch from 3dce9dc to 89f4566 Compare September 10, 2026 18:18
…unloop_monad and statesync

runloop_monad and the statesync client and server now require a single
page-encoded db and assert it on entry, instead of carrying an optional
secondary timeline and branching on encoding.

- runloop_monad: drop the secondary_db parameter and the for_each_db
  dual writes; assert db.is_page_encoded() and no active secondary.
- statesync client: drop the secondary db and slot storage builder;
  commit() is page-only, finalize() rolls forward one db. Drop the
  chain_config parameter from the C ABI and the Rust StateSyncCtx, since
  the target revision no longer selects an encoding.
- statesync server: always expand page leaves into slot upserts; the
  server context asserts a page-encoded TrieDb.
- runloop C library: open a page-encoded primary only; replace the
  primary/secondary state root getters with monad_runloop_get_state_root.
- tests: collapse the pre/post-mip8 typed fixture into one page-encoded
  fixture, drop chain and timestamp plumbing, update hardcoded state roots.

runloop_monad_ethblocks keeps its secondary_db for pre-mip8 replay.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Chen-Yifan
Chen-Yifan force-pushed the vicky/single-timeline-page-encoded branch from 89f4566 to 739e608 Compare September 10, 2026 18:53
@Chen-Yifan
Chen-Yifan marked this pull request as ready for review September 10, 2026 18:58
Comment thread category/execution/runloop/runloop_interface_monad.cpp Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the single-timeline/page-encoded cleanup across runloop_monad, statesync client/server, the C ABI, and the tests.

The overall direction is sound and the diff is internally consistent: runloop_monad and the statesync client/server now assert their preconditions instead of branching on encoding, the removed chain_config parameter is cleaned out of the C header, the Rust StateSyncCtx, and all in-repo callers, runloop_monad_ethblocks retains its dual-db path as described, and the identifier/temporal-comment sweeps come up clean (no stale references to secondary_tdb, for_each_db in the touched paths, or the removed C functions). The intrusive UpdateList lifetime discipline in the flattened commit() is preserved (deques outlive the upsert), and main.cpp still opens the db via the kind-driven ctor, so the new asserts in runloop_monad genuinely reject non-migrated dbs on the production path.

One blocking issue (inline): MonadRunloopImpl opens the primary with the machine-taking mpt::Db ctor, which force-stamps the persisted state_machine_kind to monad. That makes the new is_page_encoded() assert a tautology in this entry point and mutates a legacy slot-encoded db's metadata on open, which can make the db unreadable/corrupt for subsequent kind-driven opens. Switching to the kind-driven mpt::Db{OnDiskDbConfig} ctor (as main.cpp and the statesync client do) resolves it.

Verdict: NEEDS CHANGES

🤖 Generated with Claude Code

MonadRunloopImpl used the Db ctor that takes a StateMachine, which stamps
the machine's kind into the pool metadata on every open and would relabel
an existing pool of the other encoding. Use the kind-reading ctor instead
and register the state machine factories in monad_runloop_new, so the
encoding always comes from monad-mpt --create --state-machine.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Chen-Yifan

Copy link
Copy Markdown
Contributor Author

@claude re-review please

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after 2027be8, which addresses the one blocking finding from the previous review.

The fix is correct: MonadRunloopImpl now opens the primary with the kind-driven mpt::Db{OnDiskDbConfig} ctor (same as cmd/monad/main.cpp and the statesync client), so the persisted state_machine_kind is read rather than overwritten, and MONAD_ASSERT(triedb.is_page_encoded()) genuinely rejects a non-migrated db instead of being a tautology. The factory registration in monad_runloop_new happens before the impl is constructed (the only construction path for MonadRunloopImpl), register_state_machine tolerates repeat registration, and the updated header comment documents the new precondition on db_path. The remaining machine-taking mpt::Db ctor uses in the diff are all test-fixture creation with .append = false, where stamping the kind is the intent.

No new findings. One hygiene note: the PR is now two commits; per the repo convention, squash before merging.

Verdict: CORRECT

🤖 Generated with Claude Code

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