Skip to content

Commit 3e2b631

Browse files
committed
Merge remote-tracking branch 'upstream/eips/amsterdam/eip-7843' into devnets/bal/2
2 parents 7903251 + b63306f commit 3e2b631

25 files changed

Lines changed: 380 additions & 6 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def client_genesis(fixture: BlockchainFixtureCommon) -> dict:
3333
alloc = to_json(fixture.pre)
3434
# NOTE: nethermind requires account keys without '0x' prefix
3535
genesis["alloc"] = {k.replace("0x", ""): v for k, v in alloc.items()}
36+
# NOTE: geth expects slotNumber as plain integer, not hex string
37+
if "slotNumber" in genesis:
38+
genesis["slotNumber"] = int(genesis["slotNumber"], 16)
3639
return genesis
3740

3841

packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/rpc/chain_builder_eth_rpc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ def generate_block(self: "ChainBuilderEthRPC") -> None:
300300
)
301301
else None
302302
),
303+
slot_number=(
304+
0
305+
if self.fork.engine_payload_attribute_slot_number(
306+
block_number=0, timestamp=0
307+
)
308+
else None
309+
),
303310
)
304311
forkchoice_updated_version = (
305312
self.fork.engine_forkchoice_updated_version()

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ class FixtureHeader(CamelModel):
214214
block_access_list_hash: (
215215
Annotated[Hash, HeaderForkRequirement("bal_hash")] | None
216216
) = Field(None, alias="blockAccessListHash")
217+
slot_number: (
218+
Annotated[ZeroPaddedHexNumber, HeaderForkRequirement("slot_number")]
219+
| None
220+
) = Field(None)
217221

218222
fork: Fork | None = Field(None, exclude=True)
219223

@@ -365,7 +369,7 @@ def get_default_from_annotation(
365369
def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> Self:
366370
"""Get the genesis header for the given fork."""
367371
environment_values = env.model_dump(
368-
exclude_none=True, exclude={"withdrawals"}
372+
exclude_none=True, exclude={"withdrawals", "slot_number"}
369373
)
370374
if env.withdrawals is not None:
371375
environment_values["withdrawals_root"] = Withdrawal.list_root(
@@ -382,6 +386,13 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> Self:
382386
if fork.header_bal_hash_required(block_number=0, timestamp=0)
383387
else None
384388
),
389+
"slot_number": (
390+
0
391+
if fork.header_slot_number_required(
392+
block_number=0, timestamp=0
393+
)
394+
else None
395+
),
385396
"fork": fork,
386397
}
387398
return cls(**environment_values, **extras)
@@ -422,6 +433,7 @@ class FixtureExecutionPayload(CamelModel):
422433
block_access_list: Bytes | None = Field(
423434
None, description="RLP-serialized EIP-7928 Block Access List"
424435
)
436+
slot_number: HexNumber | None = Field(None)
425437

426438
@classmethod
427439
def from_fixture_header(

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,14 @@ def header_bal_hash_required(
369369
"""Return true if the header must contain block access list hash."""
370370
pass
371371

372+
@classmethod
373+
@abstractmethod
374+
def header_slot_number_required(
375+
cls, *, block_number: int = 0, timestamp: int = 0
376+
) -> bool:
377+
"""Return true if the header must contain slot number (EIP-7843)."""
378+
pass
379+
372380
# Gas related abstract methods
373381

374382
@classmethod
@@ -799,6 +807,16 @@ def engine_payload_attribute_max_blobs_per_block(
799807
"""
800808
pass
801809

810+
@classmethod
811+
@abstractmethod
812+
def engine_payload_attribute_slot_number(
813+
cls, *, block_number: int = 0, timestamp: int = 0
814+
) -> bool:
815+
"""
816+
Return true if the payload attributes include the slot number.
817+
"""
818+
pass
819+
802820
@classmethod
803821
@abstractmethod
804822
def engine_forkchoice_updated_version(

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

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,14 @@ def header_beacon_root_required(
977977
del block_number, timestamp
978978
return False
979979

980+
@classmethod
981+
def header_slot_number_required(
982+
cls, *, block_number: int = 0, timestamp: int = 0
983+
) -> bool:
984+
"""At genesis, header must not contain slot number (EIP-7843)."""
985+
del block_number, timestamp
986+
return False
987+
980988
@classmethod
981989
def engine_new_payload_blob_hashes(
982990
cls, *, block_number: int = 0, timestamp: int = 0
@@ -1041,6 +1049,16 @@ def engine_payload_attribute_max_blobs_per_block(
10411049
del block_number, timestamp
10421050
return False
10431051

1052+
@classmethod
1053+
def engine_payload_attribute_slot_number(
1054+
cls, *, block_number: int = 0, timestamp: int = 0
1055+
) -> bool:
1056+
"""
1057+
At genesis, payload attributes do not include the slot number.
1058+
"""
1059+
del block_number, timestamp
1060+
return False
1061+
10441062
@classmethod
10451063
def engine_forkchoice_updated_version(
10461064
cls, *, block_number: int = 0, timestamp: int = 0
@@ -3362,9 +3380,7 @@ class Amsterdam(BPO2):
33623380
def header_bal_hash_required(
33633381
cls, *, block_number: int = 0, timestamp: int = 0
33643382
) -> bool:
3365-
"""
3366-
From Amsterdam, header must contain block access list hash (EIP-7928).
3367-
"""
3383+
"""BAL hash in header required from Amsterdam (EIP-7928)."""
33683384
del block_number, timestamp
33693385
return True
33703386

@@ -3373,6 +3389,31 @@ def is_deployed(cls) -> bool:
33733389
"""Return True if this fork is deployed."""
33743390
return False
33753391

3392+
@classmethod
3393+
def valid_opcodes(
3394+
cls, *, block_number: int = 0, timestamp: int = 0
3395+
) -> List[Opcodes]:
3396+
"""Add SLOTNUM opcode for Amsterdam (EIP-7843)."""
3397+
return [Opcodes.SLOTNUM] + super(Amsterdam, cls).valid_opcodes(
3398+
block_number=block_number, timestamp=timestamp
3399+
)
3400+
3401+
@classmethod
3402+
def opcode_gas_map(
3403+
cls, *, block_number: int = 0, timestamp: int = 0
3404+
) -> Dict[OpcodeBase, int | Callable[[OpcodeBase], int]]:
3405+
"""Add SLOTNUM opcode gas cost for Amsterdam (EIP-7843)."""
3406+
gas_costs = cls.gas_costs(
3407+
block_number=block_number, timestamp=timestamp
3408+
)
3409+
base_map = super(Amsterdam, cls).opcode_gas_map(
3410+
block_number=block_number, timestamp=timestamp
3411+
)
3412+
return {
3413+
**base_map,
3414+
Opcodes.SLOTNUM: gas_costs.G_BASE,
3415+
}
3416+
33763417
@classmethod
33773418
def engine_new_payload_version(
33783419
cls, *, block_number: int = 0, timestamp: int = 0
@@ -3391,3 +3432,27 @@ def engine_execution_payload_block_access_list(
33913432
"""
33923433
del block_number, timestamp
33933434
return True
3435+
3436+
@classmethod
3437+
def header_slot_number_required(
3438+
cls, *, block_number: int = 0, timestamp: int = 0
3439+
) -> bool:
3440+
"""Slot number in header required from Amsterdam (EIP-7843)."""
3441+
del block_number, timestamp
3442+
return True
3443+
3444+
@classmethod
3445+
def engine_forkchoice_updated_version(
3446+
cls, *, block_number: int = 0, timestamp: int = 0
3447+
) -> Optional[int]:
3448+
"""From Amsterdam, forkchoice updated calls must use version 4."""
3449+
del block_number, timestamp
3450+
return 4
3451+
3452+
@classmethod
3453+
def engine_payload_attribute_slot_number(
3454+
cls, *, block_number: int = 0, timestamp: int = 0
3455+
) -> bool:
3456+
"""From Amsterdam, payload attributes include the slot number."""
3457+
del block_number, timestamp
3458+
return True

packages/testing/src/execution_testing/rpc/rpc_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ class PayloadAttributes(CamelModel):
157157
parent_beacon_block_root: Hash | None = None
158158
target_blobs_per_block: HexNumber | None = None
159159
max_blobs_per_block: HexNumber | None = None
160+
slot_number: HexNumber | None = None
160161

161162

162163
class BlobsBundle(CamelModel):

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ class Header(CamelModel):
157157
parent_beacon_block_root: Removable | Hash | None = None
158158
requests_hash: Removable | Hash | None = None
159159
bal_hash: Removable | Hash | None = None
160+
slot_number: Removable | HexNumber | None = None
160161

161162
REMOVE_FIELD: ClassVar[Removable] = Removable()
162163
"""
@@ -330,6 +331,8 @@ def set_environment(self, env: Environment) -> Environment:
330331
and self.block_access_list is not None
331332
):
332333
new_env_values["block_access_list"] = self.block_access_list
334+
if not isinstance(self.slot_number, Removable):
335+
new_env_values["slot_number"] = self.slot_number
333336
"""
334337
These values are required, but they depend on the previous environment,
335338
so they can be calculated here.
@@ -669,6 +672,12 @@ def generate_block_data(
669672
fork=self.fork,
670673
)
671674

675+
# Clear block_access_list_hash if the fork doesn't require it
676+
if not self.fork.header_bal_hash_required(
677+
block_number=int(env.number), timestamp=int(env.timestamp)
678+
):
679+
header.block_access_list_hash = None
680+
672681
if block.header_verify is not None:
673682
# Verify the header after transition tool processing.
674683
try:
@@ -773,8 +782,11 @@ def generate_block_data(
773782
bal = block.expected_block_access_list.modify_if_invalid_test(
774783
t8n_bal
775784
)
776-
if bal != t8n_bal:
777-
# If the BAL was modified, update the header hash
785+
if bal != t8n_bal and self.fork.header_bal_hash_required(
786+
block_number=int(env.number), timestamp=int(env.timestamp)
787+
):
788+
# If the BAL was modified and the fork requires it,
789+
# update the header hash
778790
header.block_access_list_hash = Hash(bal.rlp.keccak256())
779791

780792
built_block = BuiltBlock(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ def _generate_blockchain_blocks(self) -> List[Block]:
311311
"extra_data": self.env.extra_data,
312312
"withdrawals": self.env.withdrawals,
313313
"parent_beacon_block_root": self.env.parent_beacon_block_root,
314+
"slot_number": self.env.slot_number,
314315
"txs": [self.tx],
315316
"ommers": [],
316317
"header_verify": self.blockchain_test_header_verify,

packages/testing/src/execution_testing/specs/static_state/environment.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class EnvironmentInStateTestFiller(BaseModel):
3333
current_excess_blob_gas: ValueInFiller | None = Field(
3434
None, alias="currentExcessBlobGas"
3535
)
36+
current_slot_number: ValueInFiller | None = Field(None, alias="slotNumber")
3637

3738
model_config = ConfigDict(extra="forbid")
3839

@@ -72,4 +73,6 @@ def get_environment(self, tags: TagDict) -> Environment:
7273
kwargs["base_fee_per_gas"] = self.current_base_fee
7374
if self.current_excess_blob_gas is not None:
7475
kwargs["excess_blob_gas"] = self.current_excess_blob_gas
76+
if self.current_slot_number is not None:
77+
kwargs["slot_number"] = self.current_slot_number
7578
return Environment(**kwargs)

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class EnvironmentGeneric(CamelModel, Generic[NumberBoundTypeVar]):
101101
excess_blob_gas: NumberBoundTypeVar | None = Field(
102102
None, alias="currentExcessBlobGas"
103103
)
104+
slot_number: NumberBoundTypeVar | None = Field(None, alias="slotNumber")
104105

105106
parent_difficulty: NumberBoundTypeVar | None = Field(None)
106107
parent_timestamp: NumberBoundTypeVar | None = Field(None)
@@ -223,6 +224,14 @@ def set_fork_requirements(self, fork: Fork) -> "Environment":
223224
):
224225
updated_values["parent_beacon_block_root"] = 0
225226

227+
if (
228+
fork.header_slot_number_required(
229+
block_number=number, timestamp=timestamp
230+
)
231+
and self.slot_number is None
232+
):
233+
updated_values["slot_number"] = 0
234+
226235
return self.copy(**updated_values)
227236

228237
def __hash__(self) -> int:

0 commit comments

Comments
 (0)