Skip to content

test(fc): store from anchor rejects mismatched state root#678

Merged
tcoratger merged 1 commit intoleanEthereum:mainfrom
mananuf:test/fc-store-from-anchor-rejects-mismatched-state-root
Apr 26, 2026
Merged

test(fc): store from anchor rejects mismatched state root#678
tcoratger merged 1 commit intoleanEthereum:mainfrom
mananuf:test/fc-store-from-anchor-rejects-mismatched-state-root

Conversation

@mananuf
Copy link
Copy Markdown
Contributor

@mananuf mananuf commented Apr 23, 2026

🗒️ Description

Adds a fork choice filler asserting that Store.from_anchor aborts when the anchor block's state_root disagrees with hash_tree_root(anchor_state). This is a safety precondition every client must enforce: an anchor pair where the block and state disagree on the post state would corrupt every subsequent block-root-to-state lookup.

Test

tests/consensus/devnet/fc/test_checkpoint_sync.py::test_store_from_anchor_rejects_mismatched_state_root

Builds a valid mid-chain anchor via build_anchor, overrides the anchor block's state_root with an unrelated value, and feeds the pair to the filler. The fixture verifies Store.from_anchor raises AssertionError whose message contains the exact precondition text ("Anchor block state root must match anchor state hash"), pinning the failure to the state-root check rather than any later crash.

Framework extension

Store.from_anchor runs before any step, so the existing per-step valid=False / expected_error mechanism cannot express an expected failure at initialization. Two optional fields are added to ForkChoiceTest to fill this gap:

  • anchor_valid: bool = True
  • expected_anchor_error: str | None = None

When anchor_valid=False, the fixture:

  1. Asserts steps == [] (no step can run if init aborts).
  2. Skips the validator pubkey sync that would otherwise silently overwrite the anchor block's state_root to match the state.
  3. Wraps Store.from_anchor in try/except and verifies the raised exception's message contains expected_anchor_error.

Defaults preserve existing behaviour: all 545 consensus fixtures regenerate byte-identical.

Serialised as anchorValid / expectedAnchorError via CamelModel. Clients consuming fixtures branch on anchorValid=false and verify their equivalent Store.from_anchor rejects the input.

🔗 Related Issues or PRs

Closes #570

✅ Checklist

  • Ran tox checks to avoid unnecessary CI fails:
    uvx tox -e all-checks
  • Considered adding appropriate tests for the changes.
  • Considered updating the online docs in the ./docs/ directory.

Add a fork choice filler asserting that Store.from_anchor aborts when the
anchor block's state_root disagrees with hash_tree_root(anchor_state).

Extend ForkChoiceTest with two optional fields to express expected
failure at anchor initialization (which runs before any step):

- anchor_valid: bool = True
- expected_anchor_error: str | None = None

When anchor_valid is False, the fixture skips the validator pubkey sync
(which would silently overwrite the anchor block's state_root), wraps
Store.from_anchor in try/except, and verifies the raised exception's
message contains expected_anchor_error. No store is returned.

Default behavior is unchanged: anchor_valid defaults to True, and every
existing filler (545 consensus fixtures) regenerates identically.

Closes leanEthereum#570
@tcoratger tcoratger force-pushed the test/fc-store-from-anchor-rejects-mismatched-state-root branch from 6dabd0a to 1dcc76d Compare April 25, 2026 22:11
@tcoratger tcoratger merged commit 655da3c into leanEthereum:main Apr 26, 2026
13 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.

test(fc): store from anchor rejects mismatched state root

2 participants