Skip to content

Commit 58cac9b

Browse files
committed
Merge branch 'projects/zkevm' into projects/zkevm-bal-devnet-3
2 parents 7ea84be + 3e2e716 commit 58cac9b

30 files changed

Lines changed: 1548 additions & 129 deletions

packages/testing/src/execution_testing/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
Environment,
6868
ExecutionWitnessCodesExpectation,
6969
ExecutionWitnessHeadersExpectation,
70+
ExecutionWitnessStateExpectation,
7071
NetworkWrappedTransaction,
7172
Removable,
7273
Requests,
@@ -157,6 +158,7 @@
157158
"ConsolidationRequest",
158159
"ExecutionWitnessCodesExpectation",
159160
"ExecutionWitnessHeadersExpectation",
161+
"ExecutionWitnessStateExpectation",
160162
"ExtCallGenerator",
161163
"DeploymentTestType",
162164
"DepositRequest",

packages/testing/src/execution_testing/fixtures/blockchain.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,14 @@ class FixtureBlock(FixtureBlockBase):
678678
def without_rlp(self) -> FixtureBlockBase:
679679
"""Return FixtureBlockBase without the RLP bytes set."""
680680
return FixtureBlockBase(
681-
**self.model_dump(exclude={"rlp"}),
681+
**self.model_dump(
682+
exclude={
683+
"rlp",
684+
"execution_witness",
685+
"stateless_input_bytes",
686+
"stateless_output_bytes",
687+
},
688+
),
682689
)
683690

684691

@@ -698,6 +705,9 @@ class InvalidFixtureBlock(CamelModel):
698705
rlp: Bytes
699706
expect_exception: ExceptionInstanceOrList
700707
rlp_decoded: FixtureBlockBase | None = Field(None, alias="rlp_decoded")
708+
execution_witness: ExecutionWitness | None = None
709+
stateless_input_bytes: Bytes | None = None
710+
stateless_output_bytes: Bytes | None = None
701711

702712

703713
@post_state_validator()

packages/testing/src/execution_testing/forks/base_fork.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,17 @@ def system_contracts(
732732
"""Return list of system contracts supported by the fork."""
733733
pass
734734

735+
@classmethod
736+
def execution_witness_implicit_code_addresses(
737+
cls, *, block_number: int = 0, timestamp: int = 0
738+
) -> List[Address]:
739+
"""
740+
Return addresses whose pre-state bytecodes are implicitly expected in
741+
execution witnesses for block execution at this fork.
742+
"""
743+
del block_number, timestamp
744+
return []
745+
735746
@classmethod
736747
@abstractmethod
737748
def deterministic_factory_predeploy_address(

packages/testing/src/execution_testing/forks/forks/forks.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,6 +2643,19 @@ def system_contracts(
26432643
)
26442644
]
26452645

2646+
@classmethod
2647+
def execution_witness_implicit_code_addresses(
2648+
cls, *, block_number: int = 0, timestamp: int = 0
2649+
) -> List[Address]:
2650+
"""Cancun witnesses implicitly include beacon roots code."""
2651+
del block_number, timestamp
2652+
return [
2653+
Address(
2654+
0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02,
2655+
label="BEACON_ROOTS_ADDRESS",
2656+
)
2657+
]
2658+
26462659
@classmethod
26472660
def pre_allocation_blockchain(
26482661
cls, *, block_number: int = 0, timestamp: int = 0
@@ -2865,6 +2878,28 @@ def system_contracts(
28652878
block_number=block_number, timestamp=timestamp
28662879
)
28672880

2881+
@classmethod
2882+
def execution_witness_implicit_code_addresses(
2883+
cls, *, block_number: int = 0, timestamp: int = 0
2884+
) -> List[Address]:
2885+
"""Include tracked block-level system code."""
2886+
return [
2887+
Address(
2888+
0x00000961EF480EB55E80D19AD83579A64C007002,
2889+
label="WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS",
2890+
),
2891+
Address(
2892+
0x0000BBDDC7CE488642FB579F8B00F3A590007251,
2893+
label="CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS",
2894+
),
2895+
Address(
2896+
0x0000F90827F1C53A10CB7A02335B175320002935,
2897+
label="HISTORY_STORAGE_ADDRESS",
2898+
),
2899+
] + super(Prague, cls).execution_witness_implicit_code_addresses(
2900+
block_number=block_number, timestamp=timestamp
2901+
)
2902+
28682903
@classmethod
28692904
def max_request_type(
28702905
cls, *, block_number: int = 0, timestamp: int = 0
@@ -3755,6 +3790,31 @@ def empty_block_bal_item_count(
37553790
del block_number, timestamp
37563791
return 15
37573792

3793+
@classmethod
3794+
def execution_witness_implicit_code_addresses(
3795+
cls, *, block_number: int = 0, timestamp: int = 0
3796+
) -> List[Address]:
3797+
"""Include tracked block-level system code."""
3798+
del block_number, timestamp
3799+
return [
3800+
Address(
3801+
0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02,
3802+
label="BEACON_ROOTS_ADDRESS",
3803+
),
3804+
Address(
3805+
0x00000961EF480EB55E80D19AD83579A64C007002,
3806+
label="WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS",
3807+
),
3808+
Address(
3809+
0x0000BBDDC7CE488642FB579F8B00F3A590007251,
3810+
label="CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS",
3811+
),
3812+
Address(
3813+
0x0000F90827F1C53A10CB7A02335B175320002935,
3814+
label="HISTORY_STORAGE_ADDRESS",
3815+
),
3816+
]
3817+
37583818
@classmethod
37593819
def is_deployed(cls) -> bool:
37603820
"""Return True if this fork is deployed."""

packages/testing/src/execution_testing/forks/tests/test_forks.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,22 @@ def test_forks() -> None:
218218
)
219219

220220

221+
def test_amsterdam_execution_witness_implicit_code_addresses() -> None:
222+
"""Amsterdam exposes exactly the tracked ambient witness code addresses."""
223+
addresses = [
224+
address.hex()
225+
for address in Amsterdam.execution_witness_implicit_code_addresses()
226+
]
227+
228+
assert addresses == [
229+
"0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
230+
"0x00000961ef480eb55e80d19ad83579a64c007002",
231+
"0x0000bbddc7ce488642fb579f8b00f3a590007251",
232+
"0x0000f90827f1c53a10cb7a02335b175320002935",
233+
]
234+
assert "0x00000000219ab540356cbb839cbe05303d7705fa" not in addresses
235+
236+
221237
class ForkInPydanticModel(BaseModel):
222238
"""Fork in pydantic model."""
223239

packages/testing/src/execution_testing/specs/blockchain.py

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
from execution_testing.test_types.execution_witness import (
9393
ExecutionWitnessCodesExpectation,
9494
ExecutionWitnessHeadersExpectation,
95+
ExecutionWitnessStateExpectation,
9596
)
9697

9798
from .base import BaseTest, FillResult, OpMode, verify_result
@@ -148,6 +149,71 @@ def count_blobs(txs: List[Transaction]) -> int:
148149
)
149150

150151

152+
def execution_witness_implicit_codes_for_block(
153+
*,
154+
fork: Fork,
155+
alloc: Alloc | LazyAlloc,
156+
block_number: int,
157+
timestamp: int,
158+
) -> List[Bytes]:
159+
"""
160+
Return ambient witness bytecodes implied by block-level execution.
161+
162+
These codes are resolved from the effective pre-state for the block, not
163+
from raw fork defaults, so test `pre` overrides are respected.
164+
"""
165+
active_fork = fork.fork_at(block_number=block_number, timestamp=timestamp)
166+
addresses = active_fork.execution_witness_implicit_code_addresses(
167+
block_number=block_number,
168+
timestamp=timestamp,
169+
)
170+
if not addresses:
171+
return []
172+
173+
effective_alloc = alloc.get() if isinstance(alloc, LazyAlloc) else alloc
174+
175+
codes: List[Bytes] = []
176+
seen: set[Bytes] = set()
177+
for address in addresses:
178+
if address not in effective_alloc:
179+
continue
180+
account = effective_alloc[address]
181+
if account is None or len(account.code) == 0:
182+
continue
183+
code = Bytes(account.code)
184+
if code in seen:
185+
continue
186+
codes.append(code)
187+
seen.add(code)
188+
return codes
189+
190+
191+
def with_execution_witness_implicit_codes(
192+
*,
193+
expectation: ExecutionWitnessCodesExpectation,
194+
fork: Fork,
195+
alloc: Alloc | LazyAlloc,
196+
block_number: int,
197+
timestamp: int,
198+
) -> ExecutionWitnessCodesExpectation:
199+
"""Return expectation copy with ambient block-level codes added."""
200+
codes_present = list(expectation.codes_present)
201+
seen = set(codes_present)
202+
203+
for code in execution_witness_implicit_codes_for_block(
204+
fork=fork,
205+
alloc=alloc,
206+
block_number=block_number,
207+
timestamp=timestamp,
208+
):
209+
if code in seen:
210+
continue
211+
codes_present.append(code)
212+
seen.add(code)
213+
214+
return expectation.model_copy(update={"codes_present": codes_present})
215+
216+
151217
class Header(CamelModel):
152218
"""Header type used to describe block header properties in test specs."""
153219

@@ -283,6 +349,13 @@ class Block(Header):
283349
If set, the execution witness codes will be verified and potentially
284350
modified for invalid tests.
285351
"""
352+
expected_execution_witness_state: (
353+
ExecutionWitnessStateExpectation | None
354+
) = None
355+
"""
356+
If set, the execution witness state will be verified and potentially
357+
modified for invalid tests.
358+
"""
286359
expected_execution_witness_headers: (
287360
ExecutionWitnessHeadersExpectation | None
288361
) = None
@@ -464,6 +537,9 @@ def get_fixture_block(
464537
in self.expected_exception
465538
else fixture_block.without_rlp()
466539
),
540+
execution_witness=self.execution_witness,
541+
stateless_input_bytes=self.stateless_input_bytes,
542+
stateless_output_bytes=self.stateless_output_bytes,
467543
)
468544

469545
return fixture_block
@@ -830,17 +906,33 @@ def generate_block_data(
830906
# update the header hash
831907
header.block_access_list_hash = Hash(bal.rlp.keccak256())
832908

833-
# If expected witness codes defined, verify against actual
909+
# If expected witness state/codes defined, verify against actual
834910
t8n_witness = transition_tool_output.result.execution_witness
835911
execution_witness = t8n_witness
912+
state_expectation = block.expected_execution_witness_state
913+
if state_expectation is not None and execution_witness is not None:
914+
state_expectation.verify_against(execution_witness)
915+
execution_witness = state_expectation.modify_if_invalid_test(
916+
execution_witness
917+
)
918+
836919
if (
837920
block.expected_execution_witness_codes is not None
838-
and t8n_witness is not None
921+
and execution_witness is not None
839922
):
840-
block.expected_execution_witness_codes.verify_against(t8n_witness)
923+
effective_codes_expectation = (
924+
with_execution_witness_implicit_codes(
925+
expectation=block.expected_execution_witness_codes,
926+
fork=self.fork,
927+
alloc=previous_alloc,
928+
block_number=env.number,
929+
timestamp=env.timestamp,
930+
)
931+
)
932+
effective_codes_expectation.verify_against(execution_witness)
841933
execution_witness = (
842934
block.expected_execution_witness_codes.modify_if_invalid_test(
843-
t8n_witness
935+
execution_witness
844936
)
845937
)
846938

@@ -892,6 +984,11 @@ def generate_block_data(
892984
block.expected_block_access_list is not None
893985
and block.expected_block_access_list._modifier is not None
894986
)
987+
and not (
988+
block.expected_execution_witness_state is not None
989+
and block.expected_execution_witness_state._modifier
990+
is not None
991+
)
895992
and not (
896993
block.expected_execution_witness_codes is not None
897994
and block.expected_execution_witness_codes._modifier

packages/testing/src/execution_testing/specs/state.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
Environment,
5656
ExecutionWitnessCodesExpectation,
5757
ExecutionWitnessHeadersExpectation,
58+
ExecutionWitnessStateExpectation,
5859
Transaction,
5960
)
6061

@@ -88,6 +89,9 @@ class StateTest(BaseTest):
8889
expected_execution_witness_codes: Optional[
8990
ExecutionWitnessCodesExpectation
9091
] = None
92+
expected_execution_witness_state: Optional[
93+
ExecutionWitnessStateExpectation
94+
] = None
9195
expected_execution_witness_headers: Optional[
9296
ExecutionWitnessHeadersExpectation
9397
] = None
@@ -326,6 +330,9 @@ def _generate_blockchain_blocks(self) -> List[Block]:
326330
"expected_execution_witness_codes": (
327331
self.expected_execution_witness_codes
328332
),
333+
"expected_execution_witness_state": (
334+
self.expected_execution_witness_state
335+
),
329336
"expected_execution_witness_headers": (
330337
self.expected_execution_witness_headers
331338
),

packages/testing/src/execution_testing/test_types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
ExecutionWitness,
2424
ExecutionWitnessCodesExpectation,
2525
ExecutionWitnessHeadersExpectation,
26+
ExecutionWitnessStateExpectation,
2627
ExecutionWitnessValidationError,
2728
)
2829
from .helpers import (
@@ -80,6 +81,7 @@
8081
"ExecutionWitness",
8182
"ExecutionWitnessCodesExpectation",
8283
"ExecutionWitnessHeadersExpectation",
84+
"ExecutionWitnessStateExpectation",
8385
"ExecutionWitnessValidationError",
8486
"NetworkWrappedTransaction",
8587
"Removable",

packages/testing/src/execution_testing/test_types/execution_witness/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
from .expectations import (
1010
ExecutionWitnessCodesExpectation,
1111
ExecutionWitnessHeadersExpectation,
12+
ExecutionWitnessStateExpectation,
1213
)
1314
from .types import ExecutionWitness
1415

1516
__all__ = [
1617
"ExecutionWitness",
1718
"ExecutionWitnessCodesExpectation",
1819
"ExecutionWitnessHeadersExpectation",
20+
"ExecutionWitnessStateExpectation",
1921
"ExecutionWitnessValidationError",
2022
]

0 commit comments

Comments
 (0)