From 5e43ad69cfd2a51f0a08459761ca82570dfa58d5 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 5 Apr 2021 18:31:05 -0700 Subject: [PATCH 01/25] Add some basic tests for Altair validator guide --- .../test/altair/validator/__init__.py | 0 .../test/altair/validator/test_validator.py | 155 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 tests/core/pyspec/eth2spec/test/altair/validator/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py diff --git a/tests/core/pyspec/eth2spec/test/altair/validator/__init__.py b/tests/core/pyspec/eth2spec/test/altair/validator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py new file mode 100644 index 000000000..da7b7a131 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py @@ -0,0 +1,155 @@ +import random +from eth2spec.utils.ssz.ssz_typing import Bitvector +from eth2spec.test.helpers.block import build_empty_block +from eth2spec.test.helpers.keys import pubkey_to_privkey +from eth2spec.test.helpers.state import transition_to +from eth2spec.utils import bls +from eth2spec.utils.bls import only_with_bls +from eth2spec.test.context import ( + PHASE0, + with_all_phases_except, + with_state, +) + +rng = random.Random(1337) + + +def ensure_assignments_in_sync_committee( + spec, state, epoch, sync_committee, active_pubkeys +): + assert len(sync_committee.pubkeys) >= 3 + some_pubkeys = rng.sample(sync_committee.pubkeys, 3) + for pubkey in some_pubkeys: + validator_index = active_pubkeys.index(pubkey) + assert spec.is_assigned_to_sync_committee(state, epoch, validator_index) + + +@with_all_phases_except([PHASE0]) +@with_state +def test_is_assigned_to_sync_committee(phases, spec, state): + epoch = spec.get_current_epoch(state) + validator_indices = spec.get_active_validator_indices(state, epoch) + validator_count = len(validator_indices) + + query_epoch = epoch + 1 + next_query_epoch = query_epoch + spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD + active_pubkeys = [state.validators[index].pubkey for index in validator_indices] + + ensure_assignments_in_sync_committee( + spec, state, query_epoch, state.current_sync_committee, active_pubkeys + ) + ensure_assignments_in_sync_committee( + spec, state, next_query_epoch, state.next_sync_committee, active_pubkeys + ) + + assert validator_count >= 3 + sync_committee_pubkeys = set( + list(state.current_sync_committee.pubkeys) + + list(state.next_sync_committee.pubkeys) + ) + disqualified_pubkeys = list( + filter(lambda key: key not in sync_committee_pubkeys, active_pubkeys) + ) + some_pubkeys = rng.sample(disqualified_pubkeys, 3) + for pubkey in some_pubkeys: + validator_index = active_pubkeys.index(pubkey) + is_current = spec.is_assigned_to_sync_committee( + state, query_epoch, validator_index + ) + is_next = spec.is_assigned_to_sync_committee( + state, next_query_epoch, validator_index + ) + is_current_or_next = is_current or is_next + assert not is_current_or_next + + +def _get_sync_committee_signature( + spec, + state, + target_slot, + target_block_root, + subcommittee_index, + index_in_subcommittee, +): + subcommittee_size = spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT + sync_committee_index = ( + subcommittee_index * subcommittee_size + index_in_subcommittee + ) + pubkey = state.current_sync_committee.pubkeys[sync_committee_index] + privkey = pubkey_to_privkey[pubkey] + + domain = spec.get_domain( + state, + spec.DOMAIN_SYNC_COMMITTEE, + ) + signing_data = spec.compute_signing_root(target_block_root, domain) + return bls.Sign(privkey, spec.hash_tree_root(signing_data)) + + +@only_with_bls() +@with_all_phases_except([PHASE0]) +@with_state +def test_process_sync_committee_contributions(phases, spec, state): + # skip over slots at genesis + transition_to(spec, state, state.slot + 3) + + # build a block and attempt to assemble a sync aggregate + # from some sync committee contributions + block = build_empty_block(spec, state) + previous_slot = state.slot - 1 + target_block_root = spec.get_block_root_at_slot(state, previous_slot) + aggregation_bits = Bitvector[ + spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT + ]() + aggregation_index = 0 + aggregation_bits[aggregation_index] = True + + contributions = [ + spec.SyncCommitteeContribution( + slot=block.slot, + beacon_block_root=target_block_root, + subcommittee_index=i, + aggregation_bits=aggregation_bits, + signature=_get_sync_committee_signature( + spec, state, previous_slot, target_block_root, i, aggregation_index + ), + ) + for i in range(spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT) + ] + + # ensure the block has an empty sync aggregate... + empty_sync_aggregate = spec.SyncAggregate() + empty_sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY + assert block.body.sync_aggregate == empty_sync_aggregate + spec.process_sync_committee_contributions(block, set(contributions)) + + # and that after processing, it is no longer empty + assert len(block.body.sync_aggregate.sync_committee_bits) != 0 + assert ( + block.body.sync_aggregate.sync_committee_signature != spec.G2_POINT_AT_INFINITY + ) + # moreover, ensure the sync aggregate is valid if the block is accepted + spec.process_block(state, block) + + +@with_all_phases_except([PHASE0]) +@with_state +def test_compute_subnets_for_sync_committee(state, spec, phases): + k = max(spec.SYNC_COMMITTEE_SIZE // 4, 1) + some_sync_committee_members = rng.sample( + list( + (i, pubkey) for i, pubkey in enumerate(state.current_sync_committee.pubkeys) + ), + k, + ) + validator_indices = [ + list(map(lambda v: v.pubkey, state.validators)).index(pubkey) + for pubkey in map(lambda t: t[1], some_sync_committee_members) + ] + expected_subnets = [ + index // (spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT) + for index in map(lambda t: t[0], some_sync_committee_members) + ] + for validator_index, expected_subnet in zip(validator_indices, expected_subnets): + subnet = spec.compute_subnets_for_sync_committee(state, validator_index) + assert subnet == [expected_subnet] From 4678ffc7942e3e7a4ce13632de858cbdd2778036 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 8 Apr 2021 10:50:21 -0700 Subject: [PATCH 02/25] Update tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py Co-authored-by: Hsiao-Wei Wang --- .../pyspec/eth2spec/test/altair/validator/test_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py index da7b7a131..673184b18 100644 --- a/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py @@ -151,5 +151,5 @@ def test_compute_subnets_for_sync_committee(state, spec, phases): for index in map(lambda t: t[0], some_sync_committee_members) ] for validator_index, expected_subnet in zip(validator_indices, expected_subnets): - subnet = spec.compute_subnets_for_sync_committee(state, validator_index) - assert subnet == [expected_subnet] + subnets = spec.compute_subnets_for_sync_committee(state, validator_index) + assert subnets == [expected_subnet] From 749b49898a15bb5d895f33700643a5f0b17897e2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 8 Apr 2021 11:22:59 -0700 Subject: [PATCH 03/25] file reorg --- .../eth2spec/test/altair/{ => unittests}/validator/__init__.py | 0 .../test/altair/{ => unittests}/validator/test_validator.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/core/pyspec/eth2spec/test/altair/{ => unittests}/validator/__init__.py (100%) rename tests/core/pyspec/eth2spec/test/altair/{ => unittests}/validator/test_validator.py (100%) diff --git a/tests/core/pyspec/eth2spec/test/altair/validator/__init__.py b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/__init__.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/altair/validator/__init__.py rename to tests/core/pyspec/eth2spec/test/altair/unittests/validator/__init__.py diff --git a/tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/altair/validator/test_validator.py rename to tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py From 3fd49744304f193436694bd3df2a7adeb7d75c5c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 8 Apr 2021 17:44:10 -0700 Subject: [PATCH 04/25] iterate over the correct number of subcommittees --- .../eth2spec/test/altair/unittests/validator/test_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py index 673184b18..016234541 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py @@ -114,7 +114,7 @@ def test_process_sync_committee_contributions(phases, spec, state): spec, state, previous_slot, target_block_root, i, aggregation_index ), ) - for i in range(spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT) + for i in range(spec.SYNC_COMMITTEE_SUBNET_COUNT) ] # ensure the block has an empty sync aggregate... From e4e65295b6db09ce1b299b0c8fe91974c6af5c75 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 8 Apr 2021 17:57:43 -0700 Subject: [PATCH 05/25] modify assignment test when sync committee size >= validator count --- .../unittests/validator/test_validator.py | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py index 016234541..bb26dff1c 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py @@ -42,25 +42,28 @@ def test_is_assigned_to_sync_committee(phases, spec, state): spec, state, next_query_epoch, state.next_sync_committee, active_pubkeys ) - assert validator_count >= 3 sync_committee_pubkeys = set( list(state.current_sync_committee.pubkeys) + list(state.next_sync_committee.pubkeys) ) - disqualified_pubkeys = list( + disqualified_pubkeys = set( filter(lambda key: key not in sync_committee_pubkeys, active_pubkeys) ) - some_pubkeys = rng.sample(disqualified_pubkeys, 3) - for pubkey in some_pubkeys: - validator_index = active_pubkeys.index(pubkey) - is_current = spec.is_assigned_to_sync_committee( - state, query_epoch, validator_index - ) - is_next = spec.is_assigned_to_sync_committee( - state, next_query_epoch, validator_index - ) - is_current_or_next = is_current or is_next - assert not is_current_or_next + # NOTE: only check `disqualified_pubkeys` if SYNC_COMMITEE_SIZE < validator count + if disqualified_pubkeys: + sample_size = 3 + assert validator_count >= sample_size + some_pubkeys = rng.sample(disqualified_pubkeys, sample_size) + for pubkey in some_pubkeys: + validator_index = active_pubkeys.index(pubkey) + is_current = spec.is_assigned_to_sync_committee( + state, query_epoch, validator_index + ) + is_next = spec.is_assigned_to_sync_committee( + state, next_query_epoch, validator_index + ) + is_current_or_next = is_current or is_next + assert not is_current_or_next def _get_sync_committee_signature( From 66905f4fa621c8204e5948d0277ce20aaad199e0 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 8 Apr 2021 18:25:58 -0700 Subject: [PATCH 06/25] update test to work for both minimal and mainnet config --- .../unittests/validator/test_validator.py | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py index bb26dff1c..244e1aa7e 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/validator/test_validator.py @@ -1,4 +1,5 @@ import random +from collections import defaultdict from eth2spec.utils.ssz.ssz_typing import Bitvector from eth2spec.test.helpers.block import build_empty_block from eth2spec.test.helpers.keys import pubkey_to_privkey @@ -135,24 +136,31 @@ def test_process_sync_committee_contributions(phases, spec, state): spec.process_block(state, block) +def _validator_index_for_pubkey(state, pubkey): + return list(map(lambda v: v.pubkey, state.validators)).index(pubkey) + + +def _subnet_for_sync_committee_index(spec, i): + return i // (spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT) + + @with_all_phases_except([PHASE0]) @with_state def test_compute_subnets_for_sync_committee(state, spec, phases): - k = max(spec.SYNC_COMMITTEE_SIZE // 4, 1) - some_sync_committee_members = rng.sample( - list( - (i, pubkey) for i, pubkey in enumerate(state.current_sync_committee.pubkeys) - ), - k, + some_sync_committee_members = list( + ( + _subnet_for_sync_committee_index(spec, i), + pubkey, + ) + for i, pubkey in enumerate(state.current_sync_committee.pubkeys) ) - validator_indices = [ - list(map(lambda v: v.pubkey, state.validators)).index(pubkey) - for pubkey in map(lambda t: t[1], some_sync_committee_members) - ] - expected_subnets = [ - index // (spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT) - for index in map(lambda t: t[0], some_sync_committee_members) - ] - for validator_index, expected_subnet in zip(validator_indices, expected_subnets): + + expected_subnets_by_pubkey = defaultdict(list) + for (subnet, pubkey) in some_sync_committee_members: + expected_subnets_by_pubkey[pubkey].append(subnet) + + for _, pubkey in some_sync_committee_members: + validator_index = _validator_index_for_pubkey(state, pubkey) subnets = spec.compute_subnets_for_sync_committee(state, validator_index) - assert subnets == [expected_subnet] + expected_subnets = expected_subnets_by_pubkey[pubkey] + assert subnets == expected_subnets From a1ded22b3ab4fa08bf45c12fb945f9adfc5b37c8 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 8 Apr 2021 14:48:03 +0600 Subject: [PATCH 07/25] Introduce Hash32 custom type --- specs/merge/beacon-chain.md | 9 +++++---- specs/merge/fork-choice.md | 4 ++-- specs/merge/validator.md | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index be79cf5b5..a93076001 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -47,6 +47,7 @@ We define the following Python custom types for type hinting and readability: | Name | SSZ equivalent | Description | | - | - | - | | `OpaqueTransaction` | `ByteList[MAX_BYTES_PER_OPAQUE_TRANSACTION]` | a byte-list containing a single [typed transaction envelope](https://eips.ethereum.org/EIPS/eip-2718#opaque-byte-array-rather-than-an-rlp-array) structured as `TransactionType \|\| TransactionPayload` | +| `Hash32` | `Bytes32` | a 256-bit hash | ## Constants @@ -98,8 +99,8 @@ The execution payload included in a `BeaconBlockBody`. ```python class ExecutionPayload(Container): - block_hash: Bytes32 # Hash of execution block - parent_hash: Bytes32 + block_hash: Hash32 # Hash of execution block + parent_hash: Hash32 coinbase: Bytes20 state_root: Bytes32 number: uint64 @@ -118,8 +119,8 @@ The execution payload header included in a `BeaconState`. ```python class ExecutionPayloadHeader(Container): - block_hash: Bytes32 # Hash of execution block - parent_hash: Bytes32 + block_hash: Hash32 # Hash of execution block + parent_hash: Hash32 coinbase: Bytes20 state_root: Bytes32 number: uint64 diff --git a/specs/merge/fork-choice.md b/specs/merge/fork-choice.md index 647a663c2..df45bedd1 100644 --- a/specs/merge/fork-choice.md +++ b/specs/merge/fork-choice.md @@ -30,7 +30,7 @@ This is the modification of the fork choice according to the executable beacon c ```python class PowBlock(Container): - block_hash: Bytes32 + block_hash: Hash32 is_processed: boolean is_valid: boolean total_difficulty: uint256 @@ -38,7 +38,7 @@ class PowBlock(Container): #### `get_pow_block` -Let `get_pow_block(hash: Bytes32) -> PowBlock` be the function that given the hash of the PoW block returns its data. +Let `get_pow_block(hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data. *Note*: The `eth_getBlockByHash` JSON-RPC method does not distinguish invalid blocks from blocks that haven't been processed yet. Either extending this existing method or implementing a new one is required. diff --git a/specs/merge/validator.md b/specs/merge/validator.md index 5b26a21dd..42fe7adcf 100644 --- a/specs/merge/validator.md +++ b/specs/merge/validator.md @@ -48,7 +48,7 @@ Let `get_pow_chain_head() -> PowBlock` be the function that returns the head of ###### `produce_execution_payload` -Let `produce_execution_payload(parent_hash: Bytes32) -> ExecutionPayload` be the function that produces new instance of execution payload. +Let `produce_execution_payload(parent_hash: Hash32) -> ExecutionPayload` be the function that produces new instance of execution payload. The body of this function is implementation dependent. * Set `block.body.execution_payload = get_execution_payload(state)` where: From 334a9b2434f70fe6bb01672f5a8d6c3886b7220f Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 8 Apr 2021 15:26:32 +0600 Subject: [PATCH 08/25] Pass timestamp to execution state transition and payload production --- specs/merge/beacon-chain.md | 14 ++++++++++++-- specs/merge/validator.md | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index a93076001..2793a4579 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -26,6 +26,7 @@ - [Misc](#misc) - [`is_transition_completed`](#is_transition_completed) - [`is_transition_block`](#is_transition_block) + - [`compute_time_at_slot`](#compute_time_at_slot) - [Block processing](#block-processing) - [Execution payload processing](#execution-payload-processing) - [`get_execution_state`](#get_execution_state) @@ -149,6 +150,14 @@ def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> bool return not is_transition_completed(state) and block_body.execution_payload != ExecutionPayload() ``` +#### `compute_time_at_slot` + +```python +def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64: + slots_since_genesis = slot - GENESIS_SLOT + return uint64(state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT) +``` + ### Block processing ```python @@ -171,7 +180,7 @@ The body of the function is implementation dependent. ##### `execution_state_transition` -Let `execution_state_transition(execution_state: ExecutionState, execution_payload: ExecutionPayload) -> None` be the transition function of Ethereum execution state. +Let `execution_state_transition(execution_state: ExecutionState, execution_payload: ExecutionPayload, timestamp: uint64) -> None` be the transition function of Ethereum execution state. The body of the function is implementation dependent. *Note*: `execution_state_transition` must throw `AssertionError` if either the transition itself or one of the pre or post conditions has failed. @@ -193,8 +202,9 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None assert execution_payload.parent_hash == state.latest_execution_payload_header.block_hash assert execution_payload.number == state.latest_execution_payload_header.number + 1 + timestamp = compute_time_at_slot(state, state.slot) execution_state = get_execution_state(state.latest_execution_payload_header.state_root) - execution_state_transition(execution_state, execution_payload) + execution_state_transition(execution_state, body.execution_payload, timestamp) state.latest_execution_payload_header = ExecutionPayloadHeader( block_hash=execution_payload.block_hash, diff --git a/specs/merge/validator.md b/specs/merge/validator.md index 42fe7adcf..2a23fd3e8 100644 --- a/specs/merge/validator.md +++ b/specs/merge/validator.md @@ -48,7 +48,7 @@ Let `get_pow_chain_head() -> PowBlock` be the function that returns the head of ###### `produce_execution_payload` -Let `produce_execution_payload(parent_hash: Hash32) -> ExecutionPayload` be the function that produces new instance of execution payload. +Let `produce_execution_payload(parent_hash: Hash32, timestamp: uint64) -> ExecutionPayload` be the function that produces new instance of execution payload. The body of this function is implementation dependent. * Set `block.body.execution_payload = get_execution_payload(state)` where: @@ -66,5 +66,6 @@ def get_execution_payload(state: BeaconState) -> ExecutionPayload: # Post-merge, normal payload execution_parent_hash = state.latest_execution_payload_header.block_hash - return produce_execution_payload(execution_parent_hash) + timestamp = compute_time_at_slot(state, state.slot) + return produce_execution_payload(execution_parent_hash, timestamp) ``` From ac175fd3255cefbe02c677ca67abb3b329cc573d Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 8 Apr 2021 15:29:42 +0600 Subject: [PATCH 09/25] Replace state with its root in execution_state_transition params --- specs/merge/beacon-chain.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 2793a4579..98312d246 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -29,7 +29,6 @@ - [`compute_time_at_slot`](#compute_time_at_slot) - [Block processing](#block-processing) - [Execution payload processing](#execution-payload-processing) - - [`get_execution_state`](#get_execution_state) - [`execution_state_transition`](#execution_state_transition) - [`process_execution_payload`](#process_execution_payload) @@ -171,16 +170,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: #### Execution payload processing -##### `get_execution_state` - -*Note*: `ExecutionState` class is an abstract class representing Ethereum execution state. - -Let `get_execution_state(execution_state_root: Bytes32) -> ExecutionState` be the function that given the root hash returns a copy of Ethereum execution state. -The body of the function is implementation dependent. - ##### `execution_state_transition` -Let `execution_state_transition(execution_state: ExecutionState, execution_payload: ExecutionPayload, timestamp: uint64) -> None` be the transition function of Ethereum execution state. +Let `execution_state_transition(execution_state_root: Bytes32, execution_payload: ExecutionPayload, timestamp: uint64) -> None` be the transition function of Ethereum execution state. The body of the function is implementation dependent. *Note*: `execution_state_transition` must throw `AssertionError` if either the transition itself or one of the pre or post conditions has failed. @@ -203,8 +195,8 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None assert execution_payload.number == state.latest_execution_payload_header.number + 1 timestamp = compute_time_at_slot(state, state.slot) - execution_state = get_execution_state(state.latest_execution_payload_header.state_root) - execution_state_transition(execution_state, body.execution_payload, timestamp) + execution_state_root = state.latest_execution_payload_header.state_root + execution_state_transition(execution_state_root, body.execution_payload, timestamp) state.latest_execution_payload_header = ExecutionPayloadHeader( block_hash=execution_payload.block_hash, From c4c4dade27ff08bad81171132b4717dd6e3762b7 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 9 Apr 2021 22:50:37 +0600 Subject: [PATCH 10/25] Add missing timestamp in validator.md/get_execution_payload --- specs/merge/validator.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/merge/validator.md b/specs/merge/validator.md index 2a23fd3e8..dccc5727b 100644 --- a/specs/merge/validator.md +++ b/specs/merge/validator.md @@ -62,7 +62,8 @@ def get_execution_payload(state: BeaconState) -> ExecutionPayload: return ExecutionPayload() else: # Signify merge via producing on top of the last PoW block - return produce_execution_payload(pow_block.block_hash) + timestamp = compute_time_at_slot(state, state.slot) + return produce_execution_payload(pow_block.block_hash, timestamp) # Post-merge, normal payload execution_parent_hash = state.latest_execution_payload_header.block_hash From 79230c5f68f975a4765dcd4c0bd9f28a11e427b8 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sat, 10 Apr 2021 03:04:27 +0800 Subject: [PATCH 11/25] Update pyspec builder --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 514f75c50..b337d70ff 100644 --- a/setup.py +++ b/setup.py @@ -313,11 +313,13 @@ def get_pow_chain_head() -> PowBlock: pass -def execution_state_transition(execution_state: ExecutionState, execution_payload: ExecutionPayload) -> None: +def execution_state_transition(execution_state_root: Bytes32, + execution_payload: ExecutionPayload, + timestamp: uint64) -> None: pass -def produce_execution_payload(parent_hash: Bytes32) -> ExecutionPayload: +def produce_execution_payload(parent_hash: Hash32, timestamp: uint64) -> ExecutionPayload: pass""" From cd43d64809acb37344fc13ef48b2b03a60c7c48f Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 12 Apr 2021 22:20:27 +0800 Subject: [PATCH 12/25] Move constants to `eth2spec.test.helpers.constants` --- .../gen_helpers/gen_from_tests/gen.py | 3 +- .../test_process_sync_committee.py | 6 ++-- .../test_process_sync_committee_updates.py | 6 ++-- .../eth2spec/test/altair/fork/test_fork.py | 6 ++-- .../test/altair/sanity/test_blocks.py | 2 +- .../test/altair/unittests/test_helpers.py | 2 +- .../altair/unittests/test_sync_protocol.py | 6 ++-- tests/core/pyspec/eth2spec/test/context.py | 30 ++++--------------- .../test_process_attestation.py | 2 +- .../test_process_chunk_challenge.py | 6 ++-- .../test_process_custody_key_reveal.py | 2 +- .../test_process_custody_slashing.py | 6 ++-- ...est_process_early_derived_secret_reveal.py | 2 +- .../test_process_challenge_deadlines.py | 6 ++-- .../test_process_custody_final_updates.py | 2 +- .../test_process_reveal_deadlines.py | 6 ++-- .../test/custody_game/sanity/test_blocks.py | 6 ++-- .../pyspec/eth2spec/test/helpers/constants.py | 29 ++++++++++++++++++ .../pyspec/eth2spec/test/helpers/typing.py | 4 +++ ...st_process_participation_record_updates.py | 3 +- .../test/phase0/fork_choice/test_get_head.py | 2 +- .../phase0/genesis/test_initialization.py | 2 +- .../test/phase0/genesis/test_validity.py | 2 +- .../test/phase0/rewards/test_basic.py | 3 +- .../eth2spec/test/phase0/rewards/test_leak.py | 3 +- .../test/phase0/sanity/test_blocks.py | 3 +- .../fork_choice/test_on_attestation.py | 3 +- .../validator/test_validator_unittest.py | 2 +- .../unittests/test_get_start_shard.py | 2 +- tests/generators/README.md | 2 +- tests/generators/bls/main.py | 2 +- tests/generators/epoch_processing/main.py | 2 +- tests/generators/finality/main.py | 2 +- tests/generators/fork_choice/main.py | 2 +- tests/generators/forks/main.py | 2 +- tests/generators/genesis/main.py | 2 +- tests/generators/operations/main.py | 2 +- tests/generators/rewards/main.py | 2 +- tests/generators/sanity/main.py | 2 +- tests/generators/shuffling/main.py | 2 +- tests/generators/ssz_generic/main.py | 2 +- tests/generators/ssz_static/main.py | 2 +- 42 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/helpers/constants.py create mode 100644 tests/core/pyspec/eth2spec/test/helpers/typing.py 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 c090869d5..bc63b212b 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 @@ -4,7 +4,8 @@ from typing import Any, Callable, Dict, Iterable, Optional from eth2spec.config import config_util from eth2spec.utils import bls -from eth2spec.test.context import ALL_CONFIGS, TESTGEN_FORKS, SpecForkName, ConfigName +from eth2spec.test.helpers.constants import ALL_CONFIGS, TESTGEN_FORKS +from eth2spec.test.helpers.typing import SpecForkName, ConfigName from eth2spec.gen_helpers.gen_base import gen_runner from eth2spec.gen_helpers.gen_base.gen_typing import TestCase, TestProvider diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index ed9bcac9c..307d0f82d 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -8,12 +8,14 @@ from eth2spec.test.helpers.state import ( state_transition_and_sign_block, transition_to, ) +from eth2spec.test.helpers.constants import ( + PHASE0, + MAINNET, MINIMAL, +) from eth2spec.test.helpers.sync_committee import ( compute_aggregate_sync_committee_signature, ) from eth2spec.test.context import ( - PHASE0, - MAINNET, MINIMAL, expect_assertion_error, with_all_phases_except, with_configs, diff --git a/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py b/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py index 4c5ac0633..7ba2645a2 100644 --- a/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py +++ b/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py @@ -1,10 +1,12 @@ from eth2spec.test.context import ( - PHASE0, - MINIMAL, spec_state_test, with_all_phases_except, with_configs, ) +from eth2spec.test.helpers.constants import ( + PHASE0, + MINIMAL, +) from eth2spec.test.helpers.state import transition_to from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, diff --git a/tests/core/pyspec/eth2spec/test/altair/fork/test_fork.py b/tests/core/pyspec/eth2spec/test/altair/fork/test_fork.py index fb056b72a..1ad39209c 100644 --- a/tests/core/pyspec/eth2spec/test/altair/fork/test_fork.py +++ b/tests/core/pyspec/eth2spec/test/altair/fork/test_fork.py @@ -1,6 +1,4 @@ from eth2spec.test.context import ( - PHASE0, ALTAIR, - MINIMAL, with_phases, with_custom_state, with_configs, @@ -8,6 +6,10 @@ from eth2spec.test.context import ( low_balances, misc_balances, large_validator_set, ) from eth2spec.test.utils import with_meta_tags +from eth2spec.test.helpers.constants import ( + PHASE0, ALTAIR, + MINIMAL, +) from eth2spec.test.helpers.state import ( next_epoch, next_epoch_via_block, diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py index 9f28926d4..48ab6956b 100644 --- a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py @@ -11,8 +11,8 @@ from eth2spec.test.helpers.block import ( from eth2spec.test.helpers.sync_committee import ( compute_aggregate_sync_committee_signature, ) +from eth2spec.test.helpers.constants import PHASE0 from eth2spec.test.context import ( - PHASE0, with_all_phases_except, spec_state_test, ) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_helpers.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_helpers.py index d89ff6d84..c837f06c3 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_helpers.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_helpers.py @@ -1,8 +1,8 @@ from eth2spec.test.context import ( spec_state_test, with_phases, - ALTAIR, ) +from eth2spec.test.helpers.constants import ALTAIR from eth2spec.test.helpers.merkle import build_proof diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py index 4c9b98e0a..9b8c35e76 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py @@ -1,6 +1,4 @@ from eth2spec.test.context import ( - ALTAIR, - MINIMAL, spec_state_test, with_configs, with_phases, @@ -10,6 +8,10 @@ from eth2spec.test.helpers.block import ( build_empty_block, build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.constants import ( + ALTAIR, + MINIMAL, +) from eth2spec.test.helpers.state import ( next_slots, state_transition_and_sign_block, diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 7ae1b9541..002e84136 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -6,11 +6,15 @@ from eth2spec.merge import spec as spec_merge from eth2spec.utils import bls from .exceptions import SkippedTest +from .helpers.constants import ( + PHASE0, ALTAIR, MERGE, SHARDING, CUSTODY_GAME, DAS, + ALL_PHASES, +) from .helpers.genesis import create_genesis_state from .utils import vector_test, with_meta_tags from random import Random -from typing import Any, Callable, NewType, Sequence, TypedDict, Protocol +from typing import Any, Callable, Sequence, TypedDict, Protocol from lru import LRU @@ -23,30 +27,6 @@ def reload_specs(): reload(spec_merge) -# Some of the Spec module functionality is exposed here to deal with phase-specific changes. - -SpecForkName = NewType("SpecForkName", str) -ConfigName = NewType("ConfigName", str) - -PHASE0 = SpecForkName('phase0') -ALTAIR = SpecForkName('altair') - -# Experimental phases (not included in default "ALL_PHASES"): -MERGE = SpecForkName('merge') -SHARDING = SpecForkName('sharding') -CUSTODY_GAME = SpecForkName('custody_game') -DAS = SpecForkName('das') - -ALL_PHASES = (PHASE0, ALTAIR) - -MAINNET = ConfigName('mainnet') -MINIMAL = ConfigName('minimal') - -ALL_CONFIGS = (MINIMAL, MAINNET) - -# The forks that output to the test vectors. -TESTGEN_FORKS = (PHASE0, ALTAIR) - # TODO: currently phases are defined as python modules. # It would be better if they would be more well-defined interfaces for stronger typing. diff --git a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_attestation.py b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_attestation.py index 92633a8c5..707ac0b2e 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_attestation.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_attestation.py @@ -1,9 +1,9 @@ from eth2spec.test.context import ( - CUSTODY_GAME, with_phases, spec_state_test, always_bls, ) +from eth2spec.test.helpers.constants import CUSTODY_GAME from eth2spec.test.helpers.state import transition_to from eth2spec.test.helpers.attestations import ( run_attestation_processing, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_chunk_challenge.py b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_chunk_challenge.py index 69143812f..5a939c108 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_chunk_challenge.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_chunk_challenge.py @@ -6,10 +6,12 @@ from eth2spec.test.helpers.custody import ( from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, ) -from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot -from eth2spec.test.context import ( +from eth2spec.test.helpers.constants import ( CUSTODY_GAME, MINIMAL, +) +from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot +from eth2spec.test.context import ( expect_assertion_error, disable_process_reveal_deadlines, spec_state_test, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_key_reveal.py b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_key_reveal.py index a825d7c75..fa8401228 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_key_reveal.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_key_reveal.py @@ -1,6 +1,6 @@ +from eth2spec.test.helpers.constants import CUSTODY_GAME from eth2spec.test.helpers.custody import get_valid_custody_key_reveal from eth2spec.test.context import ( - CUSTODY_GAME, with_phases, spec_state_test, expect_assertion_error, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_slashing.py b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_slashing.py index 12ac708aa..f554761f3 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_slashing.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_custody_slashing.py @@ -5,12 +5,14 @@ from eth2spec.test.helpers.custody import ( from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, ) +from eth2spec.test.helpers.constants import ( + CUSTODY_GAME, + MINIMAL, +) from eth2spec.test.helpers.keys import privkeys from eth2spec.utils.ssz.ssz_typing import ByteList from eth2spec.test.helpers.state import get_balance, transition_to from eth2spec.test.context import ( - MINIMAL, - CUSTODY_GAME, with_phases, spec_state_test, expect_assertion_error, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_early_derived_secret_reveal.py b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_early_derived_secret_reveal.py index d3da6c580..904c9af4e 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_early_derived_secret_reveal.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/block_processing/test_process_early_derived_secret_reveal.py @@ -1,7 +1,7 @@ +from eth2spec.test.helpers.constants import CUSTODY_GAME from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal from eth2spec.test.helpers.state import next_epoch_via_block, get_balance from eth2spec.test.context import ( - CUSTODY_GAME, with_phases, spec_state_test, expect_assertion_error, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_challenge_deadlines.py b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_challenge_deadlines.py index f0e353cec..42ff54303 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_challenge_deadlines.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_challenge_deadlines.py @@ -7,13 +7,15 @@ from eth2spec.test.helpers.attestations import ( ) from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot from eth2spec.test.context import ( - CUSTODY_GAME, - MINIMAL, spec_state_test, with_phases, with_configs, ) from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing +from eth2spec.test.helpers.constants import ( + CUSTODY_GAME, + MINIMAL, +) from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with from eth2spec.test.custody_game.block_processing.test_process_chunk_challenge import ( diff --git a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_custody_final_updates.py b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_custody_final_updates.py index acc076bce..92c311a29 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_custody_final_updates.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_custody_final_updates.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import ( +from eth2spec.test.helpers.constants import ( CUSTODY_GAME, ) from eth2spec.test.helpers.custody import ( diff --git a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_reveal_deadlines.py b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_reveal_deadlines.py index c82ebd8bb..aec24bca8 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_reveal_deadlines.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/epoch_processing/test_process_reveal_deadlines.py @@ -3,12 +3,14 @@ from eth2spec.test.helpers.custody import ( ) from eth2spec.test.helpers.state import transition_to from eth2spec.test.context import ( - CUSTODY_GAME, - MINIMAL, with_phases, with_configs, spec_state_test, ) +from eth2spec.test.helpers.constants import ( + CUSTODY_GAME, + MINIMAL, +) from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with from eth2spec.test.custody_game.block_processing.test_process_custody_key_reveal import ( run_custody_key_reveal_processing, diff --git a/tests/core/pyspec/eth2spec/test/custody_game/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/custody_game/sanity/test_blocks.py index 88dd54bda..5f5eadef3 100644 --- a/tests/core/pyspec/eth2spec/test/custody_game/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/custody_game/sanity/test_blocks.py @@ -1,14 +1,16 @@ from typing import Dict, Sequence from eth2spec.test.context import ( - CUSTODY_GAME, - MINIMAL, with_phases, spec_state_test, with_configs, ) from eth2spec.test.helpers.attestations import get_valid_on_time_attestation from eth2spec.test.helpers.block import build_empty_block +from eth2spec.test.helpers.constants import ( + CUSTODY_GAME, + MINIMAL, +) from eth2spec.test.helpers.custody import ( get_custody_slashable_test_vector, get_valid_chunk_challenge, diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py new file mode 100644 index 000000000..bffffe348 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -0,0 +1,29 @@ +from .typing import SpecForkName, ConfigName + + +# +# SpecForkName +# +# Some of the Spec module functionality is exposed here to deal with phase-specific changes. +PHASE0 = SpecForkName('phase0') +ALTAIR = SpecForkName('altair') + +# Experimental phases (not included in default "ALL_PHASES"): +MERGE = SpecForkName('merge') +SHARDING = SpecForkName('sharding') +CUSTODY_GAME = SpecForkName('custody_game') +DAS = SpecForkName('das') + +# The forks that pytest runs with. +ALL_PHASES = (PHASE0, ALTAIR) +# The forks that output to the test vectors. +TESTGEN_FORKS = (PHASE0, ALTAIR) + + +# +# Config +# +MAINNET = ConfigName('mainnet') +MINIMAL = ConfigName('minimal') + +ALL_CONFIGS = (MINIMAL, MAINNET) diff --git a/tests/core/pyspec/eth2spec/test/helpers/typing.py b/tests/core/pyspec/eth2spec/test/helpers/typing.py new file mode 100644 index 000000000..04578f64c --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/helpers/typing.py @@ -0,0 +1,4 @@ +from typing import NewType + +SpecForkName = NewType("SpecForkName", str) +ConfigName = NewType("ConfigName", str) diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_participation_record_updates.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_participation_record_updates.py index 978ef5739..c4d4332bc 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_participation_record_updates.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_participation_record_updates.py @@ -1,4 +1,5 @@ -from eth2spec.test.context import PHASE0, spec_state_test, with_phases +from eth2spec.test.context import spec_state_test, with_phases +from eth2spec.test.helpers.constants import PHASE0 from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index c598a3a7f..0822d44c2 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -1,7 +1,6 @@ from eth_utils import encode_hex from eth2spec.test.context import ( - MINIMAL, is_post_altair, spec_state_test, with_all_phases, @@ -9,6 +8,7 @@ from eth2spec.test.context import ( ) from eth2spec.test.helpers.attestations import get_valid_attestation, next_epoch_with_attestations from eth2spec.test.helpers.block import build_empty_block_for_next_slot +from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.fork_choice import ( tick_and_run_on_attestation, tick_and_run_on_block, diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py index 41fbd7726..be9d120b4 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py @@ -1,11 +1,11 @@ from eth2spec.test.context import ( - MINIMAL, is_post_altair, single_phase, spec_test, with_configs, with_all_phases, ) +from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, prepare_random_genesis_deposits, diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py index a7bcaa6d0..91148da1d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py @@ -1,11 +1,11 @@ from eth2spec.test.context import ( - MINIMAL, is_post_altair, spec_test, single_phase, with_configs, with_all_phases, ) +from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_basic.py b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_basic.py index 82dbccc52..511849f8f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_basic.py +++ b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_basic.py @@ -1,4 +1,5 @@ -from eth2spec.test.context import PHASE0, with_all_phases, with_phases, spec_state_test +from eth2spec.test.context import with_all_phases, with_phases, spec_state_test +from eth2spec.test.helpers.constants import PHASE0 import eth2spec.test.helpers.rewards as rewards_helpers diff --git a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_leak.py b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_leak.py index f11b2734f..0ad2491f0 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_leak.py +++ b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_leak.py @@ -1,4 +1,5 @@ -from eth2spec.test.context import PHASE0, with_all_phases, with_phases, spec_state_test +from eth2spec.test.context import with_all_phases, with_phases, spec_state_test +from eth2spec.test.helpers.constants import PHASE0 from eth2spec.test.helpers.rewards import leaking import eth2spec.test.helpers.rewards as rewards_helpers diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index 3efe07b01..9b184b018 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -24,9 +24,8 @@ from eth2spec.test.helpers.multi_operations import ( run_slash_and_exit, run_test_full_random_operations, ) - +from eth2spec.test.helpers.constants import PHASE0, MINIMAL from eth2spec.test.context import ( - PHASE0, MINIMAL, spec_test, spec_state_test, dump_skipping_message, with_phases, with_all_phases, single_phase, expect_assertion_error, always_bls, diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py index 4d5f1ca16..fcc5e2d21 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py @@ -1,6 +1,7 @@ -from eth2spec.test.context import PHASE0, ALTAIR, with_all_phases, spec_state_test +from eth2spec.test.context import with_all_phases, spec_state_test from eth2spec.test.helpers.block import build_empty_block_for_next_slot from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation +from eth2spec.test.helpers.constants import PHASE0, ALTAIR from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot from eth2spec.test.helpers.fork_choice import get_genesis_forkchoice_store diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py index d793db789..fb63839d6 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py @@ -1,8 +1,8 @@ from eth2spec.test.context import ( spec_state_test, always_bls, with_phases, with_all_phases, - PHASE0, ) +from eth2spec.test.helpers.constants import PHASE0 from eth2spec.test.helpers.attestations import build_attestation_data, get_valid_attestation from eth2spec.test.helpers.block import build_empty_block from eth2spec.test.helpers.deposits import prepare_state_and_deposit diff --git a/tests/core/pyspec/eth2spec/test/sharding/unittests/test_get_start_shard.py b/tests/core/pyspec/eth2spec/test/sharding/unittests/test_get_start_shard.py index 41ef754b3..c38f28b2b 100644 --- a/tests/core/pyspec/eth2spec/test/sharding/unittests/test_get_start_shard.py +++ b/tests/core/pyspec/eth2spec/test/sharding/unittests/test_get_start_shard.py @@ -1,8 +1,8 @@ from eth2spec.test.context import ( - SHARDING, with_phases, spec_state_test, ) +from eth2spec.test.helpers.constants import SHARDING from eth2spec.test.helpers.state import next_epoch diff --git a/tests/generators/README.md b/tests/generators/README.md index 5e12e6bfe..731184326 100644 --- a/tests/generators/README.md +++ b/tests/generators/README.md @@ -164,7 +164,7 @@ Another example, to generate tests from pytests: ```python from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators diff --git a/tests/generators/bls/main.py b/tests/generators/bls/main.py index fecc2df7d..3d67c9db3 100644 --- a/tests/generators/bls/main.py +++ b/tests/generators/bls/main.py @@ -12,7 +12,7 @@ from eth_utils import ( import milagro_bls_binding as milagro_bls from eth2spec.utils import bls -from eth2spec.test.context import PHASE0 +from eth2spec.test.helpers.constants import PHASE0 from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing diff --git a/tests/generators/epoch_processing/main.py b/tests/generators/epoch_processing/main.py index e3caf69fa..9efd96534 100644 --- a/tests/generators/epoch_processing/main.py +++ b/tests/generators/epoch_processing/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/finality/main.py b/tests/generators/finality/main.py index 29ab46c39..e50425da4 100644 --- a/tests/generators/finality/main.py +++ b/tests/generators/finality/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/fork_choice/main.py b/tests/generators/fork_choice/main.py index f09bbcc0a..445ee629c 100644 --- a/tests/generators/fork_choice/main.py +++ b/tests/generators/fork_choice/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/forks/main.py b/tests/generators/forks/main.py index 3bec19735..71a4a54de 100644 --- a/tests/generators/forks/main.py +++ b/tests/generators/forks/main.py @@ -1,7 +1,7 @@ from importlib import reload from typing import Iterable -from eth2spec.test.context import PHASE0, ALTAIR, MINIMAL, MAINNET +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MINIMAL, MAINNET from eth2spec.config import config_util from eth2spec.test.altair.fork import test_fork as test_altair_forks from eth2spec.phase0 import spec as spec_phase0 diff --git a/tests/generators/genesis/main.py b/tests/generators/genesis/main.py index 362677c24..3b4d045a3 100644 --- a/tests/generators/genesis/main.py +++ b/tests/generators/genesis/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/operations/main.py b/tests/generators/operations/main.py index f00c4f894..0c1b84c24 100644 --- a/tests/generators/operations/main.py +++ b/tests/generators/operations/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/rewards/main.py b/tests/generators/rewards/main.py index d8115f4cb..2a0f14863 100644 --- a/tests/generators/rewards/main.py +++ b/tests/generators/rewards/main.py @@ -1,7 +1,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR specs = (spec_phase0, spec_altair) diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 90f9a00df..7f7fecc67 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -1,6 +1,6 @@ from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import PHASE0, ALTAIR +from eth2spec.test.helpers.constants import PHASE0, ALTAIR from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators diff --git a/tests/generators/shuffling/main.py b/tests/generators/shuffling/main.py index 091207bca..73b714760 100644 --- a/tests/generators/shuffling/main.py +++ b/tests/generators/shuffling/main.py @@ -6,7 +6,7 @@ from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing from eth2spec.config import config_util from eth2spec.phase0 import spec as spec -from eth2spec.test.context import PHASE0 +from eth2spec.test.helpers.constants import PHASE0 def shuffling_case_fn(seed, count): diff --git a/tests/generators/ssz_generic/main.py b/tests/generators/ssz_generic/main.py index 737f8cda6..e6cd3d976 100644 --- a/tests/generators/ssz_generic/main.py +++ b/tests/generators/ssz_generic/main.py @@ -6,7 +6,7 @@ import ssz_bitvector import ssz_boolean import ssz_uints import ssz_container -from eth2spec.test.context import PHASE0 +from eth2spec.test.helpers.constants import PHASE0 def create_provider(handler_name: str, suite_name: str, case_maker) -> gen_typing.TestProvider: diff --git a/tests/generators/ssz_static/main.py b/tests/generators/ssz_static/main.py index 77a88a8cd..617fb2f02 100644 --- a/tests/generators/ssz_static/main.py +++ b/tests/generators/ssz_static/main.py @@ -9,7 +9,7 @@ from eth2spec.debug import random_value, encode from eth2spec.config import config_util from eth2spec.phase0 import spec as spec_phase0 from eth2spec.altair import spec as spec_altair -from eth2spec.test.context import ALTAIR, TESTGEN_FORKS, MINIMAL, MAINNET +from eth2spec.test.helpers.constants import ALTAIR, TESTGEN_FORKS, MINIMAL, MAINNET from eth2spec.utils.ssz.ssz_typing import Container from eth2spec.utils.ssz.ssz_impl import ( hash_tree_root, From 4bf6331c219b09ca7dc633afee167b1f50c7a5d8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 12 Apr 2021 15:11:21 -0700 Subject: [PATCH 13/25] update remerkleable --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6d9147661..74a96eea8 100644 --- a/setup.py +++ b/setup.py @@ -607,7 +607,7 @@ setup( "py_ecc==5.2.0", "milagro_bls_binding==1.6.3", "dataclasses==0.6", - "remerkleable==0.1.18", + "remerkleable==0.1.19", "ruamel.yaml==0.16.5", "lru-dict==1.1.6", ] From 3ea897d531cdf1b3446b0724dc7db03db42120ed Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 12 Apr 2021 15:27:04 -0700 Subject: [PATCH 14/25] Add sync committee aggregation constant to config --- configs/mainnet/altair.yaml | 6 ++++++ configs/minimal/altair.yaml | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/configs/mainnet/altair.yaml b/configs/mainnet/altair.yaml index 2a2552da4..475cea732 100644 --- a/configs/mainnet/altair.yaml +++ b/configs/mainnet/altair.yaml @@ -51,3 +51,9 @@ MIN_SYNC_COMMITTEE_PARTICIPANTS: 1 MAX_VALID_LIGHT_CLIENT_UPDATES: 8192 # 2**13 (=8192) LIGHT_CLIENT_UPDATE_TIMEOUT: 8192 + + +# Validator +# --------------------------------------------------------------- +# 2**2 (= 4) +TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 4 diff --git a/configs/minimal/altair.yaml b/configs/minimal/altair.yaml index b852e13c0..096941721 100644 --- a/configs/minimal/altair.yaml +++ b/configs/minimal/altair.yaml @@ -51,3 +51,8 @@ MIN_SYNC_COMMITTEE_PARTICIPANTS: 1 MAX_VALID_LIGHT_CLIENT_UPDATES: 32 # [customized] LIGHT_CLIENT_UPDATE_TIMEOUT: 32 + +# Validator +# --------------------------------------------------------------- +# 2**2 (= 4) +TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 4 From 44de07fee924fd010f73a1b4f83086cb1782bb23 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 13 Apr 2021 15:20:45 +0600 Subject: [PATCH 15/25] Replace hash: Hash32 with block_hash: Hash32 Co-authored-by: Hsiao-Wei Wang --- specs/merge/fork-choice.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/specs/merge/fork-choice.md b/specs/merge/fork-choice.md index df45bedd1..ae3917814 100644 --- a/specs/merge/fork-choice.md +++ b/specs/merge/fork-choice.md @@ -38,7 +38,7 @@ class PowBlock(Container): #### `get_pow_block` -Let `get_pow_block(hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data. +Let `get_pow_block(block_hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data. *Note*: The `eth_getBlockByHash` JSON-RPC method does not distinguish invalid blocks from blocks that haven't been processed yet. Either extending this existing method or implementing a new one is required. @@ -113,4 +113,3 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: if ancestor_at_finalized_slot != store.finalized_checkpoint.root: store.justified_checkpoint = state.current_justified_checkpoint ``` - From 13edd20a365d8ac8f018864b806d1552fd2fcef5 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 13 Apr 2021 15:29:07 +0600 Subject: [PATCH 16/25] Change Eth1Data.block_hash type to Hash32 --- specs/merge/beacon-chain.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 98312d246..3a13c1a3d 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -16,6 +16,8 @@ - [Transition](#transition) - [Execution](#execution) - [Containers](#containers) + - [Updated containers](#updated-containers) + - [`Eth1Data`](#eth1data) - [Extended containers](#extended-containers) - [`BeaconBlockBody`](#beaconblockbody) - [`BeaconState`](#beaconstate) @@ -67,6 +69,19 @@ We define the following Python custom types for type hinting and readability: ## Containers +### Modified containers + +#### `Eth1Data` + +*Note*: The only modification is the type of `block_hash` field that is changed to `Hash32`. + +```python +class Eth1Data(Container): + deposit_root: Root + deposit_count: uint64 + block_hash: Hash32 # [Modified in Merge] +``` + ### Extended containers *Note*: Extended SSZ containers inherit all fields from the parent in the original From ad0f1e56207b9170d6609f57aa4cf552f8e3bc49 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 13 Apr 2021 19:08:47 +0600 Subject: [PATCH 17/25] Add timestamp field into ExecutionPayload --- specs/merge/beacon-chain.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 3a13c1a3d..ade05d4b8 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -121,6 +121,7 @@ class ExecutionPayload(Container): number: uint64 gas_limit: uint64 gas_used: uint64 + timestamp: uint64 receipt_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] transactions: List[OpaqueTransaction, MAX_APPLICATION_TRANSACTIONS] @@ -141,6 +142,7 @@ class ExecutionPayloadHeader(Container): number: uint64 gas_limit: uint64 gas_used: uint64 + timestamp: uint64 receipt_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] transactions_root: Root @@ -187,7 +189,7 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: ##### `execution_state_transition` -Let `execution_state_transition(execution_state_root: Bytes32, execution_payload: ExecutionPayload, timestamp: uint64) -> None` be the transition function of Ethereum execution state. +Let `execution_state_transition(execution_state_root: Bytes32, execution_payload: ExecutionPayload) -> None` be the transition function of Ethereum execution state. The body of the function is implementation dependent. *Note*: `execution_state_transition` must throw `AssertionError` if either the transition itself or one of the pre or post conditions has failed. @@ -209,9 +211,10 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None assert execution_payload.parent_hash == state.latest_execution_payload_header.block_hash assert execution_payload.number == state.latest_execution_payload_header.number + 1 - timestamp = compute_time_at_slot(state, state.slot) + assert execution_payload.timestamp == compute_time_at_slot(state, state.slot) + execution_state_root = state.latest_execution_payload_header.state_root - execution_state_transition(execution_state_root, body.execution_payload, timestamp) + execution_state_transition(execution_state_root, body.execution_payload) state.latest_execution_payload_header = ExecutionPayloadHeader( block_hash=execution_payload.block_hash, @@ -221,6 +224,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None number=execution_payload.number, gas_limit=execution_payload.gas_limit, gas_used=execution_payload.gas_used, + timestamp=execution_payload.timestamp, receipt_root=execution_payload.receipt_root, logs_bloom=execution_payload.logs_bloom, transactions_root=hash_tree_root(execution_payload.transactions), From dbbc63b7a3857fbda74b194b238b6ef7a5179f40 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 13 Apr 2021 19:13:54 +0600 Subject: [PATCH 18/25] Replace execution_state_transition with validate_execution_payload --- specs/merge/beacon-chain.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index ade05d4b8..2dc1bbc84 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -16,7 +16,7 @@ - [Transition](#transition) - [Execution](#execution) - [Containers](#containers) - - [Updated containers](#updated-containers) + - [Modified containers](#modified-containers) - [`Eth1Data`](#eth1data) - [Extended containers](#extended-containers) - [`BeaconBlockBody`](#beaconblockbody) @@ -31,7 +31,7 @@ - [`compute_time_at_slot`](#compute_time_at_slot) - [Block processing](#block-processing) - [Execution payload processing](#execution-payload-processing) - - [`execution_state_transition`](#execution_state_transition) + - [`validate_execution_payload`](#validate_execution_payload) - [`process_execution_payload`](#process_execution_payload) @@ -187,13 +187,11 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: #### Execution payload processing -##### `execution_state_transition` +##### `validate_execution_payload` -Let `execution_state_transition(execution_state_root: Bytes32, execution_payload: ExecutionPayload) -> None` be the transition function of Ethereum execution state. +Let `validate_execution_payload(execution_payload: ExecutionPayload) -> boolean` be the function checking whether given `ExecutionPayload` is valid or not. The body of the function is implementation dependent. -*Note*: `execution_state_transition` must throw `AssertionError` if either the transition itself or one of the pre or post conditions has failed. - ##### `process_execution_payload` ```python @@ -213,8 +211,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None assert execution_payload.timestamp == compute_time_at_slot(state, state.slot) - execution_state_root = state.latest_execution_payload_header.state_root - execution_state_transition(execution_state_root, body.execution_payload) + assert validate_execution_payload(execution_payload) state.latest_execution_payload_header = ExecutionPayloadHeader( block_hash=execution_payload.block_hash, From 7d8570d48871b82e260ca09454299fc5edf7ef2a Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 14 Apr 2021 12:53:30 +0600 Subject: [PATCH 19/25] Warn about potential overflows in compute_time_at_slot --- specs/merge/beacon-chain.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 2dc1bbc84..028eb5b84 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -168,6 +168,8 @@ def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> bool #### `compute_time_at_slot` +*Note*: This function is unsafe with respect to overflows and underflows. + ```python def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64: slots_since_genesis = slot - GENESIS_SLOT From 292fd604f8f6073c891694fa3794c98634b9e6b4 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 14 Apr 2021 12:54:49 +0600 Subject: [PATCH 20/25] Replace boolean with bool whenever make sense --- specs/merge/beacon-chain.md | 6 +++--- specs/merge/fork-choice.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 028eb5b84..688f36b47 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -155,14 +155,14 @@ class ExecutionPayloadHeader(Container): #### `is_transition_completed` ```python -def is_transition_completed(state: BeaconState) -> boolean: +def is_transition_completed(state: BeaconState) -> bool: return state.latest_execution_payload_header != ExecutionPayloadHeader() ``` #### `is_transition_block` ```python -def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> boolean: +def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> bool: return not is_transition_completed(state) and block_body.execution_payload != ExecutionPayload() ``` @@ -191,7 +191,7 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: ##### `validate_execution_payload` -Let `validate_execution_payload(execution_payload: ExecutionPayload) -> boolean` be the function checking whether given `ExecutionPayload` is valid or not. +Let `validate_execution_payload(execution_payload: ExecutionPayload) -> bool` be the function checking whether given `ExecutionPayload` is valid or not. The body of the function is implementation dependent. ##### `process_execution_payload` diff --git a/specs/merge/fork-choice.md b/specs/merge/fork-choice.md index ae3917814..34647f45d 100644 --- a/specs/merge/fork-choice.md +++ b/specs/merge/fork-choice.md @@ -47,7 +47,7 @@ Let `get_pow_block(block_hash: Hash32) -> PowBlock` be the function that given t Used by fork-choice handler, `on_block`. ```python -def is_valid_transition_block(block: PowBlock) -> boolean: +def is_valid_transition_block(block: PowBlock) -> bool: is_total_difficulty_reached = block.total_difficulty >= TRANSITION_TOTAL_DIFFICULTY return block.is_valid and is_total_difficulty_reached ``` From 9d79831b568ace7e06b9b52db23bb083632a5980 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 14 Apr 2021 13:03:58 +0600 Subject: [PATCH 21/25] Rename validate_execution_payload to verify_execution_state_transition --- specs/merge/beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 688f36b47..4e0c554d2 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -31,7 +31,7 @@ - [`compute_time_at_slot`](#compute_time_at_slot) - [Block processing](#block-processing) - [Execution payload processing](#execution-payload-processing) - - [`validate_execution_payload`](#validate_execution_payload) + - [`verify_execution_state_transition`](#verify_execution_state_transition) - [`process_execution_payload`](#process_execution_payload) @@ -189,9 +189,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: #### Execution payload processing -##### `validate_execution_payload` +##### `verify_execution_state_transition` -Let `validate_execution_payload(execution_payload: ExecutionPayload) -> bool` be the function checking whether given `ExecutionPayload` is valid or not. +Let `verify_execution_state_transition(execution_payload: ExecutionPayload) -> bool` be the function that verifies given `ExecutionPayload` with respect to execution state transition. The body of the function is implementation dependent. ##### `process_execution_payload` @@ -213,7 +213,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None assert execution_payload.timestamp == compute_time_at_slot(state, state.slot) - assert validate_execution_payload(execution_payload) + assert verify_execution_state_transition(execution_payload) state.latest_execution_payload_header = ExecutionPayloadHeader( block_hash=execution_payload.block_hash, From 320172fb08a0dad653fa3a4a67dce92bce5747b7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 14 Apr 2021 08:02:09 -0500 Subject: [PATCH 22/25] fix lint --- setup.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index b337d70ff..6490f4ffa 100644 --- a/setup.py +++ b/setup.py @@ -313,10 +313,8 @@ def get_pow_chain_head() -> PowBlock: pass -def execution_state_transition(execution_state_root: Bytes32, - execution_payload: ExecutionPayload, - timestamp: uint64) -> None: - pass +def verify_execution_state_transition(execution_payload: ExecutionPayload) -> bool: + return True def produce_execution_payload(parent_hash: Hash32, timestamp: uint64) -> ExecutionPayload: From 35fea7a11b9239e23491f9abfc050d887c8dbd92 Mon Sep 17 00:00:00 2001 From: BenSchZA Date: Wed, 14 Apr 2021 21:37:25 +0200 Subject: [PATCH 23/25] Update copy INVAIANT to INVARIANT --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 0a64307c0..0a95fbb5a 100644 --- a/setup.py +++ b/setup.py @@ -329,7 +329,7 @@ ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS = { } -ALTAIR_INVAIANT_CHECKS = ''' +ALTAIR_INVARIANT_CHECKS = ''' assert ( TIMELY_HEAD_WEIGHT + TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT + SYNC_REWARD_WEIGHT + PROPOSER_WEIGHT ) == WEIGHT_DENOMINATOR''' @@ -414,7 +414,7 @@ def objects_to_spec(spec_object: SpecObject, imports: str, fork: str, ordered_cl if is_altair(fork): altair_ssz_dep_constants_verification = '\n'.join(map(lambda x: 'assert %s == %s' % (x, spec_object.ssz_dep_constants[x]), ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS)) spec += '\n\n\n' + altair_ssz_dep_constants_verification - spec += '\n' + ALTAIR_INVAIANT_CHECKS + spec += '\n' + ALTAIR_INVARIANT_CHECKS spec += '\n' return spec From 26f54d6f22cb561afcb1fa830d47eb4efb441d7e Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 15 Apr 2021 15:49:29 +0800 Subject: [PATCH 24/25] Remove `CONFIG_NAME` from the config files. And add it back to pyspec context for testing --- configs/mainnet/altair.yaml | 2 -- configs/mainnet/custody_game.yaml | 2 -- configs/mainnet/merge.yaml | 2 -- configs/mainnet/phase0.yaml | 2 -- configs/mainnet/sharding.yaml | 2 -- configs/minimal/altair.yaml | 2 -- configs/minimal/custody_game.yaml | 2 -- configs/minimal/merge.yaml | 2 -- configs/minimal/phase0.yaml | 2 -- configs/minimal/sharding.yaml | 2 -- tests/core/pyspec/eth2spec/config/config_util.py | 3 +-- 11 files changed, 1 insertion(+), 22 deletions(-) diff --git a/configs/mainnet/altair.yaml b/configs/mainnet/altair.yaml index 475cea732..44490f982 100644 --- a/configs/mainnet/altair.yaml +++ b/configs/mainnet/altair.yaml @@ -1,7 +1,5 @@ # Mainnet preset - Altair -CONFIG_NAME: "mainnet" - # Updated penalty values # --------------------------------------------------------------- # 3 * 2**24 (= 50,331,648) diff --git a/configs/mainnet/custody_game.yaml b/configs/mainnet/custody_game.yaml index 8039d839b..ecb2dc377 100644 --- a/configs/mainnet/custody_game.yaml +++ b/configs/mainnet/custody_game.yaml @@ -1,7 +1,5 @@ # Mainnet preset - Custody Game -CONFIG_NAME: "mainnet" - # Time parameters # --------------------------------------------------------------- # 2**1 (= 2) epochs, 12.8 minutes diff --git a/configs/mainnet/merge.yaml b/configs/mainnet/merge.yaml index 582e7d642..b4667f5b5 100644 --- a/configs/mainnet/merge.yaml +++ b/configs/mainnet/merge.yaml @@ -1,7 +1,5 @@ # Mainnet preset - The Merge -CONFIG_NAME: "mainnet" - # Fork # --------------------------------------------------------------- MERGE_FORK_VERSION: 0x02000000 diff --git a/configs/mainnet/phase0.yaml b/configs/mainnet/phase0.yaml index ace44dd23..8b902f1c3 100644 --- a/configs/mainnet/phase0.yaml +++ b/configs/mainnet/phase0.yaml @@ -1,7 +1,5 @@ # Mainnet preset -CONFIG_NAME: "mainnet" - # Misc # --------------------------------------------------------------- # 2**6 (= 64) diff --git a/configs/mainnet/sharding.yaml b/configs/mainnet/sharding.yaml index 0e59a674b..4773aa5f5 100644 --- a/configs/mainnet/sharding.yaml +++ b/configs/mainnet/sharding.yaml @@ -1,7 +1,5 @@ # Mainnet preset - Sharding -CONFIG_NAME: "mainnet" - # Fork # --------------------------------------------------------------- SHARDING_FORK_VERSION: 0x03000000 diff --git a/configs/minimal/altair.yaml b/configs/minimal/altair.yaml index 096941721..10bdf318b 100644 --- a/configs/minimal/altair.yaml +++ b/configs/minimal/altair.yaml @@ -1,7 +1,5 @@ # Minimal preset - Altair -CONFIG_NAME: "minimal" - # Updated penalty values # --------------------------------------------------------------- # 3 * 2**24 (= 50,331,648) diff --git a/configs/minimal/custody_game.yaml b/configs/minimal/custody_game.yaml index 1d9393e80..8b8992fb6 100644 --- a/configs/minimal/custody_game.yaml +++ b/configs/minimal/custody_game.yaml @@ -1,7 +1,5 @@ # Minimal preset - Custody Game -CONFIG_NAME: "minimal" - # Time parameters # --------------------------------------------------------------- # 2**1 (= 2) epochs, 12.8 minutes diff --git a/configs/minimal/merge.yaml b/configs/minimal/merge.yaml index e2857917f..394595d02 100644 --- a/configs/minimal/merge.yaml +++ b/configs/minimal/merge.yaml @@ -1,7 +1,5 @@ # Minimal preset - The Merge -CONFIG_NAME: "minimal" - # Fork # --------------------------------------------------------------- MERGE_FORK_VERSION: 0x02000001 diff --git a/configs/minimal/phase0.yaml b/configs/minimal/phase0.yaml index 93337adf8..3624a2702 100644 --- a/configs/minimal/phase0.yaml +++ b/configs/minimal/phase0.yaml @@ -1,7 +1,5 @@ # Minimal preset -CONFIG_NAME: "minimal" - # Misc # --------------------------------------------------------------- diff --git a/configs/minimal/sharding.yaml b/configs/minimal/sharding.yaml index ca1cc1d6b..f32e2827d 100644 --- a/configs/minimal/sharding.yaml +++ b/configs/minimal/sharding.yaml @@ -1,7 +1,5 @@ # Minimal preset - Sharding -CONFIG_NAME: "minimal" - # Fork # --------------------------------------------------------------- SHARDING_FORK_VERSION: 0x03000001 diff --git a/tests/core/pyspec/eth2spec/config/config_util.py b/tests/core/pyspec/eth2spec/config/config_util.py index ee2007600..917cf3a60 100644 --- a/tests/core/pyspec/eth2spec/config/config_util.py +++ b/tests/core/pyspec/eth2spec/config/config_util.py @@ -54,8 +54,7 @@ def load_config_file(configs_dir: str, presets_name: str) -> Dict[str, Any]: out[k] = [int(item) if item.isdigit() else item for item in v] elif isinstance(v, str) and v.startswith("0x"): out[k] = bytes.fromhex(v[2:]) - elif k == "CONFIG_NAME": - out[k] = str(v) else: out[k] = int(v) + out['CONFIG_NAME'] = presets_name return out From c7166a37af400ba174c70db88ceeaa690685f873 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 15 Apr 2021 06:47:11 -0500 Subject: [PATCH 25/25] change eth1data block_hash type to Hash32 in phase 0 --- specs/merge/beacon-chain.md | 16 ---------------- specs/phase0/beacon-chain.md | 4 +++- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 4e0c554d2..a508cb670 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -16,8 +16,6 @@ - [Transition](#transition) - [Execution](#execution) - [Containers](#containers) - - [Modified containers](#modified-containers) - - [`Eth1Data`](#eth1data) - [Extended containers](#extended-containers) - [`BeaconBlockBody`](#beaconblockbody) - [`BeaconState`](#beaconstate) @@ -49,7 +47,6 @@ We define the following Python custom types for type hinting and readability: | Name | SSZ equivalent | Description | | - | - | - | | `OpaqueTransaction` | `ByteList[MAX_BYTES_PER_OPAQUE_TRANSACTION]` | a byte-list containing a single [typed transaction envelope](https://eips.ethereum.org/EIPS/eip-2718#opaque-byte-array-rather-than-an-rlp-array) structured as `TransactionType \|\| TransactionPayload` | -| `Hash32` | `Bytes32` | a 256-bit hash | ## Constants @@ -69,19 +66,6 @@ We define the following Python custom types for type hinting and readability: ## Containers -### Modified containers - -#### `Eth1Data` - -*Note*: The only modification is the type of `block_hash` field that is changed to `Hash32`. - -```python -class Eth1Data(Container): - deposit_root: Root - deposit_count: uint64 - block_hash: Hash32 # [Modified in Merge] -``` - ### Extended containers *Note*: Extended SSZ containers inherit all fields from the parent in the original diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index cbd085bd3..3176d543c 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -157,6 +157,7 @@ We define the following Python custom types for type hinting and readability: | `ValidatorIndex` | `uint64` | a validator registry index | | `Gwei` | `uint64` | an amount in Gwei | | `Root` | `Bytes32` | a Merkle root | +| `Hash32` | `Bytes32` | a 256-bit hash | | `Version` | `Bytes4` | a fork version number | | `DomainType` | `Bytes4` | a domain type | | `ForkDigest` | `Bytes4` | a digest of the current fork data | @@ -164,6 +165,7 @@ We define the following Python custom types for type hinting and readability: | `BLSPubkey` | `Bytes48` | a BLS12-381 public key | | `BLSSignature` | `Bytes96` | a BLS12-381 signature | + ## Constants The following values are (non-configurable) constants used throughout the specification. @@ -374,7 +376,7 @@ class PendingAttestation(Container): class Eth1Data(Container): deposit_root: Root deposit_count: uint64 - block_hash: Bytes32 + block_hash: Hash32 ``` #### `HistoricalBatch`