-
Notifications
You must be signed in to change notification settings - Fork 489
fix(tests,test-fill): fix Engine X fills on BAL forks #3219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: forks/amsterdam
Are you sure you want to change the base?
Changes from all commits
778b791
e076b4e
bef68d7
887d53c
882909a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,8 @@ | |
| from pathlib import Path | ||
| from typing import Any, Dict, List, NamedTuple, Optional, Tuple | ||
|
|
||
| from ethereum_rlp import rlp | ||
|
|
||
| ENGINE_X_FIXTURES_DIR = "blockchain_tests_engine_x" | ||
| SIBLING_FIXTURES_DIR = "blockchain_tests_engine" | ||
|
|
||
|
|
@@ -12,6 +14,40 @@ | |
| # payload is a pure function of the test's execution. | ||
| _STATE_ROOT_DERIVED_FIELDS = ("stateRoot", "blockHash", "parentHash") | ||
|
|
||
| # Placeholder for the parent-hash value embedded in a block access list. | ||
| _PARENT_HASH_PLACEHOLDER = "<parent-hash>" | ||
|
|
||
|
|
||
| def _masked(node: Any, parent_hash: bytes) -> Any: | ||
| """Mask every ``parent_hash`` leaf in a decoded BAL, hex the rest.""" | ||
| if isinstance(node, bytes): | ||
| if parent_hash and node == parent_hash: | ||
| return _PARENT_HASH_PLACEHOLDER | ||
| return node.hex() | ||
| return [_masked(child, parent_hash) for child in node] | ||
|
|
||
|
|
||
| def _scrubbed_bal(bal_hex: str, parent_hash_hex: str) -> Any: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not great that we need this in the first place, this highlights how brittle this file is. |
||
| """ | ||
| Return a comparable form of a BAL with its parent hash masked out. | ||
|
|
||
| The EIP-2935 system call writes the parent hash into the history | ||
| contract on every block, so each payload's BAL embeds one | ||
| state-root-derived value (at payload 0, the genesis hash itself). The | ||
| BAL is decoded and that value masked rather than the whole field | ||
| dropped, so the rest of the BAL still participates in the comparison: | ||
| a leaked account shows up in the BAL before anywhere else. Storage | ||
| values are RLP-encoded with leading zeros trimmed, so the trimmed | ||
| parent hash is masked. An undecodable BAL (an intentionally malformed | ||
| one from a negative test) is compared verbatim. | ||
| """ | ||
| parent_hash = bytes.fromhex(parent_hash_hex.removeprefix("0x")) | ||
| try: | ||
| decoded = rlp.decode(bytes.fromhex(bal_hex.removeprefix("0x"))) | ||
| except Exception: | ||
| return bal_hex | ||
| return _masked(decoded, parent_hash.lstrip(b"\x00")) | ||
|
|
||
|
|
||
| class EngineXExecutionDriftError(Exception): | ||
| """ | ||
|
|
@@ -74,8 +110,13 @@ def _scrubbed_payloads(fixture: Dict[str, Any]) -> List[Any]: | |
| entry = json.loads(json.dumps(entry)) | ||
| params = entry.get("params") | ||
| if params and isinstance(params[0], dict): | ||
| payload = params[0] | ||
| bal = payload.get("blockAccessList") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem with this is that we are passing |
||
| parent_hash = payload.get("parentHash") | ||
| if isinstance(bal, str) and isinstance(parent_hash, str): | ||
| payload["blockAccessList"] = _scrubbed_bal(bal, parent_hash) | ||
| for field in _STATE_ROOT_DERIVED_FIELDS: | ||
| params[0].pop(field, None) | ||
| payload.pop(field, None) | ||
| payloads.append(entry) | ||
| return payloads | ||
|
|
||
|
|
@@ -114,7 +155,10 @@ def verify_engine_x_execution( | |
| `blockchain_test_engine` sibling fixture (filled against the test's own | ||
| pre-allocation in the same session, with an independent `t8n` execution: | ||
| Engine X fixtures never share the transition tool output cache). All | ||
| payload fields except the state-root-derived ones must match exactly. | ||
| payload fields except the state-root-derived ones must match exactly; | ||
| each payload's block access list is compared with its own parent-hash | ||
| bytes normalized out, since the EIP-2935 system write embeds that | ||
| state-root-derived value in every BAL. | ||
|
|
||
| Return the comparison counts, or ``None`` when one of the two fixture | ||
| format trees was not generated at all (e.g. when filling with | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is just a nightmare to maintain: it introduced a post-fact verification and provides zero indication about the cause when there's a failure.