Skip to content

Commit

Permalink
improvement: Add Engine API forkchoice updated field to fixtures for …
Browse files Browse the repository at this point in the history
…hive.
  • Loading branch information
--global committed Aug 16, 2023
1 parent efe1d49 commit 8d00032
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 5 deletions.
25 changes: 23 additions & 2 deletions src/ethereum_test_forks/base_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,40 @@ def engine_new_payload_version(
@abstractmethod
def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool:
"""
Returns true if the engine api version requires new payload calls to include blob hashes.
Returns true if the engine new payload version requires new calls to include blob hashes.
"""
pass

@classmethod
@abstractmethod
def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool:
"""
Returns true if the engine api version requires new payload calls to include a parent
Returns true if the engine new payload version requires new calls to include a parent
beacon block root.
"""
pass

@classmethod
@abstractmethod
def engine_forkchoice_updated_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Returns `None` if this fork's canonical chain cannot be set using the forkchoice method.
"""
pass

@classmethod
@abstractmethod
def engine_forkchoice_updated_beacon_root(
cls, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
Returns true if the engine forkchoice updated version requires new calls to include a
parent beacon block root.
"""
pass

# Meta information about the fork
@classmethod
def name(cls) -> str:
Expand Down
42 changes: 39 additions & 3 deletions src/ethereum_test_forks/forks/forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,16 @@ def engine_new_payload_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at the merge, payloads can be sent through the engine API
Starting at the merge, payloads can be sent through the engine API.
"""
return 1

@classmethod
def engine_forkchoice_updated_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at the merge, forkchoice update determines the canonical chain
"""
return 1

Expand All @@ -261,7 +270,16 @@ def engine_new_payload_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at Shanghai, new payload calls must use version 2
Starting at Shanghai, new payload calls must use version 2.
"""
return 2

@classmethod
def engine_forkchoice_updated_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at Shanghai, forkchoice updated calls must use version 2.
"""
return 2

Expand Down Expand Up @@ -320,7 +338,7 @@ def engine_new_payload_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at Cancun, new payload calls must use version 3
Starting at Cancun, new payload calls must use version 3.
"""
return 3

Expand All @@ -337,3 +355,21 @@ def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int =
Starting at Cancun, payloads must have a parent beacon block root.
"""
return True

@classmethod
def engine_forkchoice_updated_version(
cls, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
Starting at Cancun, forkchoice updated calls must use version 3.
"""
return 3

@classmethod
def engine_forkchoice_updated_beacon_root(
cls, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
Starting at Cancun, forkchoice update calls must have a parent beacon block root.
"""
return True
2 changes: 2 additions & 0 deletions src/ethereum_test_tools/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
Environment,
Fixture,
FixtureBlock,
FixtureEngineForkchoiceUpdated,
FixtureEngineNewPayload,
FixtureHeader,
Hash,
Expand Down Expand Up @@ -71,6 +72,7 @@
"Environment",
"Fixture",
"FixtureBlock",
"FixtureEngineForkchoiceUpdated",
"FixtureEngineNewPayload",
"FixtureHeader",
"Hash",
Expand Down
114 changes: 114 additions & 0 deletions src/ethereum_test_tools/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,113 @@ def copy_with_rlp(self, rlp: Bytes | BytesConvertible | None) -> "Block":
return new_block


@dataclass(kw_only=True)
class FixtureEnginePayloadAttributes:
"""
Representation of the engine api payload attributes from a block within a test fixture.
"""

mix_digest: Hash = field(
json_encoder=JSONEncoder.Field(
name="prevRandao",
),
)

coinbase: Address = field(
json_encoder=JSONEncoder.Field(
name="feeRecipient",
)
)

timestamp: int = field(
json_encoder=JSONEncoder.Field(
cast_type=HexNumber,
)
)

withdrawals: Optional[List[Withdrawal]] = field(
default=None,
json_encoder=JSONEncoder.Field(
to_json=True,
),
)

beacon_root: Optional[Hash] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="parentBeaconBlockRoot",
),
)

@classmethod
def from_fixture_header(
cls,
fork,
header: FixtureHeader,
withdrawals: Optional[List[Withdrawal]] = None,
) -> "FixtureEnginePayloadAttributes":
"""
Returns `FixtureEnginePayloadAttributes` from a `FixtureHeader` and a list of withdrawals.
"""
return cls(
mix_digest=header.mix_digest,
coinbase=header.coinbase,
timestamp=header.timestamp,
withdrawals=withdrawals,
beacon_root=header.beacon_root
if fork.engine_forkchoice_updated_beacon_root(header.number, header.timestamp)
else None,
)


@dataclass(kw_only=True)
class FixtureEngineForkchoiceUpdated:
"""
Representation of the `engine_forkchoiceUpdatedVX` information to be
sent using the block information.
"""

payload_attributes: FixtureEnginePayloadAttributes = field(
json_encoder=JSONEncoder.Field(
name="payloadAttributes",
to_json=True,
)
)

version: int = field(
json_encoder=JSONEncoder.Field(),
)

@classmethod
def from_fixture_header(
cls,
fork: Fork,
header: FixtureHeader,
withdrawals: Optional[List[Withdrawal]],
) -> Optional["FixtureEngineForkchoiceUpdated"]:
"""
Creates `FixtureEngineForkchoiceUpdated` from a `FixtureHeader`.
"""
forkchoice_updated_version = fork.engine_forkchoice_updated_version(
header.number,
header.timestamp,
)

if forkchoice_updated_version is None:
return None

forkchoice_updated = cls(
payload_attributes=FixtureEnginePayloadAttributes.from_fixture_header(
fork=fork,
header=header,
withdrawals=withdrawals,
),
version=forkchoice_updated_version,
)

return forkchoice_updated


@dataclass(kw_only=True)
class FixtureExecutionPayload(FixtureHeader):
"""
Expand Down Expand Up @@ -2569,6 +2676,13 @@ class FixtureBlock:
to_json=True,
),
)
forkchoice_updated: Optional[FixtureEngineForkchoiceUpdated] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="forkchoiceUpdated",
to_json=True,
),
)
new_payload: Optional[FixtureEngineNewPayload] = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand Down
10 changes: 10 additions & 0 deletions src/ethereum_test_tools/spec/blockchain_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
EmptyTrieRoot,
Environment,
FixtureBlock,
FixtureEngineForkchoiceUpdated,
FixtureEngineNewPayload,
FixtureHeader,
Hash,
Expand Down Expand Up @@ -203,8 +204,15 @@ def make_block(
withdrawals=env.withdrawals,
)

forkchoice_updated: FixtureEngineForkchoiceUpdated | None = None
new_payload: FixtureEngineNewPayload | None = None
if not self.base_test_config.disable_hive:
forkchoice_updated = FixtureEngineForkchoiceUpdated.from_fixture_header(
fork=fork,
header=header,
withdrawals=env.withdrawals,
)

new_payload = FixtureEngineNewPayload.from_fixture_header(
fork=fork,
header=header,
Expand All @@ -218,6 +226,7 @@ def make_block(
return (
FixtureBlock(
rlp=rlp,
forkchoice_updated=forkchoice_updated,
new_payload=new_payload,
block_header=header,
block_number=Number(header.number),
Expand All @@ -233,6 +242,7 @@ def make_block(
return (
FixtureBlock(
rlp=rlp,
forkchoice_updated=forkchoice_updated,
new_payload=new_payload,
expected_exception=block.exception,
block_number=Number(header.number),
Expand Down
9 changes: 9 additions & 0 deletions src/ethereum_test_tools/spec/state_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
EmptyTrieRoot,
Environment,
FixtureBlock,
FixtureEngineForkchoiceUpdated,
FixtureEngineNewPayload,
FixtureHeader,
Hash,
Expand Down Expand Up @@ -171,8 +172,15 @@ def make_blocks(
withdrawals=env.withdrawals,
)

forkchoice_updated: FixtureEngineForkchoiceUpdated | None = None
new_payload: FixtureEngineNewPayload | None = None
if not self.base_test_config.disable_hive:
forkchoice_updated = FixtureEngineForkchoiceUpdated.from_fixture_header(
fork=fork,
header=header,
withdrawals=env.withdrawals,
)

new_payload = FixtureEngineNewPayload.from_fixture_header(
fork=fork,
header=header,
Expand All @@ -185,6 +193,7 @@ def make_blocks(
[
FixtureBlock(
rlp=block,
forkchoice_updated=forkchoice_updated,
new_payload=new_payload,
block_header=header,
txs=txs,
Expand Down

0 comments on commit 8d00032

Please sign in to comment.