From cdaf7e84dd8e4af2400fabd5505f6c8d46ea4c87 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 27 Oct 2022 21:59:17 +0200 Subject: [PATCH 1/5] Allow extending LC merkle proof tests Currently, `test_single_merkle_proof` only supports `BeaconState` tests. For future tests, different object classes are desirable. Update format to allow testing other objects as well. --- .../light_client/test_single_merkle_proof.py | 18 ++++++++++++------ .../light_client/single_merkle_proof.md | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py index 064760bf0..5628cb70d 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py @@ -7,8 +7,10 @@ from eth2spec.test.context import ( @with_altair_and_later @spec_state_test def test_current_sync_committee_merkle_proof(spec, state): - yield "state", state - current_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX) + yield "object_class", "meta", "BeaconState" + yield "object", state + current_sync_committee_branch = \ + spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX) yield "proof", { "leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(), "leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX, @@ -26,8 +28,10 @@ def test_current_sync_committee_merkle_proof(spec, state): @with_altair_and_later @spec_state_test def test_next_sync_committee_merkle_proof(spec, state): - yield "state", state - next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) + yield "object_class", "meta", "BeaconState" + yield "object", state + next_sync_committee_branch = \ + spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) yield "proof", { "leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(), "leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX, @@ -45,8 +49,10 @@ def test_next_sync_committee_merkle_proof(spec, state): @with_altair_and_later @spec_state_test def test_finality_root_merkle_proof(spec, state): - yield "state", state - finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) + yield "object_class", "meta", "BeaconState" + yield "object", state + finality_branch = \ + spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) yield "proof", { "leaf": "0x" + state.finalized_checkpoint.root.hex(), "leaf_index": spec.FINALIZED_ROOT_INDEX, diff --git a/tests/formats/light_client/single_merkle_proof.md b/tests/formats/light_client/single_merkle_proof.md index 65fe7c988..c8b2dea6e 100644 --- a/tests/formats/light_client/single_merkle_proof.md +++ b/tests/formats/light_client/single_merkle_proof.md @@ -5,24 +5,30 @@ generation and verification of merkle proofs based on static data. ## Test case format -### `state.ssz_snappy` +### `meta.yaml` -An SSZ-snappy encoded `BeaconState` object from which other data is generated. +```yaml +object_class: string -- 'BeaconState' +``` + +### `object.yaml` + +A SSZ-snappy encoded object of type `object_class` from which other data is generated. ### `proof.yaml` -A proof of the leaf value (a merkle root) at generalized-index `leaf_index` in the given `state`. +A proof of the leaf value (a merkle root) at generalized-index `leaf_index` in the given `object`. ```yaml leaf: Bytes32 # string, hex encoded, with 0x prefix leaf_index: int # integer, decimal -branch: list of Bytes32 # list, each element is a string, hex encoded, with 0x prefix +branch: list of Bytes32 # list, each element is a string, hex encoded, with 0x prefix ``` ## Condition A test-runner can implement the following assertions: - Check that `is_valid_merkle_branch` confirms `leaf` at `leaf_index` to verify - against `has_tree_root(state)` and `proof`. + against `hash_tree_root(object)` and `branch`. - If the implementation supports generating merkle proofs, check that the - self-generated proof matches the `proof` provided with the test. + self-generated proof matches the `branch` provided with the test. From 5c663001711ae6507862731801cb161adc122802 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 28 Oct 2022 20:32:33 +0200 Subject: [PATCH 2/5] Use `suite_name` instead of `meta.yaml` for SSZ type --- .../pyspec/eth2spec/gen_helpers/gen_from_tests/gen.py | 2 +- .../test/altair/light_client/test_single_merkle_proof.py | 7 ++++--- tests/core/pyspec/eth2spec/test/context.py | 7 +++++++ tests/formats/light_client/single_merkle_proof.md | 8 ++------ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/core/pyspec/eth2spec/gen_helpers/gen_from_tests/gen.py b/tests/core/pyspec/eth2spec/gen_helpers/gen_from_tests/gen.py index 328b7edf1..b951a6a85 100644 --- a/tests/core/pyspec/eth2spec/gen_helpers/gen_from_tests/gen.py +++ b/tests/core/pyspec/eth2spec/gen_helpers/gen_from_tests/gen.py @@ -49,7 +49,7 @@ def generate_from_tests(runner_name: str, handler_name: str, src: Any, preset_name=preset_name, runner_name=runner_name, handler_name=handler_name, - suite_name='pyspec_tests', + suite_name=getattr(tfn, 'suite_name', 'pyspec_tests'), case_name=case_name, # TODO: with_all_phases and other per-phase tooling, should be replaced with per-fork equivalent. case_fn=lambda: tfn(generator_mode=True, phase=phase, preset=preset_name, bls_active=bls_active) diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py index 5628cb70d..465fa629f 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_single_merkle_proof.py @@ -1,13 +1,14 @@ from eth2spec.test.context import ( spec_state_test, with_altair_and_later, + with_test_suite_name, ) +@with_test_suite_name("BeaconState") @with_altair_and_later @spec_state_test def test_current_sync_committee_merkle_proof(spec, state): - yield "object_class", "meta", "BeaconState" yield "object", state current_sync_committee_branch = \ spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX) @@ -25,10 +26,10 @@ def test_current_sync_committee_merkle_proof(spec, state): ) +@with_test_suite_name("BeaconState") @with_altair_and_later @spec_state_test def test_next_sync_committee_merkle_proof(spec, state): - yield "object_class", "meta", "BeaconState" yield "object", state next_sync_committee_branch = \ spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) @@ -46,10 +47,10 @@ def test_next_sync_committee_merkle_proof(spec, state): ) +@with_test_suite_name("BeaconState") @with_altair_and_later @spec_state_test def test_finality_root_merkle_proof(spec, state): - yield "object_class", "meta", "BeaconState" yield "object", state finality_branch = \ spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index bc04c05f2..bcc77398c 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -620,6 +620,13 @@ def only_generator(reason): return _decorator +def with_test_suite_name(suite_name: str): + def _decorator(inner): + inner.suite_name = suite_name + return inner + return _decorator + + # # Fork transition state tests # diff --git a/tests/formats/light_client/single_merkle_proof.md b/tests/formats/light_client/single_merkle_proof.md index c8b2dea6e..d2137605e 100644 --- a/tests/formats/light_client/single_merkle_proof.md +++ b/tests/formats/light_client/single_merkle_proof.md @@ -5,15 +5,11 @@ generation and verification of merkle proofs based on static data. ## Test case format -### `meta.yaml` - -```yaml -object_class: string -- 'BeaconState' -``` +Tests for each individual SSZ type are grouped into a `suite` indicating the SSZ type name. ### `object.yaml` -A SSZ-snappy encoded object of type `object_class` from which other data is generated. +A SSZ-snappy encoded object from which other data is generated. The SSZ type can be determined from the test `suite` name. ### `proof.yaml` From b737e5370fee75af306a93a4d86f4a9ed7ca2220 Mon Sep 17 00:00:00 2001 From: Enrico Del Fante Date: Wed, 16 Nov 2022 12:12:18 +0100 Subject: [PATCH 3/5] fix state upgrade --- specs/eip4844/fork.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/specs/eip4844/fork.md b/specs/eip4844/fork.md index eaabba916..18d334261 100644 --- a/specs/eip4844/fork.md +++ b/specs/eip4844/fork.md @@ -66,8 +66,25 @@ Since the `eip4844.BeaconState` format is equal to the `bellatrix.BeaconState` f ```python def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState: - # TODO: if Capella gets scheduled, add sync it with Capella.BeaconState + # TODO: if Capella gets scheduled, add sync it with Capella.BeaconState and Capella.ExecutionPayloadHeader epoch = bellatrix.get_current_epoch(pre) + latest_execution_payload_header = ExecutionPayloadHeader( + parent_hash=pre.latest_execution_payload_header.parent_hash, + fee_recipient=pre.latest_execution_payload_header.fee_recipient, + state_root=pre.latest_execution_payload_header.state_root, + receipts_root=pre.latest_execution_payload_header.receipts_root, + logs_bloom=pre.latest_execution_payload_header.logs_bloom, + prev_randao=pre.latest_execution_payload_header.prev_randao, + block_number=pre.latest_execution_payload_header.block_number, + gas_limit=pre.latest_execution_payload_header.gas_limit, + gas_used=pre.latest_execution_payload_header.gas_used, + timestamp=pre.latest_execution_payload_header.timestamp, + extra_data=pre.latest_execution_payload_header.extra_data, + base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas, + excess_blobs=uint64(0), # [New in EIP-4844] + block_hash=pre.latest_execution_payload_header.block_hash, + transactions_root=pre.latest_execution_payload_header.transactions_root, + ) post = BeaconState( # Versioning genesis_time=pre.genesis_time, @@ -108,7 +125,7 @@ def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState: current_sync_committee=pre.current_sync_committee, next_sync_committee=pre.next_sync_committee, # Execution-layer - latest_execution_payload_header=pre.latest_execution_payload_header, + latest_execution_payload_header=latest_execution_payload_header, ) return post From 620943b2756fa28a767a3f6dd470e68449a233de Mon Sep 17 00:00:00 2001 From: Enrico Del Fante Date: Wed, 16 Nov 2022 19:19:39 +0100 Subject: [PATCH 4/5] Update specs/eip4844/fork.md Co-authored-by: Alex Stokes --- specs/eip4844/fork.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/eip4844/fork.md b/specs/eip4844/fork.md index 18d334261..fcae85c25 100644 --- a/specs/eip4844/fork.md +++ b/specs/eip4844/fork.md @@ -66,7 +66,7 @@ Since the `eip4844.BeaconState` format is equal to the `bellatrix.BeaconState` f ```python def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState: - # TODO: if Capella gets scheduled, add sync it with Capella.BeaconState and Capella.ExecutionPayloadHeader + # TODO: if Capella gets scheduled, add sync it with Capella.BeaconState epoch = bellatrix.get_current_epoch(pre) latest_execution_payload_header = ExecutionPayloadHeader( parent_hash=pre.latest_execution_payload_header.parent_hash, From 30dce7f232b1864ff4afdce8f3a2a80e0b69b11c Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 18 Nov 2022 02:25:56 +0800 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Alex Stokes --- specs/eip4844/fork.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/eip4844/fork.md b/specs/eip4844/fork.md index fcae85c25..8e3a727df 100644 --- a/specs/eip4844/fork.md +++ b/specs/eip4844/fork.md @@ -81,9 +81,10 @@ def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState: timestamp=pre.latest_execution_payload_header.timestamp, extra_data=pre.latest_execution_payload_header.extra_data, base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas, - excess_blobs=uint64(0), # [New in EIP-4844] + excess_data_gas=uint256(0), # [New in EIP-4844] block_hash=pre.latest_execution_payload_header.block_hash, transactions_root=pre.latest_execution_payload_header.transactions_root, + withdrawals_root=pre.latest_execution_payload_header.withdrawals_root, ) post = BeaconState( # Versioning