Skip to content
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

improvement: Refactor of spec for blockchain & state test generation #307

Merged
merged 5 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Test fixtures for use by clients are available for each release on the [Github r
### 🛠️ Framework

- 🔀 Fixtures: Add a non-RLP format field (`rlp_decoded`) to invalid blocks ([#322](https://github.com/ethereum/execution-spec-tests/pull/322)).
- 🔀 Spec: Refactor state and blockchain spec ([#307](https://github.com/ethereum/execution-spec-tests/pull/307)).

### 🔧 EVM Tools

Expand Down
59 changes: 22 additions & 37 deletions src/ethereum_test_tools/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,6 @@ class Environment:
to_json=True,
),
)

base_fee: Optional[NumberConvertible] = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand All @@ -961,7 +960,6 @@ class Environment:
cast_type=Number,
),
)

parent_timestamp: Optional[NumberConvertible] = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand Down Expand Up @@ -1033,7 +1031,7 @@ class Environment:
),
)
extra_data: Optional[BytesConvertible] = field(
default=None,
default=b"\x00",
json_encoder=JSONEncoder.Field(
skip=True,
),
Expand Down Expand Up @@ -2028,7 +2026,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="parentHash"),
)

ommers_hash: Hash = header_field(
source=HeaderFieldSource(
parse_type=Hash,
Expand All @@ -2037,47 +2034,41 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="uncleHash"),
)

coinbase: Address = header_field(
source=HeaderFieldSource(
parse_type=Address,
source_environment="coinbase",
),
json_encoder=JSONEncoder.Field(),
)

state_root: Hash = header_field(
source=HeaderFieldSource(
parse_type=Hash,
source_transition_tool="stateRoot",
),
json_encoder=JSONEncoder.Field(name="stateRoot"),
)

transactions_root: Hash = header_field(
source=HeaderFieldSource(
parse_type=Hash,
source_transition_tool="txRoot",
),
json_encoder=JSONEncoder.Field(name="transactionsTrie"),
)

receipt_root: Hash = header_field(
source=HeaderFieldSource(
parse_type=Hash,
source_transition_tool="receiptsRoot",
),
json_encoder=JSONEncoder.Field(name="receiptTrie"),
)

bloom: Bloom = header_field(
source=HeaderFieldSource(
parse_type=Bloom,
source_transition_tool="logsBloom",
),
json_encoder=JSONEncoder.Field(),
)

difficulty: int = header_field(
source=HeaderFieldSource(
parse_type=Number,
Expand All @@ -2087,39 +2078,34 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(cast_type=ZeroPaddedHexNumber),
)

number: int = header_field(
source=HeaderFieldSource(
parse_type=Number,
source_environment="number",
),
json_encoder=JSONEncoder.Field(cast_type=ZeroPaddedHexNumber),
)

gas_limit: int = header_field(
source=HeaderFieldSource(
parse_type=Number,
source_environment="gas_limit",
),
json_encoder=JSONEncoder.Field(name="gasLimit", cast_type=ZeroPaddedHexNumber),
)

gas_used: int = header_field(
source=HeaderFieldSource(
parse_type=Number,
source_transition_tool="gasUsed",
),
json_encoder=JSONEncoder.Field(name="gasUsed", cast_type=ZeroPaddedHexNumber),
)

timestamp: int = header_field(
source=HeaderFieldSource(
parse_type=Number,
source_environment="timestamp",
),
json_encoder=JSONEncoder.Field(cast_type=ZeroPaddedHexNumber),
)

extra_data: Bytes = header_field(
source=HeaderFieldSource(
parse_type=Bytes,
Expand All @@ -2128,7 +2114,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="extraData"),
)

mix_digest: Hash = header_field(
source=HeaderFieldSource(
parse_type=Hash,
Expand All @@ -2137,15 +2122,13 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="mixHash"),
)

nonce: HeaderNonce = header_field(
source=HeaderFieldSource(
parse_type=HeaderNonce,
default=b"",
),
json_encoder=JSONEncoder.Field(),
)

base_fee: Optional[int] = header_field(
default=None,
source=HeaderFieldSource(
Expand All @@ -2156,7 +2139,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="baseFeePerGas", cast_type=ZeroPaddedHexNumber),
)

withdrawals_root: Optional[Hash] = header_field(
default=None,
source=HeaderFieldSource(
Expand All @@ -2166,7 +2148,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="withdrawalsRoot"),
)

blob_gas_used: Optional[int] = header_field(
default=None,
source=HeaderFieldSource(
Expand All @@ -2176,7 +2157,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="blobGasUsed", cast_type=ZeroPaddedHexNumber),
)

excess_blob_gas: Optional[int] = header_field(
default=None,
source=HeaderFieldSource(
Expand All @@ -2186,7 +2166,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="excessBlobGas", cast_type=ZeroPaddedHexNumber),
)

beacon_root: Optional[Hash] = header_field(
default=None,
source=HeaderFieldSource(
Expand All @@ -2196,7 +2175,6 @@ class FixtureHeader:
),
json_encoder=JSONEncoder.Field(name="parentBeaconBlockRoot"),
)

hash: Optional[Hash] = header_field(
default=None,
source=HeaderFieldSource(
Expand Down Expand Up @@ -2576,14 +2554,14 @@ class FixtureEngineNewPayload:
cast_type=Hash,
),
)
version: int = field(
json_encoder=JSONEncoder.Field(),
)
valid: bool = field(
json_encoder=JSONEncoder.Field(
skip_string_convert=True,
),
)
version: int = field(
json_encoder=JSONEncoder.Field(),
)
error_code: Optional[EngineAPIError] = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand Down Expand Up @@ -2638,6 +2616,14 @@ class FixtureBlock:
Representation of an Ethereum block within a test Fixture.
"""

@staticmethod
def _txs_encoder(txs: List[Transaction]) -> List[FixtureTransaction]:
return [FixtureTransaction.from_transaction(tx) for tx in txs]

@staticmethod
def _withdrawals_encoder(withdrawals: List[Withdrawal]) -> List[FixtureWithdrawal]:
return [FixtureWithdrawal.from_withdrawal(w) for w in withdrawals]

rlp: Bytes = field(
default=None,
json_encoder=JSONEncoder.Field(),
Expand Down Expand Up @@ -2666,7 +2652,7 @@ class FixtureBlock:
default=None,
json_encoder=JSONEncoder.Field(
name="transactions",
cast_type=lambda txs: [FixtureTransaction.from_transaction(tx) for tx in txs],
cast_type=_txs_encoder,
to_json=True,
),
)
Expand All @@ -2681,9 +2667,7 @@ class FixtureBlock:
default=None,
json_encoder=JSONEncoder.Field(
name="withdrawals",
cast_type=lambda withdrawals: [
FixtureWithdrawal.from_withdrawal(w) for w in withdrawals
],
cast_type=_withdrawals_encoder,
to_json=True,
),
)
Expand Down Expand Up @@ -2716,7 +2700,7 @@ class InvalidFixtureBlock:
@dataclass(kw_only=True)
class BaseFixture:
"""
Base Ethereum test fixture class.
Base Ethereum test fixture fields class.
"""

info: Dict[str, str] = field(
Expand All @@ -2726,17 +2710,17 @@ class BaseFixture:
to_json=True,
),
)
fork: str = field(
json_encoder=JSONEncoder.Field(
name="network",
),
)
name: str = field(
default="",
json_encoder=JSONEncoder.Field(
skip=True,
),
)
fork: str = field(
json_encoder=JSONEncoder.Field(
name="network",
),
)
_json: Dict[str, Any] | None = field(
default=None,
json_encoder=JSONEncoder.Field(
Expand Down Expand Up @@ -2795,7 +2779,7 @@ class Fixture(BaseFixture):
to_json=True,
),
)
head: Hash = field(
last_block_hash: Hash = field(
json_encoder=JSONEncoder.Field(
name="lastblockhash",
),
Expand All @@ -2816,6 +2800,7 @@ class Fixture(BaseFixture):
),
)
seal_engine: str = field(
default="NoProof",
json_encoder=JSONEncoder.Field(
name="sealEngine",
),
Expand Down
53 changes: 8 additions & 45 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.
Test filler definitions.
"""
from typing import List, Optional, Union

from ethereum_test_forks import Fork
from evm_transition_tool import TransitionTool

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

Expand All @@ -15,56 +15,19 @@ def fill_test(
t8n: TransitionTool,
test_spec: BaseTest,
fork: Fork,
engine: str,
spec: ReferenceSpec | None,
eips: Optional[List[int]] = None,
) -> Optional[Union[Fixture, HiveFixture]]:
"""
Fills fixtures for the specified fork.
Fills default/hive fixture for the specified fork and test spec.
"""
t8n.reset_traces()

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

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

network_info = (
"+".join([fork.name()] + [str(eip) for eip in eips]) if eips is not None else fork.name()
)

fixture: Union[Fixture, HiveFixture]
t8n.reset_traces()
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
if fork.engine_new_payload_version() is None:
return None # pre Merge tests are not supported in Hive
fixture = test_spec.make_hive_fixture(t8n, fork, eips)
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 = test_spec.make_fixture(t8n, fork, eips)
fixture.fill_info(t8n, spec)

return fixture
Loading