Skip to content

Commit

Permalink
src/ethereum_test_tools|test_filler: refactor using HiveFixture now w…
Browse files Browse the repository at this point in the history
…ith distict fixture generation.
  • Loading branch information
spencer-tb committed Sep 20, 2023
1 parent f0c16b5 commit e4fd95d
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 118 deletions.
2 changes: 2 additions & 0 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
FixtureEngineNewPayload,
Header,
HistoryStorageAddress,
HiveFixture,
JSONEncoder,
Removable,
Storage,
Expand Down Expand Up @@ -77,6 +78,7 @@
"FixtureEngineNewPayload",
"Header",
"HistoryStorageAddress",
"HiveFixture",
"Initcode",
"JSONEncoder",
"Opcode",
Expand Down
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 @@ -41,6 +41,7 @@
Hash,
Header,
HeaderNonce,
HiveFixture,
JSONEncoder,
Number,
Removable,
Expand Down Expand Up @@ -77,6 +78,7 @@
"Header",
"HeaderNonce",
"HistoryStorageAddress",
"HiveFixture",
"JSONEncoder",
"Number",
"Removable",
Expand Down
144 changes: 91 additions & 53 deletions src/ethereum_test_tools/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2642,13 +2642,6 @@ class FixtureBlock:
to_json=True,
),
)
new_payload: Optional[FixtureEngineNewPayload] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="engineNewPayload",
to_json=True,
),
)
expected_exception: Optional[str] = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand Down Expand Up @@ -2690,9 +2683,9 @@ class FixtureBlock:


@dataclass(kw_only=True)
class Fixture:
class BaseFixture:
"""
Cross-client compatible Ethereum test fixture.
Base Ethereum test fixture class.
"""

info: Dict[str, str] = field(
Expand All @@ -2702,36 +2695,78 @@ class Fixture:
to_json=True,
),
)
blocks: List[FixtureBlock] = field(
fork: str = field(
json_encoder=JSONEncoder.Field(
name="blocks",
to_json=True,
name="network",
),
)
fcu_version: Optional[int] = field(
name: str = field(
default="",
json_encoder=JSONEncoder.Field(
name="engineFcuVersion",
skip=True,
),
)
genesis: FixtureHeader = field(
_json: Dict[str, Any] | None = field(
default=None,
json_encoder=JSONEncoder.Field(
name="genesisBlockHeader",
to_json=True,
skip=True,
),
)

def __post_init__(self):
"""
Post init hook to convert to JSON after instantiation.
"""
self._json = to_json(self)

def to_json(self) -> Dict[str, Any]:
"""
Convert to JSON.
"""
assert self._json is not None, "Fixture not initialized"
self._json["_info"] = self.info
return self._json

def fill_info(
self,
t8n: TransitionTool,
ref_spec: ReferenceSpec | None,
):
"""
Fill the info field for this fixture
"""
self.info["filling-transition-tool"] = t8n.version()
if ref_spec is not None:
ref_spec.write_info(self.info)


@dataclass(kw_only=True)
class Fixture(BaseFixture):
"""
Cross-client specific test fixture information.
"""

genesis_rlp: Bytes = field(
json_encoder=JSONEncoder.Field(
name="genesisRLP",
),
)
head: Hash = field(
genesis: FixtureHeader = field(
json_encoder=JSONEncoder.Field(
name="lastblockhash",
name="genesisBlockHeader",
to_json=True,
),
)
fork: str = field(
blocks: Optional[List[FixtureBlock]] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="network",
name="blocks",
to_json=True,
),
)
head: Hash = field(
json_encoder=JSONEncoder.Field(
name="lastblockhash",
),
)
pre_state: Mapping[str, Account] = field(
Expand All @@ -2754,42 +2789,45 @@ class Fixture:
name="sealEngine",
),
)
name: str = field(
default="",


@dataclass(kw_only=True)
class HiveFixture(BaseFixture):
"""
Hive specific test fixture information.
"""

genesis: FixtureHeader = field(
json_encoder=JSONEncoder.Field(
skip=True,
name="genesisBlockHeader",
to_json=True,
),
)

_json: Dict[str, Any] | None = field(
payloads: Optional[List[Optional[FixtureEngineNewPayload]]] = field(
default=None,
json_encoder=JSONEncoder.Field(
skip=True,
name="engineNewPayloads",
to_json=True,
),
)
fcu_version: Optional[int] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="engineFcuVersion",
),
)
pre_state: Mapping[str, Account] = field(
json_encoder=JSONEncoder.Field(
name="pre",
cast_type=Alloc,
to_json=True,
),
)
post_state: Optional[Mapping[str, Account]] = field(
default=None,
json_encoder=JSONEncoder.Field(
name="postState",
cast_type=Alloc,
to_json=True,
),
)

def __post_init__(self):
"""
Post init hook to convert to JSON after instantiation.
"""
self._json = to_json(self)

def to_json(self) -> Dict[str, Any]:
"""
Convert to JSON.
"""
assert self._json is not None, "Fixture not initialized"
self._json["_info"] = self.info
return self._json

def fill_info(
self,
t8n: TransitionTool,
ref_spec: ReferenceSpec | None,
):
"""
Fill the info field for this fixture
"""
self.info["filling-transition-tool"] = t8n.version()
if ref_spec is not None:
ref_spec.write_info(self.info)
50 changes: 34 additions & 16 deletions src/ethereum_test_tools/filling/fill.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
Filler object definitions.
"""
from typing import List, Optional
from typing import List, Optional, Union

from ethereum_test_forks import Fork
from evm_transition_tool import TransitionTool

from ..common import Fixture, alloc_to_accounts
from ..common import Fixture, HiveFixture, alloc_to_accounts
from ..reference_spec.reference_spec import ReferenceSpec
from ..spec import BaseTest

Expand All @@ -18,35 +18,53 @@ def fill_test(
engine: str,
spec: ReferenceSpec | None,
eips: Optional[List[int]] = None,
) -> Fixture:
) -> Optional[Union[Fixture, HiveFixture]]:
"""
Fills fixtures for the specified fork.
"""
t8n.reset_traces()

pre, genesis_rlp, genesis = test_spec.make_genesis(t8n, fork)

(blocks, head, alloc, fcu_version) = test_spec.make_blocks(
(blocks, payloads, head, alloc, fcu_version) = test_spec.make_blocks(
t8n,
genesis,
pre,
fork,
eips=eips,
)

fork_name = fork.name()
fixture = Fixture(
blocks=blocks,
genesis=genesis,
genesis_rlp=genesis_rlp,
head=head,
fork="+".join([fork_name] + [str(eip) for eip in eips]) if eips is not None else fork_name,
pre_state=pre,
post_state=alloc_to_accounts(alloc),
seal_engine=engine,
name=test_spec.tag,
fcu_version=fcu_version,
network_info = (
"+".join([fork.name()] + [str(eip) for eip in eips]) if eips is not None else fork.name()
)

fixture: Union[Fixture, HiveFixture]
if test_spec.base_test_config.enable_hive:
if fork.engine_new_payload_version() is not None:
fixture = HiveFixture(
payloads=payloads,
fcu_version=fcu_version,
genesis=genesis,
fork=network_info,
pre_state=pre,
post_state=alloc_to_accounts(alloc),
name=test_spec.tag,
)
else: # pre Merge tests are not supported in Hive
# TODO: remove this logic. if hive enabled set --from to Merge
return None
else:
fixture = Fixture(
blocks=blocks,
genesis=genesis,
genesis_rlp=genesis_rlp,
head=head,
fork=network_info,
pre_state=pre,
post_state=alloc_to_accounts(alloc),
seal_engine=engine,
name=test_spec.tag,
)
fixture.fill_info(t8n, spec)

return fixture
9 changes: 8 additions & 1 deletion src/ethereum_test_tools/spec/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Bytes,
Environment,
FixtureBlock,
FixtureEngineNewPayload,
FixtureHeader,
Hash,
Transaction,
Expand Down Expand Up @@ -127,7 +128,13 @@ def make_blocks(
fork: Fork,
chain_id: int = 1,
eips: Optional[List[int]] = None,
) -> Tuple[List[FixtureBlock], Hash, Dict[str, Any], Optional[int]]:
) -> Tuple[
Optional[List[FixtureBlock]],
Optional[List[Optional[FixtureEngineNewPayload]]],
Hash,
Dict[str, Any],
Optional[int],
]:
"""
Generate the blockchain that must be executed sequentially during test.
"""
Expand Down
Loading

0 comments on commit e4fd95d

Please sign in to comment.