Skip to content

Commit fc6c157

Browse files
authored
fix(consume): consume sync validation relies on FCU only (#1670)
1 parent abd7612 commit fc6c157

File tree

4 files changed

+60
-28
lines changed

4 files changed

+60
-28
lines changed

docs/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ Test fixtures for use by clients are available for each release on the [Github r
1414

1515
#### `consume`
1616

17+
- 🐞 Fix a bug with `consume sync` tests where some clients don't have JSON-RPC immediately available after syncing and can't yet serve the synced block ([#1670](https://github.com/ethereum/execution-specs/pull/1670)).
18+
1719
### 📋 Misc
1820

1921
### 🧪 Test Cases
2022

21-
- 🐞Fix BALs opcode OOG test vectors by updating the Amsterdam commit hash in specs and validating appropriately on the testing side ([#2293](https://github.com/ethereum/execution-spec-tests/pull/2293)).
22-
- ✨Fix test vector for BALs SSTORE with OOG by pointing to updated specs; add new boundary conditions cases for SSTORE w/ OOG ([#2297](https://github.com/ethereum/execution-spec-tests/pull/2297)).
23+
- 🐞 Fix BALs opcode OOG test vectors by updating the Amsterdam commit hash in specs and validating appropriately on the testing side ([#2293](https://github.com/ethereum/execution-spec-tests/pull/2293)).
24+
- Fix test vector for BALs SSTORE with OOG by pointing to updated specs; add new boundary conditions cases for SSTORE w/ OOG ([#2297](https://github.com/ethereum/execution-spec-tests/pull/2297)).
2325

2426
## [v5.3.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v5.3.0) - 2025-10-09
2527

docs/running_tests/test_formats/blockchain_test_sync.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ For each [`HiveFixture`](#hivefixture) test object in the JSON fixture file, per
4848
- Send `engine_forkchoiceUpdatedVX` pointing to the last block hash
4949

5050
4. Monitor and verify synchronization:
51-
- Wait for the sync client to reach the [`lastblockhash`](#-lastblockhash-hash)
52-
- Verify the final state root matches between both clients
53-
- If [`post`](#-post-alloc) is provided, verify the final state matches
51+
- Wait for the sync client to return `VALID` for `engine_forkchoiceUpdatedVX` with the sync block payload
52+
- If RPC is available after sync, retrieve the sync block via `eth_getBlockByHash` for [`lastblockhash`](#-lastblockhash-hash) and check the state root matches on this block for client under test and sync client
5453

5554
## Structures
5655

packages/testing/src/execution_testing/cli/pytest_commands/plugins/consume/simulators/simulator_logic/test_via_sync.py

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -503,44 +503,73 @@ def test_blockchain_via_sync(
503503
f"within timeout"
504504
)
505505

506-
logger.info("Sync verification successful!")
506+
logger.info("Sync verification successful! FCU returned VALID.")
507507

508508
# Verify the final state but give a few tries
509509
assert eth_rpc is not None, "eth_rpc is required"
510510
assert sync_eth_rpc is not None, "sync_eth_rpc is required"
511511

512-
for attempt in range(5):
512+
max_attempts = 5 # 5 attempts with 1 second wait between
513+
for attempt in range(max_attempts):
513514
try:
514515
sync_block = sync_eth_rpc.get_block_by_hash(
515516
last_valid_block_hash
516517
)
517518
client_block = eth_rpc.get_block_by_hash(last_valid_block_hash)
518519

519-
if sync_block is None or client_block is None:
520-
raise LoggedError(
521-
f"Failed to retrieve block {last_valid_block_hash} "
522-
f"on attempt {attempt + 1}"
523-
)
520+
if sync_block is not None and client_block is not None:
521+
# If we have both blocks, verify they match
522+
if sync_block["stateRoot"] != client_block["stateRoot"]:
523+
raise LoggedError(
524+
f"State root mismatch after sync. "
525+
f"Sync client: {sync_block['stateRoot']}, "
526+
f"Client under test: {client_block['stateRoot']}"
527+
)
524528

525-
if sync_block["stateRoot"] != client_block["stateRoot"]:
526-
raise LoggedError(
527-
f"State root mismatch after sync. "
528-
f"Sync client: {sync_block['stateRoot']}, "
529-
f"Client under test: {client_block['stateRoot']}"
530-
)
529+
if fixture.post_state_hash:
530+
if sync_block["stateRoot"] != str(
531+
fixture.post_state_hash
532+
):
533+
raise LoggedError(
534+
f"Final state root mismatch. "
535+
f"Expected: {fixture.post_state_hash}, "
536+
f"Got: {sync_block['stateRoot']}"
537+
)
531538

532-
if fixture.post_state_hash:
533-
if sync_block["stateRoot"] != str(fixture.post_state_hash):
534-
raise LoggedError(
535-
f"Final state root mismatch. "
536-
f"Expected: {fixture.post_state_hash}, "
537-
f"Got: {sync_block['stateRoot']}"
539+
logger.info(
540+
f"Block state verified via eth_getBlockByHash (attempt {attempt + 1}): "
541+
f"{sync_block['stateRoot']}"
542+
)
543+
break
544+
else:
545+
missing = []
546+
if sync_block is None:
547+
missing.append("sync_client")
548+
if client_block is None:
549+
missing.append("client_under_test")
550+
551+
if attempt < max_attempts - 1:
552+
logger.debug(
553+
f"Block {last_valid_block_hash} not yet available on {', '.join(missing)} "
554+
f"(attempt {attempt + 1}/{max_attempts})"
538555
)
539-
break
556+
time.sleep(1)
557+
else:
558+
# Final attempt and blocks still not available
559+
logger.debug(
560+
f"Block {last_valid_block_hash} not available via eth_getBlockByHash "
561+
f"after {max_attempts} attempts (missing from: {', '.join(missing)}). "
562+
f"This is acceptable as FCU VALID is the authoritative success signal."
563+
)
564+
except LoggedError:
565+
# Re-raise validation errors immediately with no retry
566+
raise
540567
except Exception as e:
541-
if attempt < 4:
568+
# Log other errors without failing the test
569+
logger.debug(
570+
f"Error fetching blocks for verification (attempt {attempt + 1}): {e}"
571+
)
572+
if attempt < max_attempts - 1:
542573
time.sleep(1)
543-
continue
544-
raise e
545574

546575
logger.info("Sync test completed successfully!")

packages/testing/src/execution_testing/cli/pytest_commands/plugins/consume/simulators/sync/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ def pytest_collection_modifyitems(
5555

5656
for item in items:
5757
# Auto-mark all verify_sync tests as flaky with 3 reruns
58+
# TODO: We can likely remove this as we have more stable sync
59+
# tests now. Leaving this here for now to be safe.
5860
if item.get_closest_marker("blockchain_test_sync"):
5961
item.add_marker(pytest.mark.flaky(reruns=3))
6062

0 commit comments

Comments
 (0)