From fcd905cb3a41758baca11125c3a5a3d73b951d98 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:52:23 +0200 Subject: [PATCH 01/66] Update sync-protocol.md --- specs/altair/light-client/sync-protocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/altair/light-client/sync-protocol.md b/specs/altair/light-client/sync-protocol.md index 2585889bf9..f9b0625dc7 100644 --- a/specs/altair/light-client/sync-protocol.md +++ b/specs/altair/light-client/sync-protocol.md @@ -204,7 +204,7 @@ def is_better_update(new_update: LightClientUpdate, old_update: LightClientUpdat new_has_supermajority = new_num_active_participants * 3 >= max_active_participants * 2 old_has_supermajority = old_num_active_participants * 3 >= max_active_participants * 2 if new_has_supermajority != old_has_supermajority: - return new_has_supermajority > old_has_supermajority + return new_has_supermajority if not new_has_supermajority and new_num_active_participants != old_num_active_participants: return new_num_active_participants > old_num_active_participants From 355a9a3d337ad057159ac5f2f3c77aeac9c337e0 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 9 Aug 2024 12:05:23 +1200 Subject: [PATCH 02/66] Introducing ExecutionPayloadEnvelope --- specs/electra/beacon-chain.md | 79 ++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index cb5ee6a7a9..14e1cca8e3 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -30,12 +30,14 @@ - [`WithdrawalRequest`](#withdrawalrequest) - [`ConsolidationRequest`](#consolidationrequest) - [`PendingConsolidation`](#pendingconsolidation) + - [`ValidatorRequests`](#validatorrequests) + - [`ExecutionPayloadEnvelope`](#executionpayloadenvelope) - [Modified Containers](#modified-containers) - [`AttesterSlashing`](#attesterslashing) + - [`BeaconBlockBody`](#beaconblockbody) - [Extended Containers](#extended-containers) - [`Attestation`](#attestation) - [`IndexedAttestation`](#indexedattestation) - - [`BeaconBlockBody`](#beaconblockbody) - [`ExecutionPayload`](#executionpayload) - [`ExecutionPayloadHeader`](#executionpayloadheader) - [`BeaconState`](#beaconstate) @@ -258,36 +260,35 @@ class PendingConsolidation(Container): target_index: ValidatorIndex ``` -### Modified Containers +#### `ValidatorRequests` -#### `AttesterSlashing` +*Note*: The container is new in EIP????. ```python -class AttesterSlashing(Container): - attestation_1: IndexedAttestation # [Modified in Electra:EIP7549] - attestation_2: IndexedAttestation # [Modified in Electra:EIP7549] +class ValidatorRequests(Container): + deposit_requests: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] + withdrawal_requests: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7002:EIP7251] + consolidation_requests: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251] ``` -### Extended Containers +#### `ExecutionPayloadEnvelope` -#### `Attestation` +*Note*: The container is new in EIP????. ```python -class Attestation(Container): - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [Modified in Electra:EIP7549] - data: AttestationData - signature: BLSSignature - committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] # [New in Electra:EIP7549] +class ExecutionPayloadEnvelope(Container): + execution_payload: ExecutionPayload # [Modified in Electra:EIP6110:EIP7002] + requests: ValidatorRequests ``` -#### `IndexedAttestation` +### Modified Containers + +#### `AttesterSlashing` ```python -class IndexedAttestation(Container): - # [Modified in Electra:EIP7549] - attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - data: AttestationData - signature: BLSSignature +class AttesterSlashing(Container): + attestation_1: IndexedAttestation # [Modified in Electra:EIP7549] + attestation_2: IndexedAttestation # [Modified in Electra:EIP7549] ``` #### `BeaconBlockBody` @@ -305,11 +306,33 @@ class BeaconBlockBody(Container): voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] sync_aggregate: SyncAggregate # Execution - execution_payload: ExecutionPayload # [Modified in Electra:EIP6110:EIP7002] + execution_payload_envelope: ExecutionPayloadEnvelope # [Modified in Electra:EIP????] bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] ``` +### Extended Containers + +#### `Attestation` + +```python +class Attestation(Container): + aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [Modified in Electra:EIP7549] + data: AttestationData + signature: BLSSignature + committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] # [New in Electra:EIP7549] +``` + +#### `IndexedAttestation` + +```python +class IndexedAttestation(Container): + # [Modified in Electra:EIP7549] + attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] + data: AttestationData + signature: BLSSignature +``` + #### `ExecutionPayload` ```python @@ -875,7 +898,7 @@ def process_pending_balance_deposits(state: BeaconState) -> None: if processed_amount + deposit.amount > available_for_processing: break # Deposit fits in the churn, process it. Increase balance and consume churn. - else: + else: increase_balance(state, deposit.index, deposit.amount) processed_amount += deposit.amount # Regardless of how the deposit was handled, we move on in the queue. @@ -946,7 +969,7 @@ def process_effective_balance_updates(state: BeaconState) -> None: ```python def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) - process_withdrawals(state, block.body.execution_payload) # [Modified in Electra:EIP7251] + process_withdrawals(state, block.body.execution_payload_envelope.execution_payload) # [Modified in Electra:EIP7251:EIP????] process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110] process_randao(state, block.body) process_eth1_data(state, block.body) @@ -1056,7 +1079,7 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: ```python def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: - payload = body.execution_payload + payload = body.execution_payload_envelope.execution_payload # Verify consistency of the parent hash with respect to the previous execution payload header assert payload.parent_hash == state.latest_execution_payload_header.block_hash @@ -1126,11 +1149,11 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251] for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) - for_ops(body.execution_payload.deposit_requests, process_deposit_request) # [New in Electra:EIP6110] - # [New in Electra:EIP7002:EIP7251] - for_ops(body.execution_payload.withdrawal_requests, process_withdrawal_request) - # [New in Electra:EIP7251] - for_ops(body.execution_payload.consolidation_requests, process_consolidation_request) + for_ops(body.execution_payload_envelope.requests.deposit_requests, process_deposit_request) # [New in Electra:EIP6110:EIP????] + # [New in Electra:EIP7002:EIP7251:EIP????] + for_ops(body.execution_payload_envelope.requests.withdrawal_requests, process_withdrawal_request) + # [New in Electra:EIP7251:EIP????] + for_ops(body.execution_payload_envelope.requests.consolidation_requests, process_consolidation_request) ``` ##### Attestations From ed9b061fdc93850cf1bba7104dd3b0ebb4e96d2b Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 9 Aug 2024 12:15:54 +1200 Subject: [PATCH 03/66] Comments --- specs/electra/beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 14e1cca8e3..ccc55d59e6 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -970,7 +970,7 @@ def process_effective_balance_updates(state: BeaconState) -> None: def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) process_withdrawals(state, block.body.execution_payload_envelope.execution_payload) # [Modified in Electra:EIP7251:EIP????] - process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110] + process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110:EIP????] process_randao(state, block.body) process_eth1_data(state, block.body) process_operations(state, block.body) # [Modified in Electra:EIP6110:EIP7002:EIP7549:EIP7251] @@ -1075,11 +1075,11 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: ##### Modified `process_execution_payload` -*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type. +*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` and `ExecutionPayloadEnveloped` types. ```python def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: - payload = body.execution_payload_envelope.execution_payload + payload = body.execution_payload_envelope.execution_payload # [Modified in EIP????] # Verify consistency of the parent hash with respect to the previous execution payload header assert payload.parent_hash == state.latest_execution_payload_header.block_hash From 23a669dc29953c7be97a9d962c0e99bdebda0cef Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 9 Aug 2024 15:51:05 +0600 Subject: [PATCH 04/66] Get rid of compute_state_by_epoch_processing_to --- .../test_process_pending_consolidations.py | 11 +++++++---- .../pyspec/eth2spec/test/helpers/epoch_processing.py | 6 ------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py index d750149839..14e151e2e2 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, - compute_state_by_epoch_processing_to, + run_epoch_processing_to, ) from eth2spec.test.context import ( spec_state_test, @@ -219,7 +219,8 @@ def test_pending_consolidation_future_epoch(spec, state): next_epoch_with_full_participation(spec, state) # Obtain state before the call to process_pending_consolidations - state_before_consolidation = compute_state_by_epoch_processing_to(spec, state, "process_pending_consolidations") + state_before_consolidation = state.copy() + run_epoch_processing_to(spec, state_before_consolidation, "process_pending_consolidations") yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") @@ -270,7 +271,8 @@ def test_pending_consolidation_compounding_creds(spec, state): next_epoch_with_full_participation(spec, state) # Obtain state before the call to process_pending_consolidations - state_before_consolidation = compute_state_by_epoch_processing_to(spec, state, "process_pending_consolidations") + state_before_consolidation = state.copy() + run_epoch_processing_to(spec, state_before_consolidation, "process_pending_consolidations") yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") @@ -325,7 +327,8 @@ def test_pending_consolidation_with_pending_deposit(spec, state): next_epoch_with_full_participation(spec, state) # Obtain state before the call to process_pending_balance_deposits - state_before_consolidation = compute_state_by_epoch_processing_to(spec, state, "process_pending_balance_deposits") + state_before_consolidation = state.copy() + run_epoch_processing_to(spec, state_before_consolidation, "process_pending_consolidations") yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") diff --git a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py index 80302e111d..c2b7af5a44 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py +++ b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py @@ -74,9 +74,3 @@ def run_epoch_processing_with(spec, state, process_name: str): yield 'pre', state getattr(spec, process_name)(state) yield 'post', state - - -def compute_state_by_epoch_processing_to(spec, state, process_name: str): - state_copy = state.copy() - run_epoch_processing_to(spec, state_copy, process_name) - return state_copy From f26c9be1567992c6be4aaef3c740bb7501081eef Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 12 Aug 2024 10:24:53 +1200 Subject: [PATCH 05/66] Removing EL requests from ExecutionPayload --- specs/electra/beacon-chain.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index ccc55d59e6..1b95fa35b2 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -356,11 +356,6 @@ class ExecutionPayload(Container): withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] blob_gas_used: uint64 excess_blob_gas: uint64 - deposit_requests: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] - # [New in Electra:EIP7002:EIP7251] - withdrawal_requests: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] - # [New in Electra:EIP7251] - consolidation_requests: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] ``` #### `ExecutionPayloadHeader` From f9ac90200ae0109c0510f784b01bc732fff1812a Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 12 Aug 2024 10:53:47 +1200 Subject: [PATCH 06/66] Updated light-client block -> header function --- specs/electra/light-client/full-node.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/specs/electra/light-client/full-node.md b/specs/electra/light-client/full-node.md index f08a2cc5ed..8bf340419b 100644 --- a/specs/electra/light-client/full-node.md +++ b/specs/electra/light-client/full-node.md @@ -26,9 +26,14 @@ Execution payload data is updated to account for the Electra upgrade. ```python def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: epoch = compute_epoch_at_slot(block.message.slot) - + if epoch >= CAPELLA_FORK_EPOCH: - payload = block.message.body.execution_payload + # [New in Electra:EIP6110:EIP7002:EIP7251:EIP????] + if epoch >= ELECTRA_FORK_EPOCH: + payload = block.message.body.execution_payload_envelope.execution_payload + else: + payload = block.message.body.execution_payload + execution_header = ExecutionPayloadHeader( parent_hash=payload.parent_hash, fee_recipient=payload.fee_recipient, @@ -50,11 +55,12 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: execution_header.blob_gas_used = payload.blob_gas_used execution_header.excess_blob_gas = payload.excess_blob_gas - # [New in Electra:EIP6110:EIP7002:EIP7251] + # [New in Electra:EIP6110:EIP7002:EIP7251:EIP????] if epoch >= ELECTRA_FORK_EPOCH: - execution_header.deposit_requests_root = hash_tree_root(payload.deposit_requests) - execution_header.withdrawal_requests_root = hash_tree_root(payload.withdrawal_requests) - execution_header.consolidation_requests_root = hash_tree_root(payload.consolidation_requests) + requests = block.message.body.execution_payload_envelope.requests + execution_header.deposit_requests_root = hash_tree_root(requests.deposit_requests) + execution_header.withdrawal_requests_root = hash_tree_root(requests.withdrawal_requests) + execution_header.consolidation_requests_root = hash_tree_root(requests.consolidation_requests) execution_branch = ExecutionBranch( compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX)) From e26a3e04b387bf445a6b4119da77630f00ba7683 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 12 Aug 2024 10:54:21 +1200 Subject: [PATCH 07/66] New execution payload global index --- pysetup/spec_builders/electra.py | 1 + specs/electra/light-client/sync-protocol.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/pysetup/spec_builders/electra.py b/pysetup/spec_builders/electra.py index ca02ee927c..bc54b0cc06 100644 --- a/pysetup/spec_builders/electra.py +++ b/pysetup/spec_builders/electra.py @@ -18,4 +18,5 @@ def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]: 'FINALIZED_ROOT_GINDEX_ELECTRA': 'GeneralizedIndex(169)', 'CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(86)', 'NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(87)', + 'EXECUTION_PAYLOAD_GINDEX': 'GeneralizedIndex(50)', } diff --git a/specs/electra/light-client/sync-protocol.md b/specs/electra/light-client/sync-protocol.md index ef9dcd5987..f304211b2b 100644 --- a/specs/electra/light-client/sync-protocol.md +++ b/specs/electra/light-client/sync-protocol.md @@ -41,6 +41,10 @@ Additional documents describes the impact of the upgrade on certain roles: ## Constants +| Name | Value | +| - | - | +| `EXECUTION_PAYLOAD_GINDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload_envelope', 'execution_payload')` (= 50) | + ### Frozen constants Existing `GeneralizedIndex` constants are frozen at their [Altair](../../altair/light-client/sync-protocol.md#constants) values. From 9a2e08808ed60b345124436f268e9ff2fe0789c1 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 12 Aug 2024 20:17:49 +1200 Subject: [PATCH 08/66] requests_root --- specs/electra/beacon-chain.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 1b95fa35b2..e376ce0789 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -381,9 +381,7 @@ class ExecutionPayloadHeader(Container): withdrawals_root: Root blob_gas_used: uint64 excess_blob_gas: uint64 - deposit_requests_root: Root # [New in Electra:EIP6110] - withdrawal_requests_root: Root # [New in Electra:EIP7002:EIP7251] - consolidation_requests_root: Root # [New in Electra:EIP7251] + requests_root: Root # [New in Electra:EIP6110:EIP7002:EIP7251] ``` #### `BeaconState` @@ -1112,9 +1110,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi withdrawals_root=hash_tree_root(payload.withdrawals), blob_gas_used=payload.blob_gas_used, excess_blob_gas=payload.excess_blob_gas, - deposit_requests_root=hash_tree_root(payload.deposit_requests), # [New in Electra:EIP6110] - withdrawal_requests_root=hash_tree_root(payload.withdrawal_requests), # [New in Electra:EIP7002:EIP7251] - consolidation_requests_root=hash_tree_root(payload.consolidation_requests), # [New in Electra:EIP7251] + requests_root=hash_tree_root(body.execution_payload_envelope.requests), # [New in Electra:EIP6110:EIP7002:EIP7251] ) ``` From 858402fc8a481c8110ca7882e79777ace3450be7 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 12:29:27 +1200 Subject: [PATCH 09/66] Updated with requests on block body --- specs/electra/beacon-chain.md | 104 ++-------------------------------- 1 file changed, 6 insertions(+), 98 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index e376ce0789..a70960c4d5 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -31,7 +31,6 @@ - [`ConsolidationRequest`](#consolidationrequest) - [`PendingConsolidation`](#pendingconsolidation) - [`ValidatorRequests`](#validatorrequests) - - [`ExecutionPayloadEnvelope`](#executionpayloadenvelope) - [Modified Containers](#modified-containers) - [`AttesterSlashing`](#attesterslashing) - [`BeaconBlockBody`](#beaconblockbody) @@ -39,7 +38,6 @@ - [`Attestation`](#attestation) - [`IndexedAttestation`](#indexedattestation) - [`ExecutionPayload`](#executionpayload) - - [`ExecutionPayloadHeader`](#executionpayloadheader) - [`BeaconState`](#beaconstate) - [Helper functions](#helper-functions) - [Predicates](#predicates) @@ -80,8 +78,6 @@ - [Withdrawals](#withdrawals) - [Modified `get_expected_withdrawals`](#modified-get_expected_withdrawals) - [Modified `process_withdrawals`](#modified-process_withdrawals) - - [Execution payload](#execution-payload) - - [Modified `process_execution_payload`](#modified-process_execution_payload) - [Operations](#operations) - [Modified `process_operations`](#modified-process_operations) - [Attestations](#attestations) @@ -262,8 +258,6 @@ class PendingConsolidation(Container): #### `ValidatorRequests` -*Note*: The container is new in EIP????. - ```python class ValidatorRequests(Container): deposit_requests: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] @@ -271,16 +265,6 @@ class ValidatorRequests(Container): consolidation_requests: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251] ``` -#### `ExecutionPayloadEnvelope` - -*Note*: The container is new in EIP????. - -```python -class ExecutionPayloadEnvelope(Container): - execution_payload: ExecutionPayload # [Modified in Electra:EIP6110:EIP7002] - requests: ValidatorRequests -``` - ### Modified Containers #### `AttesterSlashing` @@ -306,9 +290,10 @@ class BeaconBlockBody(Container): voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] sync_aggregate: SyncAggregate # Execution - execution_payload_envelope: ExecutionPayloadEnvelope # [Modified in Electra:EIP????] + execution_payload: ExecutionPayload bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + requests: ValidatorRequests # [New in Electra:EIP????] ``` ### Extended Containers @@ -358,32 +343,6 @@ class ExecutionPayload(Container): excess_blob_gas: uint64 ``` -#### `ExecutionPayloadHeader` - -```python -class ExecutionPayloadHeader(Container): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 - transactions_root: Root - withdrawals_root: Root - blob_gas_used: uint64 - excess_blob_gas: uint64 - requests_root: Root # [New in Electra:EIP6110:EIP7002:EIP7251] -``` - #### `BeaconState` ```python @@ -962,7 +921,7 @@ def process_effective_balance_updates(state: BeaconState) -> None: ```python def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) - process_withdrawals(state, block.body.execution_payload_envelope.execution_payload) # [Modified in Electra:EIP7251:EIP????] + process_withdrawals(state, block.body.execution_payload) # [Modified in Electra:EIP7251:EIP????] process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110:EIP????] process_randao(state, block.body) process_eth1_data(state, block.body) @@ -1063,57 +1022,6 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: next_validator_index = ValidatorIndex(next_index % len(state.validators)) state.next_withdrawal_validator_index = next_validator_index ``` - -#### Execution payload - -##### Modified `process_execution_payload` - -*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` and `ExecutionPayloadEnveloped` types. - -```python -def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: - payload = body.execution_payload_envelope.execution_payload # [Modified in EIP????] - - # Verify consistency of the parent hash with respect to the previous execution payload header - assert payload.parent_hash == state.latest_execution_payload_header.block_hash - # Verify prev_randao - assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) - # Verify timestamp - assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) - # Verify commitments are under limit - assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK - # Verify the execution payload is valid - versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments] - assert execution_engine.verify_and_notify_new_payload( - NewPayloadRequest( - execution_payload=payload, - versioned_hashes=versioned_hashes, - parent_beacon_block_root=state.latest_block_header.parent_root, - ) - ) - # Cache execution payload header - state.latest_execution_payload_header = ExecutionPayloadHeader( - parent_hash=payload.parent_hash, - fee_recipient=payload.fee_recipient, - state_root=payload.state_root, - receipts_root=payload.receipts_root, - logs_bloom=payload.logs_bloom, - prev_randao=payload.prev_randao, - block_number=payload.block_number, - gas_limit=payload.gas_limit, - gas_used=payload.gas_used, - timestamp=payload.timestamp, - extra_data=payload.extra_data, - base_fee_per_gas=payload.base_fee_per_gas, - block_hash=payload.block_hash, - transactions_root=hash_tree_root(payload.transactions), - withdrawals_root=hash_tree_root(payload.withdrawals), - blob_gas_used=payload.blob_gas_used, - excess_blob_gas=payload.excess_blob_gas, - requests_root=hash_tree_root(body.execution_payload_envelope.requests), # [New in Electra:EIP6110:EIP7002:EIP7251] - ) -``` - #### Operations ##### Modified `process_operations` @@ -1140,11 +1048,11 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251] for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) - for_ops(body.execution_payload_envelope.requests.deposit_requests, process_deposit_request) # [New in Electra:EIP6110:EIP????] + for_ops(body.requests.deposit_requests, process_deposit_request) # [New in Electra:EIP6110:EIP????] # [New in Electra:EIP7002:EIP7251:EIP????] - for_ops(body.execution_payload_envelope.requests.withdrawal_requests, process_withdrawal_request) + for_ops(body.requests.withdrawal_requests, process_withdrawal_request) # [New in Electra:EIP7251:EIP????] - for_ops(body.execution_payload_envelope.requests.consolidation_requests, process_consolidation_request) + for_ops(body.requests.consolidation_requests, process_consolidation_request) ``` ##### Attestations From 794b942c9b07450abbe31c0a1e3b8772397408dc Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 17:47:50 +1200 Subject: [PATCH 10/66] Undo execution_payload gsync change --- pysetup/spec_builders/electra.py | 1 - specs/electra/light-client/sync-protocol.md | 4 ---- 2 files changed, 5 deletions(-) diff --git a/pysetup/spec_builders/electra.py b/pysetup/spec_builders/electra.py index bc54b0cc06..ca02ee927c 100644 --- a/pysetup/spec_builders/electra.py +++ b/pysetup/spec_builders/electra.py @@ -18,5 +18,4 @@ def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]: 'FINALIZED_ROOT_GINDEX_ELECTRA': 'GeneralizedIndex(169)', 'CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(86)', 'NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(87)', - 'EXECUTION_PAYLOAD_GINDEX': 'GeneralizedIndex(50)', } diff --git a/specs/electra/light-client/sync-protocol.md b/specs/electra/light-client/sync-protocol.md index f304211b2b..ef9dcd5987 100644 --- a/specs/electra/light-client/sync-protocol.md +++ b/specs/electra/light-client/sync-protocol.md @@ -41,10 +41,6 @@ Additional documents describes the impact of the upgrade on certain roles: ## Constants -| Name | Value | -| - | - | -| `EXECUTION_PAYLOAD_GINDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload_envelope', 'execution_payload')` (= 50) | - ### Frozen constants Existing `GeneralizedIndex` constants are frozen at their [Altair](../../altair/light-client/sync-protocol.md#constants) values. From 5c88de8bb917d3384c5b278ad656bbc37b02c80d Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 17:50:31 +1200 Subject: [PATCH 11/66] Remove requests in execution_payload from full-node lightclient spec --- specs/electra/light-client/full-node.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/specs/electra/light-client/full-node.md b/specs/electra/light-client/full-node.md index 8bf340419b..0393aaec24 100644 --- a/specs/electra/light-client/full-node.md +++ b/specs/electra/light-client/full-node.md @@ -26,14 +26,9 @@ Execution payload data is updated to account for the Electra upgrade. ```python def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: epoch = compute_epoch_at_slot(block.message.slot) - - if epoch >= CAPELLA_FORK_EPOCH: - # [New in Electra:EIP6110:EIP7002:EIP7251:EIP????] - if epoch >= ELECTRA_FORK_EPOCH: - payload = block.message.body.execution_payload_envelope.execution_payload - else: - payload = block.message.body.execution_payload + if epoch >= CAPELLA_FORK_EPOCH: + payload = block.message.body.execution_payload execution_header = ExecutionPayloadHeader( parent_hash=payload.parent_hash, fee_recipient=payload.fee_recipient, @@ -55,13 +50,6 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: execution_header.blob_gas_used = payload.blob_gas_used execution_header.excess_blob_gas = payload.excess_blob_gas - # [New in Electra:EIP6110:EIP7002:EIP7251:EIP????] - if epoch >= ELECTRA_FORK_EPOCH: - requests = block.message.body.execution_payload_envelope.requests - execution_header.deposit_requests_root = hash_tree_root(requests.deposit_requests) - execution_header.withdrawal_requests_root = hash_tree_root(requests.withdrawal_requests) - execution_header.consolidation_requests_root = hash_tree_root(requests.consolidation_requests) - execution_branch = ExecutionBranch( compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX)) else: From 666967502b357adfab907d64a656b0f7e5803afe Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 18:16:11 +1200 Subject: [PATCH 12/66] Test updates --- .../test/electra/sanity/blocks/test_blocks.py | 8 +++---- .../sanity/blocks/test_deposit_transition.py | 10 ++++----- .../pyspec/eth2spec/test/helpers/block.py | 7 +++++- .../test/helpers/execution_payload.py | 22 +------------------ 4 files changed, 16 insertions(+), 31 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 9fa4d609fc..8f890b4501 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -41,7 +41,7 @@ def test_basic_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawal_requests = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -77,7 +77,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): source_address=address, validator_pubkey=validator_pubkey, ) - block.body.execution_payload.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawal_requests = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -130,7 +130,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block_2 = build_empty_block_for_next_slot(spec, state) - block_2.body.execution_payload.withdrawal_requests = [withdrawal_request] + block_2.body.requests.withdrawal_requests = [withdrawal_request] block_2.body.execution_payload.block_hash = compute_el_block_hash(spec, block_2.body.execution_payload, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) @@ -163,7 +163,7 @@ def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state): ) block = build_empty_block_for_next_slot(spec, state) block.body.voluntary_exits = signed_voluntary_exits - block.body.execution_payload.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawal_requests = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py index 4b8c1cd4f8..a0b3b83956 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py @@ -38,7 +38,7 @@ def run_deposit_transition_block(spec, state, block, top_up_keys=[], valid=True) # Check that deposits are applied if valid: expected_pubkeys = [d.data.pubkey for d in block.body.deposits] - deposit_requests = block.body.execution_payload.deposit_requests + deposit_requests = block.body.requests.deposit_requests expected_pubkeys = expected_pubkeys + [d.pubkey for d in deposit_requests if (d.pubkey not in top_up_keys)] actual_pubkeys = [v.pubkey for v in state.validators[len(state.validators) - len(expected_pubkeys):]] @@ -102,7 +102,7 @@ def prepare_state_and_block(spec, # Assign deposits and deposit requests block.body.deposits = deposits - block.body.execution_payload.deposit_requests = deposit_requests + block.body.requests.deposit_requests = deposit_requests block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) return state, block @@ -120,7 +120,7 @@ def test_deposit_transition__start_index_is_set(spec, state): yield from run_deposit_transition_block(spec, state, block) # deposit_requests_start_index must be set to the index of the first request - assert state.deposit_requests_start_index == block.body.execution_payload.deposit_requests[0].index + assert state.deposit_requests_start_index == block.body.requests.deposit_requests[0].index @with_phases([ELECTRA]) @@ -219,7 +219,7 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Artificially assign deposit's pubkey to a deposit request of the same block top_up_keys = [block.body.deposits[0].data.pubkey] - block.body.execution_payload.deposit_requests[0].pubkey = top_up_keys[0] + block.body.requests.deposit_requests[0].pubkey = top_up_keys[0] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) pre_pending_deposits = len(state.pending_balance_deposits) @@ -229,5 +229,5 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Check the top up assert len(state.pending_balance_deposits) == pre_pending_deposits + 2 assert state.pending_balance_deposits[pre_pending_deposits].amount == block.body.deposits[0].data.amount - amount_from_deposit = block.body.execution_payload.deposit_requests[0].amount + amount_from_deposit = block.body.requests.deposit_requests[0].amount assert state.pending_balance_deposits[pre_pending_deposits + 1].amount == amount_from_deposit diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 96a0155732..4aa593898c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.execution_payload import build_empty_execution_payload from eth2spec.test.helpers.execution_payload import build_empty_signed_execution_payload_header -from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732 +from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732, is_post_electra from eth2spec.test.helpers.keys import privkeys, whisk_ks_initial, whisk_ks_final from eth2spec.utils import bls from eth2spec.utils.bls import only_with_bls @@ -126,6 +126,11 @@ def build_empty_block(spec, state, slot=None, proposer_index=None): if is_post_bellatrix(spec): empty_block.body.execution_payload = build_empty_execution_payload(spec, state) + if is_post_electra(spec): + empty_block.body.requests.deposit_requests = [] + empty_block.body.requests.withdrawal_requests = [] + empty_block.body.requests.consolidation_requests = [] + if is_post_whisk(spec): # Whisk opening proof ####### diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 1fbb12d7ba..647f6adb5c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -49,10 +49,6 @@ def get_execution_payload_header(spec, execution_payload): if is_post_deneb(spec): payload_header.blob_gas_used = execution_payload.blob_gas_used payload_header.excess_blob_gas = execution_payload.excess_blob_gas - if is_post_electra(spec): - payload_header.deposit_requests_root = spec.hash_tree_root(execution_payload.deposit_requests) - payload_header.withdrawal_requests_root = spec.hash_tree_root(execution_payload.withdrawal_requests) - payload_header.consolidation_requests_root = spec.hash_tree_root(execution_payload.consolidation_requests) return payload_header @@ -74,8 +70,7 @@ def compute_el_header_block_hash(spec, payload_header, transactions_trie_root, withdrawals_trie_root=None, - parent_beacon_block_root=None, - requests_trie_root=None): + parent_beacon_block_root=None): """ Computes the RLP execution block hash described by an `ExecutionPayloadHeader`. """ @@ -126,9 +121,6 @@ def compute_el_header_block_hash(spec, execution_payload_header_rlp.append((big_endian_int, payload_header.excess_blob_gas)) # parent_beacon_root execution_payload_header_rlp.append((Binary(32, 32), parent_beacon_block_root)) - if is_post_electra(spec): - # requests_root - execution_payload_header_rlp.append((Binary(32, 32), requests_trie_root)) sedes = List([schema for schema, _ in execution_payload_header_rlp]) values = [value for _, value in execution_payload_header_rlp] @@ -216,13 +208,6 @@ def compute_el_block_hash(spec, payload, pre_state): withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded) if is_post_deneb(spec): parent_beacon_block_root = pre_state.latest_block_header.hash_tree_root() - if is_post_electra(spec): - requests_encoded = [] - requests_encoded += [get_deposit_request_rlp_bytes(request) for request in payload.deposit_requests] - requests_encoded += [get_withdrawal_request_rlp_bytes(request) for request in payload.withdrawal_requests] - requests_encoded += [get_consolidation_request_rlp_bytes(request) for request in payload.consolidation_requests] - - requests_trie_root = compute_trie_root_from_indexed_data(requests_encoded) payload_header = get_execution_payload_header(spec, payload) @@ -232,7 +217,6 @@ def compute_el_block_hash(spec, payload, pre_state): transactions_trie_root, withdrawals_trie_root, parent_beacon_block_root, - requests_trie_root, ) @@ -296,10 +280,6 @@ def build_empty_execution_payload(spec, state, randao_mix=None): if is_post_deneb(spec): payload.blob_gas_used = 0 payload.excess_blob_gas = 0 - if is_post_electra(spec): - payload.deposit_requests = [] - payload.withdrawal_requests = [] - payload.consolidation_requests = [] payload.block_hash = compute_el_block_hash(spec, payload, state) From 4185c00d233e982ace4af025a06eaf7d7dc0991b Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 20:53:44 +1200 Subject: [PATCH 13/66] Fork fix and tests --- specs/electra/fork.md | 23 +------------------ .../eth2spec/test/helpers/electra/fork.py | 3 ++- .../test/helpers/execution_payload.py | 8 +------ .../pyspec/eth2spec/test/helpers/genesis.py | 4 ---- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/specs/electra/fork.md b/specs/electra/fork.md index fab02ddf25..44c41ac0bf 100644 --- a/specs/electra/fork.md +++ b/specs/electra/fork.md @@ -72,28 +72,7 @@ an irregular state change is made to upgrade to Electra. ```python def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState: epoch = deneb.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, - 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, - blob_gas_used=pre.latest_execution_payload_header.blob_gas_used, - excess_blob_gas=pre.latest_execution_payload_header.excess_blob_gas, - deposit_requests_root=Root(), # [New in Electra:EIP6110] - withdrawal_requests_root=Root(), # [New in Electra:EIP7002] - consolidation_requests_root=Root(), # [New in Electra:EIP7251] - ) + latest_execution_payload_header = pre.latest_execution_payload_header exit_epochs = [v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH] if not exit_epochs: diff --git a/tests/core/pyspec/eth2spec/test/helpers/electra/fork.py b/tests/core/pyspec/eth2spec/test/helpers/electra/fork.py index 0067a8cc07..886fc7cce0 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/electra/fork.py +++ b/tests/core/pyspec/eth2spec/test/helpers/electra/fork.py @@ -38,13 +38,14 @@ def run_fork_test(post_spec, pre_state): 'next_withdrawal_index', 'next_withdrawal_validator_index', # Deep history valid from Capella onwards 'historical_summaries', + 'latest_execution_payload_header' ] for field in stable_fields: assert getattr(pre_state, field) == getattr(post_state, field) # Modified fields - modified_fields = ['fork', 'latest_execution_payload_header'] + modified_fields = ['fork'] for field in modified_fields: assert getattr(pre_state, field) != getattr(post_state, field) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 647f6adb5c..c2876133d4 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -7,12 +7,7 @@ from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.debug.random_value import get_random_bytes_list from eth2spec.test.helpers.withdrawals import get_expected_withdrawals -from eth2spec.test.helpers.forks import ( - is_post_capella, - is_post_deneb, - is_post_electra, - is_post_eip7732, -) +from eth2spec.test.helpers.forks import is_post_capella, is_post_deneb, is_post_eip7732 def get_execution_payload_header(spec, execution_payload): @@ -201,7 +196,6 @@ def compute_el_block_hash(spec, payload, pre_state): withdrawals_trie_root = None parent_beacon_block_root = None - requests_trie_root = None if is_post_capella(spec): withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals] diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 95c1e97e55..bc7d891855 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -66,14 +66,11 @@ def get_sample_genesis_execution_payload_header(spec, transactions_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") withdrawals_trie_root = None parent_beacon_block_root = None - requests_trie_root = None if is_post_capella(spec): withdrawals_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") if is_post_deneb(spec): parent_beacon_block_root = bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000") - if is_post_electra(spec): - requests_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") payload_header.block_hash = compute_el_header_block_hash( spec, @@ -81,7 +78,6 @@ def get_sample_genesis_execution_payload_header(spec, transactions_trie_root, withdrawals_trie_root, parent_beacon_block_root, - requests_trie_root, ) return payload_header From a378e8d03b0ed58da37ab8d5caa378dd349ca89b Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 13 Aug 2024 15:19:10 +0600 Subject: [PATCH 14/66] Update correlation penalty computation --- specs/electra/beacon-chain.md | 24 ++++++++++- .../test_process_slashings.py | 40 +++++++++++-------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index cb5ee6a7a9..bfd3b18e91 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -813,7 +813,7 @@ def process_epoch(state: BeaconState) -> None: process_inactivity_updates(state) process_rewards_and_penalties(state) process_registry_updates(state) # [Modified in Electra:EIP7251] - process_slashings(state) + process_slashings(state) # [Modified in Electra:EIP7251] process_eth1_data_reset(state) process_pending_balance_deposits(state) # [New in Electra:EIP7251] process_pending_consolidations(state) # [New in Electra:EIP7251] @@ -850,6 +850,28 @@ def process_registry_updates(state: BeaconState) -> None: validator.activation_epoch = activation_epoch ``` +#### Modified `process_slashings` + +*Note*: The function `process_slashings` is modified to use a new algorithm to compute correlation penalty. + +```python +def process_slashings(state: BeaconState) -> None: + epoch = get_current_epoch(state) + total_balance = get_total_active_balance(state) + adjusted_total_slashing_balance = min( + sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX, + total_balance + ) + increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid uint64 overflow + penalty_per_effective_balance_increment = adjusted_total_slashing_balance // (total_balance // increment) + for index, validator in enumerate(state.validators): + if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: + effective_balance_increments = validator.effective_balance // increment + # [Modified in Electra:EIP7251] + penalty = penalty_per_effective_balance_increment * effective_balance_increments + decrease_balance(state, ValidatorIndex(index), penalty) +``` + #### New `process_pending_balance_deposits` ```python diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py index 172243077d..24bc843e5f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py @@ -3,7 +3,11 @@ from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, run_epoch_processing_to ) -from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix +from eth2spec.test.helpers.forks import ( + is_post_altair, + is_post_bellatrix, + is_post_electra, +) from eth2spec.test.helpers.random import randomize_state from eth2spec.test.helpers.state import has_active_balance_differential from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators @@ -40,6 +44,18 @@ def get_slashing_multiplier(spec): return spec.PROPORTIONAL_SLASHING_MULTIPLIER +def _compute_expected_correlation_penalty(spec, effective_balance, total_slashed_balance, total_balance): + if is_post_electra(spec): + return ((get_slashing_multiplier(spec) * total_slashed_balance) + // (total_balance // spec.EFFECTIVE_BALANCE_INCREMENT) + * (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT)) + else: + return (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT + * (get_slashing_multiplier(spec) * total_slashed_balance) + // total_balance + * spec.EFFECTIVE_BALANCE_INCREMENT) + + def _setup_process_slashings_test(spec, state, not_slashable_set=set()): # Slashed count to ensure that enough validators are slashed to induce maximum penalties slashed_count = min( @@ -99,7 +115,8 @@ def test_minimal_penalty(spec, state): # # Just the bare minimum for this one validator - state.balances[0] = state.validators[0].effective_balance = spec.config.EJECTION_BALANCE + state.balances[0] = state.validators[0].effective_balance = ( + spec.config.EJECTION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT) # All the other validators get the maximum. for i in range(1, len(state.validators)): state.validators[i].effective_balance = state.balances[i] = spec.MAX_EFFECTIVE_BALANCE @@ -119,15 +136,10 @@ def test_minimal_penalty(spec, state): spec.process_slashings(state) yield 'post', state - expected_penalty = ( - state.validators[0].effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT - * (get_slashing_multiplier(spec) * total_penalties) - // total_balance - * spec.EFFECTIVE_BALANCE_INCREMENT - ) + expected_penalty = _compute_expected_correlation_penalty( + spec, state.validators[0].effective_balance, total_penalties, total_balance) - assert expected_penalty == 0 - assert state.balances[0] == pre_slash_balances[0] + assert state.balances[0] == pre_slash_balances[0] - expected_penalty @with_all_phases @@ -181,12 +193,8 @@ def test_scaled_penalties(spec, state): for i in slashed_indices: v = state.validators[i] - expected_penalty = ( - v.effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT - * (get_slashing_multiplier(spec) * total_penalties) - // (total_balance) - * spec.EFFECTIVE_BALANCE_INCREMENT - ) + expected_penalty = _compute_expected_correlation_penalty( + spec, v.effective_balance, total_penalties, total_balance) assert state.balances[i] == pre_slash_balances[i] - expected_penalty From fa78e0d30194e08e6c3b329ce75271cb63107dd8 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Tue, 13 Aug 2024 21:24:28 +1200 Subject: [PATCH 15/66] PR comments --- specs/electra/beacon-chain.md | 31 ++++++++++--------- specs/electra/light-client/fork.md | 23 +------------- specs/electra/light-client/sync-protocol.md | 9 ------ .../test/electra/sanity/blocks/test_blocks.py | 8 ++--- .../sanity/blocks/test_deposit_transition.py | 10 +++--- .../pyspec/eth2spec/test/helpers/block.py | 6 ++-- 6 files changed, 30 insertions(+), 57 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index a70960c4d5..7decb37659 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -30,7 +30,7 @@ - [`WithdrawalRequest`](#withdrawalrequest) - [`ConsolidationRequest`](#consolidationrequest) - [`PendingConsolidation`](#pendingconsolidation) - - [`ValidatorRequests`](#validatorrequests) + - [`ExecutionLayerRequests`](#executionlayerrequests) - [Modified Containers](#modified-containers) - [`AttesterSlashing`](#attesterslashing) - [`BeaconBlockBody`](#beaconblockbody) @@ -256,13 +256,16 @@ class PendingConsolidation(Container): target_index: ValidatorIndex ``` -#### `ValidatorRequests` +#### `ExecutionLayerRequests` + +*Note*: This container contains request from the execution layer that are received in the Execution Payload via +Engine API. These requests are required for CL state transition (see **BeaconBlockBody**). ```python -class ValidatorRequests(Container): - deposit_requests: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] - withdrawal_requests: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7002:EIP7251] - consolidation_requests: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251] +class ExecutionLayerRequests(Container): + deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] + withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7002:EIP7251] + consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251] ``` ### Modified Containers @@ -293,7 +296,7 @@ class BeaconBlockBody(Container): execution_payload: ExecutionPayload bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - requests: ValidatorRequests # [New in Electra:EIP????] + requests: ExecutionLayerRequests # [New in Electra] ``` ### Extended Containers @@ -921,8 +924,8 @@ def process_effective_balance_updates(state: BeaconState) -> None: ```python def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) - process_withdrawals(state, block.body.execution_payload) # [Modified in Electra:EIP7251:EIP????] - process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110:EIP????] + process_withdrawals(state, block.body.execution_payload) # [Modified in Electra:EIP7251] + process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110] process_randao(state, block.body) process_eth1_data(state, block.body) process_operations(state, block.body) # [Modified in Electra:EIP6110:EIP7002:EIP7549:EIP7251] @@ -1048,11 +1051,11 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251] for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) - for_ops(body.requests.deposit_requests, process_deposit_request) # [New in Electra:EIP6110:EIP????] - # [New in Electra:EIP7002:EIP7251:EIP????] - for_ops(body.requests.withdrawal_requests, process_withdrawal_request) - # [New in Electra:EIP7251:EIP????] - for_ops(body.requests.consolidation_requests, process_consolidation_request) + for_ops(body.requests.deposits, process_deposit_request) # [New in Electra:EIP6110] + # [New in Electra:EIP7002:EIP7251] + for_ops(body.requests.withdrawals, process_withdrawal_request) + # [New in Electra:EIP7251] + for_ops(body.requests.consolidations, process_consolidation_request) ``` ##### Attestations diff --git a/specs/electra/light-client/fork.md b/specs/electra/light-client/fork.md index d613df56a9..a315146b0e 100644 --- a/specs/electra/light-client/fork.md +++ b/specs/electra/light-client/fork.md @@ -39,28 +39,7 @@ A Electra `LightClientStore` can still process earlier light client data. In ord def upgrade_lc_header_to_electra(pre: deneb.LightClientHeader) -> LightClientHeader: return LightClientHeader( beacon=pre.beacon, - execution=ExecutionPayloadHeader( - parent_hash=pre.execution.parent_hash, - fee_recipient=pre.execution.fee_recipient, - state_root=pre.execution.state_root, - receipts_root=pre.execution.receipts_root, - logs_bloom=pre.execution.logs_bloom, - prev_randao=pre.execution.prev_randao, - block_number=pre.execution.block_number, - gas_limit=pre.execution.gas_limit, - gas_used=pre.execution.gas_used, - timestamp=pre.execution.timestamp, - extra_data=pre.execution.extra_data, - base_fee_per_gas=pre.execution.base_fee_per_gas, - block_hash=pre.execution.block_hash, - transactions_root=pre.execution.transactions_root, - withdrawals_root=pre.execution.withdrawals_root, - blob_gas_used=pre.execution.blob_gas_used, - excess_blob_gas=pre.execution.blob_gas_used, - deposit_requests_root=Root(), # [New in Electra:EIP6110] - withdrawal_requests_root=Root(), # [New in Electra:EIP7002:EIP7251] - consolidation_requests_root=Root(), # [New in Electra:EIP7251] - ), + execution=pre.execution, execution_branch=pre.execution_branch, ) ``` diff --git a/specs/electra/light-client/sync-protocol.md b/specs/electra/light-client/sync-protocol.md index ef9dcd5987..26da70ee34 100644 --- a/specs/electra/light-client/sync-protocol.md +++ b/specs/electra/light-client/sync-protocol.md @@ -159,15 +159,6 @@ def get_lc_execution_root(header: LightClientHeader) -> Root: def is_valid_light_client_header(header: LightClientHeader) -> bool: epoch = compute_epoch_at_slot(header.beacon.slot) - # [New in Electra:EIP6110:EIP7002:EIP7251] - if epoch < ELECTRA_FORK_EPOCH: - if ( - header.execution.deposit_requests_root != Root() - or header.execution.withdrawal_requests_root != Root() - or header.execution.consolidation_requests_root != Root() - ): - return False - if epoch < DENEB_FORK_EPOCH: if header.execution.blob_gas_used != uint64(0) or header.execution.excess_blob_gas != uint64(0): return False diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 8f890b4501..8371e71f66 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -41,7 +41,7 @@ def test_basic_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block = build_empty_block_for_next_slot(spec, state) - block.body.requests.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -77,7 +77,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): source_address=address, validator_pubkey=validator_pubkey, ) - block.body.requests.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -130,7 +130,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block_2 = build_empty_block_for_next_slot(spec, state) - block_2.body.requests.withdrawal_requests = [withdrawal_request] + block_2.body.requests.withdrawals = [withdrawal_request] block_2.body.execution_payload.block_hash = compute_el_block_hash(spec, block_2.body.execution_payload, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) @@ -163,7 +163,7 @@ def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state): ) block = build_empty_block_for_next_slot(spec, state) block.body.voluntary_exits = signed_voluntary_exits - block.body.requests.withdrawal_requests = [withdrawal_request] + block.body.requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py index a0b3b83956..98fc707d41 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py @@ -38,7 +38,7 @@ def run_deposit_transition_block(spec, state, block, top_up_keys=[], valid=True) # Check that deposits are applied if valid: expected_pubkeys = [d.data.pubkey for d in block.body.deposits] - deposit_requests = block.body.requests.deposit_requests + deposit_requests = block.body.requests.deposits expected_pubkeys = expected_pubkeys + [d.pubkey for d in deposit_requests if (d.pubkey not in top_up_keys)] actual_pubkeys = [v.pubkey for v in state.validators[len(state.validators) - len(expected_pubkeys):]] @@ -102,7 +102,7 @@ def prepare_state_and_block(spec, # Assign deposits and deposit requests block.body.deposits = deposits - block.body.requests.deposit_requests = deposit_requests + block.body.requests.deposits = deposit_requests block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) return state, block @@ -120,7 +120,7 @@ def test_deposit_transition__start_index_is_set(spec, state): yield from run_deposit_transition_block(spec, state, block) # deposit_requests_start_index must be set to the index of the first request - assert state.deposit_requests_start_index == block.body.requests.deposit_requests[0].index + assert state.deposit_requests_start_index == block.body.requests.deposits[0].index @with_phases([ELECTRA]) @@ -219,7 +219,7 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Artificially assign deposit's pubkey to a deposit request of the same block top_up_keys = [block.body.deposits[0].data.pubkey] - block.body.requests.deposit_requests[0].pubkey = top_up_keys[0] + block.body.requests.deposits[0].pubkey = top_up_keys[0] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) pre_pending_deposits = len(state.pending_balance_deposits) @@ -229,5 +229,5 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Check the top up assert len(state.pending_balance_deposits) == pre_pending_deposits + 2 assert state.pending_balance_deposits[pre_pending_deposits].amount == block.body.deposits[0].data.amount - amount_from_deposit = block.body.requests.deposit_requests[0].amount + amount_from_deposit = block.body.requests.deposits[0].amount assert state.pending_balance_deposits[pre_pending_deposits + 1].amount == amount_from_deposit diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 4aa593898c..1f96f1f608 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -127,9 +127,9 @@ def build_empty_block(spec, state, slot=None, proposer_index=None): empty_block.body.execution_payload = build_empty_execution_payload(spec, state) if is_post_electra(spec): - empty_block.body.requests.deposit_requests = [] - empty_block.body.requests.withdrawal_requests = [] - empty_block.body.requests.consolidation_requests = [] + empty_block.body.requests.deposits = [] + empty_block.body.requests.withdrawals = [] + empty_block.body.requests.consolidations = [] if is_post_whisk(spec): # Whisk opening proof From c22105d5b345bff7ec7307e1ef9b05188d283be8 Mon Sep 17 00:00:00 2001 From: parithosh Date: Tue, 13 Aug 2024 12:56:03 +0200 Subject: [PATCH 16/66] updating readme and dependencies --- README.md | 16 ++++++++++++++++ docker/README.md | 6 +++--- setup.py | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c62a4171dc..d53f7e6cb2 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,19 @@ Documentation on the different components used during spec writing can be found ## Consensus spec tests Conformance tests built from the executable python spec are available in the [Ethereum Proof-of-Stake Consensus Spec Tests](https://github.com/ethereum/consensus-spec-tests) repo. Compressed tarballs are available in [releases](https://github.com/ethereum/consensus-spec-tests/releases). + + +## Installation and Usage +The consensus-specs repo can be used by running the tests locally or inside a docker container. + +To run the tests locally: +- Clone the repository with `git clone https://github.com/ethereum/consensus-specs.git` +- Switch to the directory `cd consensus-specs` +- Install the dependencies with: `make install_test && make preinstallation && make pyspec` +- Run the tests with `make citest` + +To run the tests inside a docker container: +- Switch to the directory with `cd scripts` +- Run the script `./build_run_docker_tests.sh` +- Find the results in a folder called `./testResults` +- Find more ways to customize the script with `./build_run_docker_tests.sh --h` \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 4f0c1ecca9..4f260130e9 100644 --- a/docker/README.md +++ b/docker/README.md @@ -13,8 +13,8 @@ Ideally manual running of docker containers is for advanced users, we recommend The `scripts/build_run_docker_tests.sh` script will cover most usecases. The script allows the user to configure the fork(altair/bellatrix/capella..), `$IMAGE_NAME` (specifies the container to use), preset type (mainnet/minimal), and test all forks flags. Ideally, this is the main way that users interact with the spec tests instead of running it locally with varying versions of dependencies. E.g: -- `./build_run_test.sh --p mainnet` will run the mainnet preset tests -- `./build_run_test.sh --a` will run all the tests across all the forks -- `./build_run_test.sh --f deneb` will only run deneb tests +`./build_run_docker_tests.sh --p mainnet` will run the mainnet preset tests +- `./build_run_docker_tests.sh --a` will run all the tests across all the forks +- `./build_run_docker_tests.sh --f deneb` will only run deneb tests Results are always placed in a folder called `./testResults`. The results are `.xml` files and contain the fork they represent and the date/time they were run at. \ No newline at end of file diff --git a/setup.py b/setup.py index 539db215b7..0ae71212cb 100644 --- a/setup.py +++ b/setup.py @@ -549,7 +549,7 @@ def run(self): install_requires=[ "eth-utils>=2.0.0,<3", "eth-typing>=3.2.0,<4.0.0", - "pycryptodome==3.15.0", + "pycryptodome>=3.19.1", "py_ecc==6.0.0", "milagro_bls_binding==1.9.0", "remerkleable==0.1.28", From bb4c5d186bb0f78d9b7a9f887c3c4d75ce9b333f Mon Sep 17 00:00:00 2001 From: Parithosh Jayanthi Date: Tue, 13 Aug 2024 16:36:21 +0200 Subject: [PATCH 17/66] Update docker/README.md Co-authored-by: Hsiao-Wei Wang --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 4f260130e9..44dc2b95e5 100644 --- a/docker/README.md +++ b/docker/README.md @@ -13,7 +13,7 @@ Ideally manual running of docker containers is for advanced users, we recommend The `scripts/build_run_docker_tests.sh` script will cover most usecases. The script allows the user to configure the fork(altair/bellatrix/capella..), `$IMAGE_NAME` (specifies the container to use), preset type (mainnet/minimal), and test all forks flags. Ideally, this is the main way that users interact with the spec tests instead of running it locally with varying versions of dependencies. E.g: -`./build_run_docker_tests.sh --p mainnet` will run the mainnet preset tests +- `./build_run_docker_tests.sh --p mainnet` will run the mainnet preset tests - `./build_run_docker_tests.sh --a` will run all the tests across all the forks - `./build_run_docker_tests.sh --f deneb` will only run deneb tests From e3ec53fcdcb058cd402dee3d0bba97b5b998dc00 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Wed, 14 Aug 2024 10:24:55 +1200 Subject: [PATCH 18/66] Fix lint --- specs/electra/beacon-chain.md | 2 +- tests/core/pyspec/eth2spec/test/helpers/block.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 7decb37659..681a1092fd 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -296,7 +296,7 @@ class BeaconBlockBody(Container): execution_payload: ExecutionPayload bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - requests: ExecutionLayerRequests # [New in Electra] + requests: ExecutionLayerRequests # [New in Electra] ``` ### Extended Containers diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 1f96f1f608..c62d70005a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,6 +1,7 @@ from eth2spec.test.helpers.execution_payload import build_empty_execution_payload from eth2spec.test.helpers.execution_payload import build_empty_signed_execution_payload_header -from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732, is_post_electra +from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732, \ + is_post_electra from eth2spec.test.helpers.keys import privkeys, whisk_ks_initial, whisk_ks_final from eth2spec.utils import bls from eth2spec.utils.bls import only_with_bls From 4051ea880bcd8d87750ac8dec7a2d452ffabf05d Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 14 Aug 2024 16:46:56 +0600 Subject: [PATCH 19/66] Fix toc --- specs/electra/beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index bfd3b18e91..e7b36e65e9 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -71,6 +71,7 @@ - [Epoch processing](#epoch-processing) - [Modified `process_epoch`](#modified-process_epoch) - [Modified `process_registry_updates`](#modified-process_registry_updates) + - [Modified `process_slashings`](#modified-process_slashings) - [New `process_pending_balance_deposits`](#new-process_pending_balance_deposits) - [New `process_pending_consolidations`](#new-process_pending_consolidations) - [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates) From 3527a9b64113386dfc83a182d77f29ca75bd42dc Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Wed, 14 Aug 2024 23:16:09 +1200 Subject: [PATCH 20/66] Cleaning unchanged ExecutionPayload --- specs/electra/beacon-chain.md | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 681a1092fd..58e0d55cdf 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -37,7 +37,6 @@ - [Extended Containers](#extended-containers) - [`Attestation`](#attestation) - [`IndexedAttestation`](#indexedattestation) - - [`ExecutionPayload`](#executionpayload) - [`BeaconState`](#beaconstate) - [Helper functions](#helper-functions) - [Predicates](#predicates) @@ -321,31 +320,6 @@ class IndexedAttestation(Container): signature: BLSSignature ``` -#### `ExecutionPayload` - -```python -class ExecutionPayload(Container): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] - blob_gas_used: uint64 - excess_blob_gas: uint64 -``` - #### `BeaconState` ```python From d10cc002d55fe506bd949a170194becc61fe9fba Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 14 Aug 2024 08:46:57 -0300 Subject: [PATCH 21/66] Run Deneb on_block tests in Electra but not 7594 --- tests/core/pyspec/eth2spec/test/context.py | 7 +++++++ .../test/deneb/fork_choice/test_on_block.py | 17 ++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index e805e1c120..8b2e8de6d3 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -429,6 +429,13 @@ def decorator(fn): return decorator +def with_all_phases_from_except(earliest_phase, except_phases=None): + """ + A decorator factory for running a tests with every phase except the ones listed + """ + return with_all_phases_from(earliest_phase, [phase for phase in ALL_PHASES if phase not in except_phases]) + + def with_all_phases_except(exclusion_phases): """ A decorator factory for running a tests with every phase except the ones listed diff --git a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py index 2334fcdc8a..a7e7f784e4 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py @@ -2,10 +2,13 @@ from eth2spec.test.context import ( spec_state_test, - with_phases, + with_all_phases_from_except, ) -from eth2spec.test.helpers.constants import DENEB +from eth2spec.test.helpers.constants import ( + DENEB, + EIP7594, +) from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, @@ -36,7 +39,7 @@ def get_block_with_blob(spec, state, rng=None): return block, blobs, blob_kzg_proofs -@with_phases([DENEB]) +@with_all_phases_from_except(DENEB, [EIP7594]) @spec_state_test def test_simple_blob_data(spec, state): rng = Random(1234) @@ -71,7 +74,7 @@ def test_simple_blob_data(spec, state): yield 'steps', test_steps -@with_phases([DENEB]) +@with_all_phases_from_except(DENEB, [EIP7594]) @spec_state_test def test_invalid_incorrect_proof(spec, state): rng = Random(1234) @@ -99,7 +102,7 @@ def test_invalid_incorrect_proof(spec, state): yield 'steps', test_steps -@with_phases([DENEB]) +@with_all_phases_from_except(DENEB, [EIP7594]) @spec_state_test def test_invalid_data_unavailable(spec, state): rng = Random(1234) @@ -127,7 +130,7 @@ def test_invalid_data_unavailable(spec, state): yield 'steps', test_steps -@with_phases([DENEB]) +@with_all_phases_from_except(DENEB, [EIP7594]) @spec_state_test def test_invalid_wrong_proofs_length(spec, state): rng = Random(1234) @@ -155,7 +158,7 @@ def test_invalid_wrong_proofs_length(spec, state): yield 'steps', test_steps -@with_phases([DENEB]) +@with_all_phases_from_except(DENEB, [EIP7594]) @spec_state_test def test_invalid_wrong_blobs_length(spec, state): rng = Random(1234) From 4eee3b0c3b91844f25cf38a1de01fcbbd200e6a9 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 14 Aug 2024 20:19:50 -0500 Subject: [PATCH 22/66] Remove matrix specific configuration value This also removes references to the "extended matrix" in favor of just "matrix" which I think is better. It's not an extended matrix, it's a matrix of extended blobs. Technically it's just a matrix of cells/proofs. --- configs/mainnet.yaml | 1 - configs/minimal.yaml | 1 - pysetup/spec_builders/eip7594.py | 1 - specs/_features/eip7594/das-core.md | 35 +++++++++---------- .../test/eip7594/unittests/das/test_das.py | 14 ++++---- .../unittests/test_config_invariants.py | 2 -- 6 files changed, 23 insertions(+), 31 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 1c2911f8f5..831d20afdc 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -161,7 +161,6 @@ WHISK_PROPOSER_SELECTION_GAP: 2 # EIP7594 NUMBER_OF_COLUMNS: 128 -MAX_CELLS_IN_EXTENDED_MATRIX: 768 DATA_COLUMN_SIDECAR_SUBNET_COUNT: 128 MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384 SAMPLES_PER_SLOT: 8 diff --git a/configs/minimal.yaml b/configs/minimal.yaml index eb4f77aa26..e1f23b68ec 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -160,7 +160,6 @@ WHISK_PROPOSER_SELECTION_GAP: 1 # EIP7594 NUMBER_OF_COLUMNS: 128 -MAX_CELLS_IN_EXTENDED_MATRIX: 768 DATA_COLUMN_SIDECAR_SUBNET_COUNT: 128 MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384 SAMPLES_PER_SLOT: 8 diff --git a/pysetup/spec_builders/eip7594.py b/pysetup/spec_builders/eip7594.py index dfbc427a70..109ad8736f 100644 --- a/pysetup/spec_builders/eip7594.py +++ b/pysetup/spec_builders/eip7594.py @@ -27,7 +27,6 @@ def hardcoded_custom_type_dep_constants(cls, spec_object) -> str: 'FIELD_ELEMENTS_PER_CELL': spec_object.preset_vars['FIELD_ELEMENTS_PER_CELL'].value, 'FIELD_ELEMENTS_PER_EXT_BLOB': spec_object.preset_vars['FIELD_ELEMENTS_PER_EXT_BLOB'].value, 'NUMBER_OF_COLUMNS': spec_object.config_vars['NUMBER_OF_COLUMNS'].value, - 'MAX_CELLS_IN_EXTENDED_MATRIX': spec_object.config_vars['MAX_CELLS_IN_EXTENDED_MATRIX'].value, } @classmethod diff --git a/specs/_features/eip7594/das-core.md b/specs/_features/eip7594/das-core.md index 3d43db4830..2096fb9a31 100644 --- a/specs/_features/eip7594/das-core.md +++ b/specs/_features/eip7594/das-core.md @@ -20,7 +20,7 @@ - [`MatrixEntry`](#matrixentry) - [Helper functions](#helper-functions) - [`get_custody_columns`](#get_custody_columns) - - [`compute_extended_matrix`](#compute_extended_matrix) + - [`compute_matrix`](#compute_matrix) - [`recover_matrix`](#recover_matrix) - [`get_data_column_sidecars`](#get_data_column_sidecars) - [Custody](#custody) @@ -62,7 +62,6 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | Description | | - | - | - | | `NUMBER_OF_COLUMNS` | `uint64(CELLS_PER_EXT_BLOB)` (= 128) | Number of columns in the extended data matrix | -| `MAX_CELLS_IN_EXTENDED_MATRIX` | `uint64(MAX_BLOBS_PER_BLOCK * NUMBER_OF_COLUMNS)` (= 768) | The data size of `ExtendedMatrix` | ### Networking @@ -133,54 +132,52 @@ def get_custody_columns(node_id: NodeID, custody_subnet_count: uint64) -> Sequen ]) ``` -### `compute_extended_matrix` +### `compute_matrix` ```python -def compute_extended_matrix(blobs: Sequence[Blob]) -> List[MatrixEntry, MAX_CELLS_IN_EXTENDED_MATRIX]: +def compute_matrix(blobs: Sequence[Blob]) -> Sequence[MatrixEntry]: """ - Return the full ``ExtendedMatrix``. + Return the full, flattened sequence of matrix entries. - This helper demonstrates the relationship between blobs and ``ExtendedMatrix``. - The data structure for storing cells is implementation-dependent. + This helper demonstrates the relationship between blobs and the matrix of cells/proofs. + The data structure for storing cells/proofs is implementation-dependent. """ - extended_matrix = [] + matrix = [] for blob_index, blob in enumerate(blobs): cells, proofs = compute_cells_and_kzg_proofs(blob) for cell_index, (cell, proof) in enumerate(zip(cells, proofs)): - extended_matrix.append(MatrixEntry( + matrix.append(MatrixEntry( cell=cell, kzg_proof=proof, row_index=blob_index, column_index=cell_index, )) - return extended_matrix + return matrix ``` ### `recover_matrix` ```python -def recover_matrix(partial_matrix: Sequence[MatrixEntry], - blob_count: uint64) -> List[MatrixEntry, MAX_CELLS_IN_EXTENDED_MATRIX]: +def recover_matrix(partial_matrix: Sequence[MatrixEntry], blob_count: uint64) -> Sequence[MatrixEntry]: """ - Return the recovered extended matrix. + Recover the full, flattened sequence of matrix entries. This helper demonstrates how to apply ``recover_cells_and_kzg_proofs``. - The data structure for storing cells is implementation-dependent. + The data structure for storing cells/proofs is implementation-dependent. """ - extended_matrix = [] + matrix = [] for blob_index in range(blob_count): cell_indices = [e.column_index for e in partial_matrix if e.row_index == blob_index] cells = [e.cell for e in partial_matrix if e.row_index == blob_index] - recovered_cells, recovered_proofs = recover_cells_and_kzg_proofs(cell_indices, cells) for cell_index, (cell, proof) in enumerate(zip(recovered_cells, recovered_proofs)): - extended_matrix.append(MatrixEntry( + matrix.append(MatrixEntry( cell=cell, kzg_proof=proof, row_index=blob_index, column_index=cell_index, )) - return extended_matrix + return matrix ``` ### `get_data_column_sidecars` @@ -241,7 +238,7 @@ At each slot, a node advertising `custody_subnet_count` downloads a minimum of ` ## Extended data -In this construction, we extend the blobs using a one-dimensional erasure coding extension. The matrix comprises maximum `MAX_BLOBS_PER_BLOCK` rows and fixed `NUMBER_OF_COLUMNS` columns, with each row containing a `Blob` and its corresponding extension. `compute_extended_matrix` demonstrates the relationship between blobs and custom type `ExtendedMatrix`. +In this construction, we extend the blobs using a one-dimensional erasure coding extension. The matrix comprises maximum `MAX_BLOBS_PER_BLOCK` rows and fixed `NUMBER_OF_COLUMNS` columns, with each row containing a `Blob` and its corresponding extension. `compute_matrix` demonstrates the relationship between blobs and the matrix, a potential method of storing cells/proofs. ## Column gossip diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/das/test_das.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/das/test_das.py index 7110f2373e..625136b73e 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/das/test_das.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/das/test_das.py @@ -19,15 +19,15 @@ def chunks(lst, n): @with_eip7594_and_later @spec_test @single_phase -def test_compute_extended_matrix(spec): +def test_compute_matrix(spec): rng = random.Random(5566) blob_count = 2 input_blobs = [get_sample_blob(spec, rng=rng) for _ in range(blob_count)] - extended_matrix = spec.compute_extended_matrix(input_blobs) - assert len(extended_matrix) == spec.CELLS_PER_EXT_BLOB * blob_count + matrix = spec.compute_matrix(input_blobs) + assert len(matrix) == spec.CELLS_PER_EXT_BLOB * blob_count - rows = chunks(extended_matrix, spec.CELLS_PER_EXT_BLOB) + rows = chunks(matrix, spec.CELLS_PER_EXT_BLOB) assert len(rows) == blob_count for row in rows: assert len(row) == spec.CELLS_PER_EXT_BLOB @@ -53,11 +53,11 @@ def test_recover_matrix(spec): # Compute an extended matrix with two blobs blob_count = 2 blobs = [get_sample_blob(spec, rng=rng) for _ in range(blob_count)] - extended_matrix = spec.compute_extended_matrix(blobs) + matrix = spec.compute_matrix(blobs) # Construct a matrix with some entries missing partial_matrix = [] - for blob_entries in chunks(extended_matrix, spec.CELLS_PER_EXT_BLOB): + for blob_entries in chunks(matrix, spec.CELLS_PER_EXT_BLOB): rng.shuffle(blob_entries) partial_matrix.extend(blob_entries[:N_SAMPLES]) @@ -65,7 +65,7 @@ def test_recover_matrix(spec): recovered_matrix = spec.recover_matrix(partial_matrix, blob_count) # Ensure that the recovered matrix matches the original matrix - assert recovered_matrix == extended_matrix + assert recovered_matrix == matrix @with_eip7594_and_later diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py index 776ea883aa..6d20882cda 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py @@ -17,8 +17,6 @@ def test_invariants(spec): assert spec.config.NUMBER_OF_COLUMNS % spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT == 0 assert spec.config.MAX_REQUEST_DATA_COLUMN_SIDECARS == ( spec.config.MAX_REQUEST_BLOCKS_DENEB * spec.config.NUMBER_OF_COLUMNS - ) - assert spec.config.MAX_CELLS_IN_EXTENDED_MATRIX == spec.config.MAX_BLOBS_PER_BLOCK * spec.config.NUMBER_OF_COLUMNS @with_eip7594_and_later From 121a3b7b240f64046848c068e17715198ffa880b Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 14 Aug 2024 20:32:11 -0500 Subject: [PATCH 23/66] Fix mistake --- .../eth2spec/test/eip7594/unittests/test_config_invariants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py index 6d20882cda..fc54cc3088 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py @@ -17,6 +17,7 @@ def test_invariants(spec): assert spec.config.NUMBER_OF_COLUMNS % spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT == 0 assert spec.config.MAX_REQUEST_DATA_COLUMN_SIDECARS == ( spec.config.MAX_REQUEST_BLOCKS_DENEB * spec.config.NUMBER_OF_COLUMNS + ) @with_eip7594_and_later From b84316de3ff86d354ad6be15563a6a73209b6913 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 16 Aug 2024 18:30:06 +1200 Subject: [PATCH 24/66] PR Comments --- specs/electra/beacon-chain.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 58e0d55cdf..1f5246814b 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -257,8 +257,9 @@ class PendingConsolidation(Container): #### `ExecutionLayerRequests` -*Note*: This container contains request from the execution layer that are received in the Execution Payload via -Engine API. These requests are required for CL state transition (see **BeaconBlockBody**). +*Note*: This container holds requests from the execution layer that are received in [ +`ExecutionPayloadV4`](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#executionpayloadv4) via +the Engine API. These requests are required for CL state transition (see `BeaconBlockBody`). ```python class ExecutionLayerRequests(Container): @@ -1026,10 +1027,8 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) for_ops(body.requests.deposits, process_deposit_request) # [New in Electra:EIP6110] - # [New in Electra:EIP7002:EIP7251] - for_ops(body.requests.withdrawals, process_withdrawal_request) - # [New in Electra:EIP7251] - for_ops(body.requests.consolidations, process_consolidation_request) + for_ops(body.requests.withdrawals, process_withdrawal_request) # [New in Electra:EIP7002:EIP7251] + for_ops(body.requests.consolidations, process_consolidation_request) # [New in Electra:EIP7251] ``` ##### Attestations From 98dd1884aea37fae2fc7e3e5462a4abde34c7ced Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 16 Aug 2024 18:34:22 +1200 Subject: [PATCH 25/66] Rename requests to execution_requests --- specs/electra/beacon-chain.md | 8 ++++---- .../eth2spec/test/electra/sanity/blocks/test_blocks.py | 8 ++++---- .../electra/sanity/blocks/test_deposit_transition.py | 10 +++++----- tests/core/pyspec/eth2spec/test/helpers/block.py | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 1f5246814b..92be2ce253 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -296,7 +296,7 @@ class BeaconBlockBody(Container): execution_payload: ExecutionPayload bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - requests: ExecutionLayerRequests # [New in Electra] + execution_requests: ExecutionLayerRequests # [New in Electra] ``` ### Extended Containers @@ -1026,9 +1026,9 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251] for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) - for_ops(body.requests.deposits, process_deposit_request) # [New in Electra:EIP6110] - for_ops(body.requests.withdrawals, process_withdrawal_request) # [New in Electra:EIP7002:EIP7251] - for_ops(body.requests.consolidations, process_consolidation_request) # [New in Electra:EIP7251] + for_ops(body.execution_requests.deposits, process_deposit_request) # [New in Electra:EIP6110] + for_ops(body.execution_requests.withdrawals, process_withdrawal_request) # [New in Electra:EIP7002:EIP7251] + for_ops(body.execution_requests.consolidations, process_consolidation_request) # [New in Electra:EIP7251] ``` ##### Attestations diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 8371e71f66..0bb8f32d46 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -41,7 +41,7 @@ def test_basic_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block = build_empty_block_for_next_slot(spec, state) - block.body.requests.withdrawals = [withdrawal_request] + block.body.execution_requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -77,7 +77,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): source_address=address, validator_pubkey=validator_pubkey, ) - block.body.requests.withdrawals = [withdrawal_request] + block.body.execution_requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) @@ -130,7 +130,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state): validator_pubkey=validator_pubkey, ) block_2 = build_empty_block_for_next_slot(spec, state) - block_2.body.requests.withdrawals = [withdrawal_request] + block_2.body.execution_requests.withdrawals = [withdrawal_request] block_2.body.execution_payload.block_hash = compute_el_block_hash(spec, block_2.body.execution_payload, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) @@ -163,7 +163,7 @@ def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state): ) block = build_empty_block_for_next_slot(spec, state) block.body.voluntary_exits = signed_voluntary_exits - block.body.requests.withdrawals = [withdrawal_request] + block.body.execution_requests.withdrawals = [withdrawal_request] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = state_transition_and_sign_block(spec, state, block) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py index 98fc707d41..e846543f23 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_deposit_transition.py @@ -38,7 +38,7 @@ def run_deposit_transition_block(spec, state, block, top_up_keys=[], valid=True) # Check that deposits are applied if valid: expected_pubkeys = [d.data.pubkey for d in block.body.deposits] - deposit_requests = block.body.requests.deposits + deposit_requests = block.body.execution_requests.deposits expected_pubkeys = expected_pubkeys + [d.pubkey for d in deposit_requests if (d.pubkey not in top_up_keys)] actual_pubkeys = [v.pubkey for v in state.validators[len(state.validators) - len(expected_pubkeys):]] @@ -102,7 +102,7 @@ def prepare_state_and_block(spec, # Assign deposits and deposit requests block.body.deposits = deposits - block.body.requests.deposits = deposit_requests + block.body.execution_requests.deposits = deposit_requests block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) return state, block @@ -120,7 +120,7 @@ def test_deposit_transition__start_index_is_set(spec, state): yield from run_deposit_transition_block(spec, state, block) # deposit_requests_start_index must be set to the index of the first request - assert state.deposit_requests_start_index == block.body.requests.deposits[0].index + assert state.deposit_requests_start_index == block.body.execution_requests.deposits[0].index @with_phases([ELECTRA]) @@ -219,7 +219,7 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Artificially assign deposit's pubkey to a deposit request of the same block top_up_keys = [block.body.deposits[0].data.pubkey] - block.body.requests.deposits[0].pubkey = top_up_keys[0] + block.body.execution_requests.deposits[0].pubkey = top_up_keys[0] block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) pre_pending_deposits = len(state.pending_balance_deposits) @@ -229,5 +229,5 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state): # Check the top up assert len(state.pending_balance_deposits) == pre_pending_deposits + 2 assert state.pending_balance_deposits[pre_pending_deposits].amount == block.body.deposits[0].data.amount - amount_from_deposit = block.body.requests.deposits[0].amount + amount_from_deposit = block.body.execution_requests.deposits[0].amount assert state.pending_balance_deposits[pre_pending_deposits + 1].amount == amount_from_deposit diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index c62d70005a..f862488c11 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -128,9 +128,9 @@ def build_empty_block(spec, state, slot=None, proposer_index=None): empty_block.body.execution_payload = build_empty_execution_payload(spec, state) if is_post_electra(spec): - empty_block.body.requests.deposits = [] - empty_block.body.requests.withdrawals = [] - empty_block.body.requests.consolidations = [] + empty_block.body.execution_requests.deposits = [] + empty_block.body.execution_requests.withdrawals = [] + empty_block.body.execution_requests.consolidations = [] if is_post_whisk(spec): # Whisk opening proof From fc3640f3c209207acc494d14449879b4489351e1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 19 Aug 2024 09:33:10 -0300 Subject: [PATCH 26/66] Require the builder is active and non-slashed --- specs/_features/eip7732/beacon-chain.md | 5 ++++- specs/_features/eip7732/p2p-interface.md | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index fdcb2b3008..04da9b5399 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -493,9 +493,12 @@ def process_execution_payload_header(state: BeaconState, block: BeaconBlock) -> signed_header = block.body.signed_execution_payload_header assert verify_execution_payload_header_signature(state, signed_header) - # Check that the builder has funds to cover the bid + # Check that the builder is active non-slashed has funds to cover the bid header = signed_header.message builder_index = header.builder_index + builder = state.validators[builder_index] + assert is_active_validator(builder, get_current_epoch(state)) + assert not builder.slashed amount = header.value assert state.balances[builder_index] >= amount diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index 86ab89568c..a48bb69905 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -170,9 +170,10 @@ The following validations MUST pass before forwarding the `signed_execution_payl - _[IGNORE]_ this is the first signed bid seen with a valid signature from the given builder for this slot. - _[IGNORE]_ this bid is the highest value bid seen for the pair of the corresponding slot and the given parent block hash. -- _[REJECT]_ The signed builder bid, `header.builder_index` is a valid and non-slashed builder index in state. +- _[REJECT]_ The signed builder bid, `header.builder_index` is a valid, active, and non-slashed builder index in state. - _[IGNORE]_ The signed builder bid value, `header.value`, is less or equal than the builder's balance in state. i.e. `MIN_BUILDER_BALANCE + header.value < state.builder_balances[header.builder_index]`. - _[IGNORE]_ `header.parent_block_hash` is the block hash of a known execution payload in fork choice. +_ _[IGNORE]_ `header.parent_block_root` is the hash tree root of a known beacon block in fork choice. - _[IGNORE]_ `header.slot` is the current slot or the next slot. - _[REJECT]_ The builder signature, `signed_execution_payload_header_envelope.signature`, is valid with respect to the `header_envelope.builder_index`. From 7d0a8c6335b2dca9d7e8f749cc886c733633d4db Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 20 Aug 2024 13:54:36 +0300 Subject: [PATCH 27/66] EIP-7732: Modify `ExecutionPayloadEnvelopeByRoot` --- configs/mainnet.yaml | 3 +++ configs/minimal.yaml | 3 +++ specs/_features/eip7732/p2p-interface.md | 24 ++++++++++++++++-------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 1c2911f8f5..cb051ce883 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -170,3 +170,6 @@ CUSTODY_REQUIREMENT: 4 # [New in Electra:EIP7251] MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000 # 2**7 * 10**9 (= 128,000,000,000) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000 # 2**8 * 10**9 (= 256,000,000,000) + +# EIP7732 +MAX_REQUEST_PAYLOADS: 128 diff --git a/configs/minimal.yaml b/configs/minimal.yaml index eb4f77aa26..a7c89ec1dd 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -169,3 +169,6 @@ CUSTODY_REQUIREMENT: 4 # [New in Electra:EIP7251] MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000 # 2**6 * 10**9 (= 64,000,000,000) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 128000000000 # 2**7 * 10**9 (= 128,000,000,000) + +# EIP7732 +MAX_REQUEST_PAYLOADS: 128 diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index 86ab89568c..cd48b79aa9 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -23,7 +23,7 @@ This document contains the consensus-layer networking specification for EIP7732. - [BeaconBlocksByRange v3](#beaconblocksbyrange-v3) - [BeaconBlocksByRoot v3](#beaconblocksbyroot-v3) - [BlobSidecarsByRoot v2](#blobsidecarsbyroot-v2) - - [ExecutionPayloadEnvelopeByRoot v1](#executionpayloadenvelopebyroot-v1) + - [ExecutionPayloadEnvelopesByRoot v1](#executionpayloadenvelopesbyroot-v1) @@ -37,6 +37,14 @@ This document contains the consensus-layer networking specification for EIP7732. |------------------------------------------|-----------------------------------|---------------------------------------------------------------------| | `KZG_COMMITMENT_INCLUSION_PROOF_DEPTH_EIP7732` | `13` # TODO: Compute it when the spec stabilizes | Merkle proof depth for the `blob_kzg_commitments` list item | +### Configuration + +*[Modified in EIP-7732]* + +| Name | Value | Description | +|------------------------------------------|-----------------------------------|---------------------------------------------------------------------| +| `MAX_REQUEST_PAYLOADS` | `2**7` (= 128) | Maximum number of execution payload envelopes in a single request | + ### Containers @@ -225,9 +233,9 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: | `EIP7732_FORK_VERSION` | `eip7732.BlobSidecar` | -##### ExecutionPayloadEnvelopeByRoot v1 +##### ExecutionPayloadEnvelopesByRoot v1 -**Protocol ID:** `/eth2/beacon_chain/req/execution_payload_envelope_by_root/1/` +**Protocol ID:** `/eth2/beacon_chain/req/execution_payload_envelopes_by_root/1/` The `` field is calculated as `context = compute_fork_digest(fork_version, genesis_validators_root)`: @@ -241,7 +249,7 @@ Request Content: ``` ( - List[Root, MAX_REQUEST_PAYLOAD] + List[Root, MAX_REQUEST_PAYLOADS] ) ``` @@ -249,14 +257,14 @@ Response Content: ``` ( - List[SignedExecutionPayloadEnvelope, MAX_REQUEST_PAYLOAD] + List[SignedExecutionPayloadEnvelope, MAX_REQUEST_PAYLOADS] ) ``` -Requests execution payload envelope by `signed_execution_payload_envelope.message.block_root`. The response is a list of `SignedExecutionPayloadEnvelope` whose length is less than or equal to the number of requested execution payload envelopes. It may be less in the case that the responding peer is missing payload envelopes. +Requests execution payload envelopes by `signed_execution_payload_envelope.message.block_root`. The response is a list of `SignedExecutionPayloadEnvelope` whose length is less than or equal to the number of requested execution payload envelopes. It may be less in the case that the responding peer is missing payload envelopes. -No more than `MAX_REQUEST_PAYLOAD` may be requested at a time. +No more than `MAX_REQUEST_PAYLOADS` may be requested at a time. -ExecutionPayloadEnvelopeByRoot is primarily used to recover recent execution payload envelope (e.g. when receiving a payload attestation with revealed status as true but never received a payload). +ExecutionPayloadEnvelopesByRoot is primarily used to recover recent execution payload envelopes (e.g. when receiving a payload attestation with revealed status as true but never received a payload). The request MUST be encoded as an SSZ-field. From 679cb60ee2b0426be8b36282f3f472b526cb920e Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 20 Aug 2024 13:58:09 +0300 Subject: [PATCH 28/66] Add to table of contents --- specs/_features/eip7732/p2p-interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index cd48b79aa9..3cbfab1e86 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -7,6 +7,7 @@ This document contains the consensus-layer networking specification for EIP7732. - [Modification in EIP-7732](#modification-in-eip-7732) - [Preset](#preset) + - [Configuration](#configuration) - [Containers](#containers) - [`BlobSidecar`](#blobsidecar) - [Helpers](#helpers) From edf0ddea3cd7ffae333bce994527b21525f736ca Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 20 Aug 2024 13:59:29 +0300 Subject: [PATCH 29/66] change to new --- specs/_features/eip7732/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index 3cbfab1e86..0de7adcfdd 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -40,7 +40,7 @@ This document contains the consensus-layer networking specification for EIP7732. ### Configuration -*[Modified in EIP-7732]* +*[New in EIP-7732]* | Name | Value | Description | |------------------------------------------|-----------------------------------|---------------------------------------------------------------------| From 7391de10a8a08b027748b70105b10ae2da7cd481 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Tue, 20 Aug 2024 23:55:52 +0800 Subject: [PATCH 30/66] bump version to 1.5.0-alpha.5 --- tests/core/pyspec/eth2spec/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/VERSION.txt b/tests/core/pyspec/eth2spec/VERSION.txt index 2ac49a507e..8c993fb5e5 100644 --- a/tests/core/pyspec/eth2spec/VERSION.txt +++ b/tests/core/pyspec/eth2spec/VERSION.txt @@ -1 +1 @@ -1.5.0-alpha.4 +1.5.0-alpha.5 From 24aecf554d0e4a8c92c241a633508dca95246b87 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 20 Aug 2024 20:18:47 +0300 Subject: [PATCH 31/66] Update specs/_features/eip7732/p2p-interface.md Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> --- specs/_features/eip7732/p2p-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index 0de7adcfdd..b0522ac98c 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -42,9 +42,9 @@ This document contains the consensus-layer networking specification for EIP7732. *[New in EIP-7732]* -| Name | Value | Description | -|------------------------------------------|-----------------------------------|---------------------------------------------------------------------| -| `MAX_REQUEST_PAYLOADS` | `2**7` (= 128) | Maximum number of execution payload envelopes in a single request | +| Name | Value | Description | +|------------------------|----------------|-------------------------------------------------------------------| +| `MAX_REQUEST_PAYLOADS` | `2**7` (= 128) | Maximum number of execution payload envelopes in a single request | ### Containers From ba99f8bb16f59b4cd01ca8260e3db6f2032c9bff Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 20 Aug 2024 20:18:55 +0300 Subject: [PATCH 32/66] Update specs/_features/eip7732/p2p-interface.md Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> --- specs/_features/eip7732/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/_features/eip7732/p2p-interface.md b/specs/_features/eip7732/p2p-interface.md index b0522ac98c..b101cc3670 100644 --- a/specs/_features/eip7732/p2p-interface.md +++ b/specs/_features/eip7732/p2p-interface.md @@ -40,7 +40,7 @@ This document contains the consensus-layer networking specification for EIP7732. ### Configuration -*[New in EIP-7732]* +*[New in EIP7732]* | Name | Value | Description | |------------------------|----------------|-------------------------------------------------------------------| From 4c9be8978faae33a69e170b679df2e0cd24f53f2 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:17:56 +0800 Subject: [PATCH 33/66] Randomize validator index in partial withdrawal test --- .../test_process_withdrawal_request.py | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py index 53460347ad..c4707733a3 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py @@ -1,3 +1,4 @@ +import random from eth2spec.test.context import ( spec_state_test, expect_assertion_error, @@ -23,7 +24,7 @@ def test_basic_withdrawal_request(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -47,7 +48,7 @@ def test_basic_withdrawal_request_with_compounding_credentials(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_compounding_withdrawal_credential(spec, state, validator_index, address=address) @@ -68,7 +69,7 @@ def test_basic_withdrawal_request_with_compounding_credentials(spec, state): def test_basic_withdrawal_request_with_full_partial_withdrawal_queue(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -106,7 +107,7 @@ def test_incorrect_source_address(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 incorrect_address = b"\x33" * 20 @@ -131,7 +132,7 @@ def test_incorrect_withdrawal_credential_prefix(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -160,7 +161,7 @@ def test_on_withdrawal_request_initiated_validator(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -183,7 +184,7 @@ def test_on_withdrawal_request_initiated_validator(spec, state): @spec_state_test def test_activation_epoch_less_than_shard_committee_period(spec, state): current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -213,7 +214,7 @@ def test_activation_epoch_less_than_shard_committee_period(spec, state): def test_basic_partial_withdrawal_request(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -245,7 +246,7 @@ def test_basic_partial_withdrawal_request(spec, state): def test_basic_partial_withdrawal_request_higher_excess_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -277,7 +278,7 @@ def test_basic_partial_withdrawal_request_higher_excess_balance(spec, state): def test_basic_partial_withdrawal_request_lower_than_excess_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT @@ -310,7 +311,7 @@ def test_basic_partial_withdrawal_request_lower_than_excess_balance(spec, state) def test_partial_withdrawal_request_with_pending_withdrawals(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -351,7 +352,7 @@ def test_partial_withdrawal_request_with_pending_withdrawals_and_high_amount( ): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.UINT64_MAX @@ -389,7 +390,7 @@ def test_partial_withdrawal_request_with_pending_withdrawals_and_high_amount( def test_partial_withdrawal_request_with_high_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA @@ -426,7 +427,7 @@ def test_partial_withdrawal_request_with_high_balance(spec, state): def test_partial_withdrawal_request_with_high_amount(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 # Set high amount requested to withdraw @@ -459,7 +460,7 @@ def test_partial_withdrawal_request_with_high_amount(spec, state): def test_partial_withdrawal_request_with_low_amount(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = 1 @@ -494,7 +495,7 @@ def test_partial_withdrawal_request_with_low_amount(spec, state): def test_partial_withdrawal_queue_full(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -524,7 +525,7 @@ def test_partial_withdrawal_queue_full(spec, state): def test_no_compounding_credentials(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -553,7 +554,7 @@ def test_no_compounding_credentials(spec, state): def test_no_excess_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -575,7 +576,7 @@ def test_no_excess_balance(spec, state): def test_pending_withdrawals_consume_all_excess_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -605,7 +606,7 @@ def test_pending_withdrawals_consume_all_excess_balance(spec, state): def test_insufficient_effective_balance(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -636,7 +637,7 @@ def test_partial_withdrawal_incorrect_source_address(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 incorrect_address = b"\x33" * 20 @@ -662,7 +663,7 @@ def test_partial_withdrawal_incorrect_withdrawal_credential_prefix(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -691,7 +692,7 @@ def test_partial_withdrawal_on_exit_initiated_validator(spec, state): state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -716,7 +717,7 @@ def test_partial_withdrawal_activation_epoch_less_than_shard_committee_period( spec, state ): current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT From ad91a835c03248dbb8a220ca157788d3e88853c7 Mon Sep 17 00:00:00 2001 From: Parithosh Jayanthi Date: Wed, 21 Aug 2024 20:15:57 +0200 Subject: [PATCH 34/66] Update python to 3.12.4 (#3880) * update python to 3.12 * drop down to 3.12.4 for compatibility * setup rust toolchain for deps * fix typo * fix linter * fixing linter * adding rust dep * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying to fix circleci * trying new image * trying new image * trying new image * trying new image * invalidate cache * bump reqs * remove cache invalidation * fix cache name * update to use latest image --- .circleci/config.yml | 30 ++++++++-------- .github/workflows/generate_vectors.yml | 2 +- .github/workflows/run-tests.yml | 10 ++++-- docker/Dockerfile | 2 +- requirements_preinstallation.txt | 8 ++--- .../gen_helpers/gen_base/gen_runner.py | 4 +-- .../ssz_generic/ssz_basic_vector.py | 14 ++++---- tests/generators/ssz_generic/ssz_bitlist.py | 6 ++-- tests/generators/ssz_generic/ssz_bitvector.py | 4 +-- tests/generators/ssz_generic/ssz_container.py | 35 +++++++++---------- tests/generators/ssz_generic/ssz_uints.py | 6 ++-- 11 files changed, 62 insertions(+), 59 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bf8b7ada8a..94dcefdb6f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -60,7 +60,7 @@ commands: jobs: checkout_specs: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: # Restore git repo at point close to target branch/revision, to speed up checkout @@ -80,7 +80,7 @@ jobs: - ~/specs-repo install_pyspec_test: docker: - - image: circleci/python:3.9 + - image: ethpandaops/circleci-python-rust:latest working_directory: ~/specs-repo steps: - restore_cache: @@ -88,11 +88,11 @@ jobs: - restore_pyspec_cached_venv - run: name: Install pyspec requirements - command: make install_test + command: make install_test && make preinstallation - save_pyspec_cached_venv test-phase0: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -105,7 +105,7 @@ jobs: path: tests/core/pyspec/test-reports test-altair: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -118,7 +118,7 @@ jobs: path: tests/core/pyspec/test-reports test-bellatrix: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -131,7 +131,7 @@ jobs: path: tests/core/pyspec/test-reports test-capella: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -144,7 +144,7 @@ jobs: path: tests/core/pyspec/test-reports test-deneb: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -157,7 +157,7 @@ jobs: path: tests/core/pyspec/test-reports test-electra: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -170,7 +170,7 @@ jobs: path: tests/core/pyspec/test-reports test-whisk: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -183,7 +183,7 @@ jobs: path: tests/core/pyspec/test-reports test-eip7594: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -205,7 +205,7 @@ jobs: command: sudo npm install -g doctoc@2.2.0 && make check_toc codespell: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - checkout @@ -214,7 +214,7 @@ jobs: command: pip install 'codespell<3.0.0,>=2.0.0' --user && make codespell lint: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -270,7 +270,7 @@ jobs: - /nix install_deposit_contract_web3_tester: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -282,7 +282,7 @@ jobs: - save_deposit_contract_tester_cached_venv test_deposit_contract_web3_tests: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: diff --git a/.github/workflows/generate_vectors.yml b/.github/workflows/generate_vectors.yml index 37468d203d..7a45953b8a 100644 --- a/.github/workflows/generate_vectors.yml +++ b/.github/workflows/generate_vectors.yml @@ -32,7 +32,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12.4' cache: '' - name: Clean up Spec Repository run: | diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index a56270030f..83926c47c5 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -45,7 +45,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12.4' cache: '' - name: Check codespell run: make codespell @@ -55,10 +55,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup Rust for dependencies + uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12.4' cache: '' - name: Install pyspec requirements run: make install_test @@ -76,10 +78,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup Rust for dependencies + uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12.4' cache: '' - name: set TEST_PRESET_TYPE if: github.event.inputs.test_preset_type != '' diff --git a/docker/Dockerfile b/docker/Dockerfile index 7713099316..8ec384499d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ # Rename the build stage from 'base' to 'builder' for clarification and code readability -FROM python:3.11.0-slim-bullseye as builder +FROM python:3.12.4-slim-bullseye as builder ENV DEBIAN_FRONTEND=noninteractive \ WORKDIR=/consensus-specs \ diff --git a/requirements_preinstallation.txt b/requirements_preinstallation.txt index 02f6d2f0b8..1aca6ad0e0 100644 --- a/requirements_preinstallation.txt +++ b/requirements_preinstallation.txt @@ -1,4 +1,4 @@ -pip>=23.1.2 -wheel>=0.40.0 -setuptools>=68.0.0 -pylint>=3.0.0 \ No newline at end of file +pip>=24.0.0 +wheel>=0.44.0 +setuptools>=72.0.0 +pylint>=3.2.0 \ No newline at end of file diff --git a/tests/core/pyspec/eth2spec/gen_helpers/gen_base/gen_runner.py b/tests/core/pyspec/eth2spec/gen_helpers/gen_base/gen_runner.py index 3ab2e9eea8..85ccec017a 100644 --- a/tests/core/pyspec/eth2spec/gen_helpers/gen_base/gen_runner.py +++ b/tests/core/pyspec/eth2spec/gen_helpers/gen_base/gen_runner.py @@ -132,7 +132,7 @@ def should_skip_case_dir(case_dir, is_force, diagnostics_obj): print(f'Skipping already existing test: {case_dir}') is_skip = True else: - print(f'Warning, output directory {case_dir} already exist,' + print(f'Warning, output directory {case_dir} already exist, ' ' old files will be deleted and it will generate test vector files with the latest version') # Clear the existing case_dir folder shutil.rmtree(case_dir) @@ -356,7 +356,7 @@ def generate_test_vector(test_case, case_dir, log_file, file_mode): test_end = time.time() span = round(test_end - test_start, 2) if span > TIME_THRESHOLD_TO_PRINT: - print(f' - generated in {span} seconds') + print(f'- generated in {span} seconds') return result diff --git a/tests/generators/ssz_generic/ssz_basic_vector.py b/tests/generators/ssz_generic/ssz_basic_vector.py index 51dfd4ba1a..41bd3a7f5c 100644 --- a/tests/generators/ssz_generic/ssz_basic_vector.py +++ b/tests/generators/ssz_generic/ssz_basic_vector.py @@ -33,7 +33,7 @@ def valid_cases(): for length in [1, 2, 3, 4, 5, 8, 16, 31, 512, 513]: for mode in random_modes: yield f'vec_{name}_{length}_{mode.to_name()}', \ - valid_test_case(lambda: basic_vector_case_fn(rng, mode, typ, length)) + valid_test_case(lambda: basic_vector_case_fn(rng, mode, typ, length)) def invalid_cases(): @@ -52,14 +52,14 @@ def invalid_cases(): if length == 1: # empty bytes, no elements. It may seem valid, but empty fixed-size elements are not valid SSZ. yield f'vec_{name}_{length}_{mode.to_name()}_one_less', \ - invalid_test_case(lambda: b"") + invalid_test_case(lambda: b"") else: yield f'vec_{name}_{length}_{mode.to_name()}_one_less', \ - invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length - 1))) + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length - 1))) yield f'vec_{name}_{length}_{mode.to_name()}_one_more', \ - invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length + 1))) + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length + 1))) yield f'vec_{name}_{length}_{mode.to_name()}_one_byte_less', \ - invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length))[:-1]) + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length))[:-1]) yield f'vec_{name}_{length}_{mode.to_name()}_one_byte_more', \ - invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length)) - + serialize(basic_vector_case_fn(rng, mode, uint8, 1))) + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length)) + + serialize(basic_vector_case_fn(rng, mode, uint8, 1))) diff --git a/tests/generators/ssz_generic/ssz_bitlist.py b/tests/generators/ssz_generic/ssz_bitlist.py index d1a940eee8..8b904dc511 100644 --- a/tests/generators/ssz_generic/ssz_bitlist.py +++ b/tests/generators/ssz_generic/ssz_bitlist.py @@ -22,7 +22,7 @@ def valid_cases(): RandomizationMode.mode_zero, RandomizationMode.mode_max]: yield f'bitlist_{size}_{mode.to_name()}_{variation}', \ - valid_test_case(lambda: bitlist_case_fn(rng, mode, size)) + valid_test_case(lambda: bitlist_case_fn(rng, mode, size)) def invalid_cases(): @@ -33,5 +33,5 @@ def invalid_cases(): for (typ_limit, test_limit) in [(1, 2), (1, 8), (1, 9), (2, 3), (3, 4), (4, 5), (5, 6), (8, 9), (32, 64), (32, 33), (512, 513)]: yield f'bitlist_{typ_limit}_but_{test_limit}', \ - invalid_test_case(lambda: serialize( - bitlist_case_fn(rng, RandomizationMode.mode_max_count, test_limit))) + invalid_test_case(lambda: serialize( + bitlist_case_fn(rng, RandomizationMode.mode_max_count, test_limit))) diff --git a/tests/generators/ssz_generic/ssz_bitvector.py b/tests/generators/ssz_generic/ssz_bitvector.py index d846140680..56e9f86c21 100644 --- a/tests/generators/ssz_generic/ssz_bitvector.py +++ b/tests/generators/ssz_generic/ssz_bitvector.py @@ -38,5 +38,5 @@ def invalid_cases(): (5, 6), (8, 9), (9, 8), (16, 8), (32, 33), (512, 513)]: for mode in [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]: yield f'bitvec_{typ_size}_{mode.to_name()}_{test_size}', \ - invalid_test_case(lambda: serialize(bitvector_case_fn(rng, mode, test_size, - invalid_making_pos=typ_size))) + invalid_test_case(lambda: serialize(bitvector_case_fn(rng, mode, test_size, + invalid_making_pos=typ_size))) diff --git a/tests/generators/ssz_generic/ssz_container.py b/tests/generators/ssz_generic/ssz_container.py index 2c1d37da88..b1a5f026b5 100644 --- a/tests/generators/ssz_generic/ssz_container.py +++ b/tests/generators/ssz_generic/ssz_container.py @@ -46,7 +46,7 @@ class BitsStruct(Container): E: Bitvector[8] -def container_case_fn(rng: Random, mode: RandomizationMode, typ: Type[View], chaos: bool=False): +def container_case_fn(rng: Random, mode: RandomizationMode, typ: Type[View], chaos: bool = False): return get_random_ssz_object(rng, typ, max_bytes_length=2000, max_list_length=2000, @@ -77,7 +77,7 @@ def valid_cases(): for mode in modes: for variation in range(3): yield f'{name}_{mode.to_name()}_chaos_{variation}', \ - valid_test_case(lambda: container_case_fn(rng, mode, typ, chaos=True)) + valid_test_case(lambda: container_case_fn(rng, mode, typ, chaos=True)) # Notes: Below is the second wave of iteration, and only the random mode is selected # for container without offset since ``RandomizationMode.mode_zero`` and ``RandomizationMode.mode_max`` # are deterministic. @@ -85,7 +85,7 @@ def valid_cases(): for mode in modes: for variation in range(10): yield f'{name}_{mode.to_name()}_{variation}', \ - valid_test_case(lambda: container_case_fn(rng, mode, typ)) + valid_test_case(lambda: container_case_fn(rng, mode, typ)) def mod_offset(b: bytes, offset_index: int, change: Callable[[int], int]): @@ -100,8 +100,8 @@ def invalid_cases(): for (name, (typ, offsets)) in PRESET_CONTAINERS.items(): # using mode_max_count, so that the extra byte cannot be picked up as normal list content yield f'{name}_extra_byte', \ - invalid_test_case(lambda: serialize( - container_case_fn(rng, RandomizationMode.mode_max_count, typ)) + b'\xff') + invalid_test_case(lambda: serialize( + container_case_fn(rng, RandomizationMode.mode_max_count, typ)) + b'\xff') if len(offsets) != 0: # Note: there are many more ways to have invalid offsets, @@ -112,23 +112,22 @@ def invalid_cases(): RandomizationMode.mode_max_count]: for index, offset_index in enumerate(offsets): yield f'{name}_{mode.to_name()}_offset_{offset_index}_plus_one', \ - invalid_test_case(lambda: mod_offset( - b=serialize(container_case_fn(rng, mode, typ)), - offset_index=offset_index, - change=lambda x: x + 1 - )) + invalid_test_case(lambda: mod_offset( + b=serialize(container_case_fn(rng, mode, typ)), + offset_index=offset_index, + change=lambda x: x + 1)) yield f'{name}_{mode.to_name()}_offset_{offset_index}_zeroed', \ - invalid_test_case(lambda: mod_offset( - b=serialize(container_case_fn(rng, mode, typ)), - offset_index=offset_index, - change=lambda x: 0 - )) + invalid_test_case(lambda: mod_offset( + b=serialize(container_case_fn(rng, mode, typ)), + offset_index=offset_index, + change=lambda x: 0 + )) if index == 0: yield f'{name}_{mode.to_name()}_offset_{offset_index}_minus_one', \ invalid_test_case(lambda: mod_offset( - b=serialize(container_case_fn(rng, mode, typ)), - offset_index=offset_index, - change=lambda x: x - 1 + b=serialize(container_case_fn(rng, mode, typ)), + offset_index=offset_index, + change=lambda x: x - 1 )) if mode == RandomizationMode.mode_max_count: serialized = serialize(container_case_fn(rng, mode, typ)) diff --git a/tests/generators/ssz_generic/ssz_uints.py b/tests/generators/ssz_generic/ssz_uints.py index abf7fc75b2..32e54353d3 100644 --- a/tests/generators/ssz_generic/ssz_uints.py +++ b/tests/generators/ssz_generic/ssz_uints.py @@ -21,7 +21,7 @@ def valid_cases(): mode = RandomizationMode.mode_random byte_len = uint_type.type_byte_length() yield f'uint_{byte_len * 8}_last_byte_empty', \ - valid_test_case(lambda: uint_type((2 ** ((byte_len - 1) * 8)) - 1)) + valid_test_case(lambda: uint_type((2 ** ((byte_len - 1) * 8)) - 1)) for variation in range(5): yield f'uint_{byte_len * 8}_{mode.to_name()}_{variation}', \ valid_test_case(lambda: uint_case_fn(rng, mode, uint_type)) @@ -38,8 +38,8 @@ def invalid_cases(): for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: byte_len = uint_type.type_byte_length() yield f'uint_{byte_len * 8}_one_byte_longer', \ - invalid_test_case(lambda: (2 ** (byte_len * 8) - 1).to_bytes(byte_len + 1, 'little')) + invalid_test_case(lambda: (2 ** (byte_len * 8) - 1).to_bytes(byte_len + 1, 'little')) for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: byte_len = uint_type.type_byte_length() yield f'uint_{byte_len * 8}_one_byte_shorter', \ - invalid_test_case(lambda: (2 ** ((byte_len - 1) * 8) - 1).to_bytes(byte_len - 1, 'little')) + invalid_test_case(lambda: (2 ** ((byte_len - 1) * 8) - 1).to_bytes(byte_len - 1, 'little')) From dc1892e1131aa8b515983ffcbc7726ae85357d45 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Thu, 22 Aug 2024 21:08:08 +1200 Subject: [PATCH 35/66] Updated NewPayloadRequest --- specs/electra/beacon-chain.md | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 92be2ce253..3c04947d4b 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -73,10 +73,15 @@ - [New `process_pending_balance_deposits`](#new-process_pending_balance_deposits) - [New `process_pending_consolidations`](#new-process_pending_consolidations) - [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates) + - [Execution engine](#execution-engine) + - [Request data](#request-data) + - [Modified `NewPayloadRequest`](#modified-newpayloadrequest) - [Block processing](#block-processing) - [Withdrawals](#withdrawals) - [Modified `get_expected_withdrawals`](#modified-get_expected_withdrawals) - [Modified `process_withdrawals`](#modified-process_withdrawals) + - [Execution payload](#execution-payload) + - [Modified `process_execution_payload`](#modified-process_execution_payload) - [Operations](#operations) - [Modified `process_operations`](#modified-process_operations) - [Attestations](#attestations) @@ -894,6 +899,21 @@ def process_effective_balance_updates(state: BeaconState) -> None: validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, EFFECTIVE_BALANCE_LIMIT) ``` +### Execution engine + +#### Request data + +##### Modified `NewPayloadRequest` + +```python +@dataclass +class NewPayloadRequest(object): + execution_payload: ExecutionPayload + execution_requests: ExecutionLayerRequests + versioned_hashes: Sequence[VersionedHash] + parent_beacon_block_root: Root +``` + ### Block processing ```python @@ -1000,6 +1020,57 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: next_validator_index = ValidatorIndex(next_index % len(state.validators)) state.next_withdrawal_validator_index = next_validator_index ``` + +#### Execution payload + +##### Modified `process_execution_payload` + +*Note*: The function `process_execution_payload` is modified to pass `execution_requests` into `execution_engine.verify_and_notify_new_payload` (via the updated `NewPayloadRequest`). + +```python +def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: + payload = body.execution_payload + + # Verify consistency of the parent hash with respect to the previous execution payload header + assert payload.parent_hash == state.latest_execution_payload_header.block_hash + # Verify prev_randao + assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) + # Verify timestamp + assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) + # Verify commitments are under limit + assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK + # Verify the execution payload is valid + versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments] + assert execution_engine.verify_and_notify_new_payload( + NewPayloadRequest( + execution_payload=payload, + execution_requests=body.execution_requests, # [New in Electra] + versioned_hashes=versioned_hashes, + parent_beacon_block_root=state.latest_block_header.parent_root, + ) + ) + # Cache execution payload header + state.latest_execution_payload_header = ExecutionPayloadHeader( + parent_hash=payload.parent_hash, + fee_recipient=payload.fee_recipient, + state_root=payload.state_root, + receipts_root=payload.receipts_root, + logs_bloom=payload.logs_bloom, + prev_randao=payload.prev_randao, + block_number=payload.block_number, + gas_limit=payload.gas_limit, + gas_used=payload.gas_used, + timestamp=payload.timestamp, + extra_data=payload.extra_data, + base_fee_per_gas=payload.base_fee_per_gas, + block_hash=payload.block_hash, + transactions_root=hash_tree_root(payload.transactions), + withdrawals_root=hash_tree_root(payload.withdrawals), + blob_gas_used=payload.blob_gas_used, + excess_blob_gas=payload.excess_blob_gas + ) +``` + #### Operations ##### Modified `process_operations` From 8e90dd06c3b7797936c23493961c3302f584d0a0 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:35:35 +0800 Subject: [PATCH 36/66] address comment --- .../test_process_withdrawal_request.py | 94 ++++++++++++++----- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py index c4707733a3..ef6de4ff8c 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py @@ -20,11 +20,12 @@ @with_electra_and_later @spec_state_test def test_basic_withdrawal_request(spec, state): + rng = random.Random(1337) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -40,15 +41,38 @@ def test_basic_withdrawal_request(spec, state): spec, state, withdrawal_request ) +@with_electra_and_later +@spec_state_test +def test_basic_withdrawal_request_with_first_validator(spec, state): + # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit + state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH + + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + validator_pubkey = state.validators[validator_index].pubkey + address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, validator_index, address=address + ) + withdrawal_request = spec.WithdrawalRequest( + source_address=address, + validator_pubkey=validator_pubkey, + amount=spec.FULL_EXIT_REQUEST_AMOUNT, + ) + + yield from run_withdrawal_request_processing( + spec, state, withdrawal_request + ) @with_electra_and_later @spec_state_test def test_basic_withdrawal_request_with_compounding_credentials(spec, state): + rng = random.Random(1338) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_compounding_withdrawal_credential(spec, state, validator_index, address=address) @@ -67,9 +91,10 @@ def test_basic_withdrawal_request_with_compounding_credentials(spec, state): @spec_state_test @with_presets([MINIMAL], "need full partial withdrawal queue") def test_basic_withdrawal_request_with_full_partial_withdrawal_queue(spec, state): + rng = random.Random(1339) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -103,11 +128,12 @@ def test_basic_withdrawal_request_with_full_partial_withdrawal_queue(spec, state @with_electra_and_later @spec_state_test def test_incorrect_source_address(spec, state): + rng = random.Random(1340) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 incorrect_address = b"\x33" * 20 @@ -128,11 +154,12 @@ def test_incorrect_source_address(spec, state): @with_electra_and_later @spec_state_test def test_incorrect_withdrawal_credential_prefix(spec, state): + rng = random.Random(1341) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -157,11 +184,12 @@ def test_incorrect_withdrawal_credential_prefix(spec, state): @with_electra_and_later @spec_state_test def test_on_withdrawal_request_initiated_validator(spec, state): + rng = random.Random(1342) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -183,8 +211,9 @@ def test_on_withdrawal_request_initiated_validator(spec, state): @with_electra_and_later @spec_state_test def test_activation_epoch_less_than_shard_committee_period(spec, state): + rng = random.Random(1343) current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 set_eth1_withdrawal_credential_with_balance( @@ -212,9 +241,10 @@ def test_activation_epoch_less_than_shard_committee_period(spec, state): @spec_state_test @with_presets([MINIMAL]) def test_basic_partial_withdrawal_request(spec, state): + rng = random.Random(1344) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -244,9 +274,10 @@ def test_basic_partial_withdrawal_request(spec, state): @spec_state_test @with_presets([MINIMAL]) def test_basic_partial_withdrawal_request_higher_excess_balance(spec, state): + rng = random.Random(1345) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -276,9 +307,10 @@ def test_basic_partial_withdrawal_request_higher_excess_balance(spec, state): @spec_state_test @with_presets([MINIMAL]) def test_basic_partial_withdrawal_request_lower_than_excess_balance(spec, state): + rng = random.Random(1346) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT @@ -309,9 +341,10 @@ def test_basic_partial_withdrawal_request_lower_than_excess_balance(spec, state) @spec_state_test @with_presets([MINIMAL]) def test_partial_withdrawal_request_with_pending_withdrawals(spec, state): + rng = random.Random(1347) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -350,9 +383,10 @@ def test_partial_withdrawal_request_with_pending_withdrawals(spec, state): def test_partial_withdrawal_request_with_pending_withdrawals_and_high_amount( spec, state ): + rng = random.Random(1348) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.UINT64_MAX @@ -388,9 +422,10 @@ def test_partial_withdrawal_request_with_pending_withdrawals_and_high_amount( @spec_state_test @with_presets([MINIMAL]) def test_partial_withdrawal_request_with_high_balance(spec, state): + rng = random.Random(1349) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA @@ -425,9 +460,10 @@ def test_partial_withdrawal_request_with_high_balance(spec, state): @spec_state_test @with_presets([MINIMAL]) def test_partial_withdrawal_request_with_high_amount(spec, state): + rng = random.Random(1350) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 # Set high amount requested to withdraw @@ -458,9 +494,10 @@ def test_partial_withdrawal_request_with_high_amount(spec, state): @spec_state_test @with_presets([MINIMAL]) def test_partial_withdrawal_request_with_low_amount(spec, state): + rng = random.Random(1351) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = 1 @@ -493,9 +530,10 @@ def test_partial_withdrawal_request_with_low_amount(spec, state): @spec_state_test @with_presets([MINIMAL], "need full partial withdrawal queue") def test_partial_withdrawal_queue_full(spec, state): + rng = random.Random(1352) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -523,9 +561,10 @@ def test_partial_withdrawal_queue_full(spec, state): @with_electra_and_later @spec_state_test def test_no_compounding_credentials(spec, state): + rng = random.Random(1353) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -552,9 +591,10 @@ def test_no_compounding_credentials(spec, state): @with_electra_and_later @spec_state_test def test_no_excess_balance(spec, state): + rng = random.Random(1354) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -574,9 +614,10 @@ def test_no_excess_balance(spec, state): @with_electra_and_later @spec_state_test def test_pending_withdrawals_consume_all_excess_balance(spec, state): + rng = random.Random(1355) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -604,9 +645,10 @@ def test_pending_withdrawals_consume_all_excess_balance(spec, state): @with_electra_and_later @spec_state_test def test_insufficient_effective_balance(spec, state): + rng = random.Random(1356) state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -633,11 +675,12 @@ def test_insufficient_effective_balance(spec, state): @with_electra_and_later @spec_state_test def test_partial_withdrawal_incorrect_source_address(spec, state): + rng = random.Random(1357) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 incorrect_address = b"\x33" * 20 @@ -659,11 +702,12 @@ def test_partial_withdrawal_incorrect_source_address(spec, state): @with_electra_and_later @spec_state_test def test_partial_withdrawal_incorrect_withdrawal_credential_prefix(spec, state): + rng = random.Random(1358) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -688,11 +732,12 @@ def test_partial_withdrawal_incorrect_withdrawal_credential_prefix(spec, state): @with_electra_and_later @spec_state_test def test_partial_withdrawal_on_exit_initiated_validator(spec, state): + rng = random.Random(1359) # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT @@ -716,8 +761,9 @@ def test_partial_withdrawal_on_exit_initiated_validator(spec, state): def test_partial_withdrawal_activation_epoch_less_than_shard_committee_period( spec, state ): + rng = random.Random(1360) current_epoch = spec.get_current_epoch(state) - validator_index = random.choice(spec.get_active_validator_indices(state, current_epoch)) + validator_index = rng.choice(spec.get_active_validator_indices(state, current_epoch)) validator_pubkey = state.validators[validator_index].pubkey address = b"\x22" * 20 amount = spec.EFFECTIVE_BALANCE_INCREMENT From f600728dd5b000063e83e6249c87dff70910098e Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Aug 2024 08:07:48 -0500 Subject: [PATCH 37/66] Fix the install_pyspec_test CI check --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 94dcefdb6f..d53e0c47e0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -80,7 +80,7 @@ jobs: - ~/specs-repo install_pyspec_test: docker: - - image: ethpandaops/circleci-python-rust:latest + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: @@ -88,7 +88,7 @@ jobs: - restore_pyspec_cached_venv - run: name: Install pyspec requirements - command: make install_test && make preinstallation + command: make install_test - save_pyspec_cached_venv test-phase0: docker: From a9a1d9ad04a40f7f58a84dfdae1164b78a873459 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Aug 2024 08:22:24 -0500 Subject: [PATCH 38/66] Try no restore/save cache --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d53e0c47e0..5a5ec5627b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -83,13 +83,13 @@ jobs: - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - - restore_cache: - key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} - - restore_pyspec_cached_venv + #- restore_cache: + # key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} + #- restore_pyspec_cached_venv - run: name: Install pyspec requirements command: make install_test - - save_pyspec_cached_venv + #- save_pyspec_cached_venv test-phase0: docker: - image: cimg/python:3.12.4 From 92a801a7411310ada765c3baf5da205bc21272ff Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Aug 2024 08:26:00 -0500 Subject: [PATCH 39/66] Only disable restore_pyspec_cached_venv --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5a5ec5627b..0dd4c61e15 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -83,13 +83,13 @@ jobs: - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - #- restore_cache: - # key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} + - restore_cache: + key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} #- restore_pyspec_cached_venv - run: name: Install pyspec requirements command: make install_test - #- save_pyspec_cached_venv + - save_pyspec_cached_venv test-phase0: docker: - image: cimg/python:3.12.4 From 4850a2801e436e34990693e126230d5425fd06a3 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Aug 2024 09:14:17 -0500 Subject: [PATCH 40/66] Remove line to pull new py_arkworks wheel --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dd4c61e15..cae1892d33 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,7 +85,6 @@ jobs: steps: - restore_cache: key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} - #- restore_pyspec_cached_venv - run: name: Install pyspec requirements command: make install_test From 562798de9ef5bd07af4536554d9f44603170df22 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Aug 2024 09:17:05 -0500 Subject: [PATCH 41/66] Update cache version and add back line --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cae1892d33..7ac281dea9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,13 +35,13 @@ commands: description: "Restore the cache with pyspec keys" steps: - restore_cached_venv: - venv_name: v24-pyspec + venv_name: v25-pyspec reqs_checksum: cache-{{ checksum "setup.py" }}-{{ checksum "requirements_preinstallation.txt" }} save_pyspec_cached_venv: description: Save a venv into a cache with pyspec keys" steps: - save_cached_venv: - venv_name: v24-pyspec + venv_name: v25-pyspec reqs_checksum: cache-{{ checksum "setup.py" }}-{{ checksum "requirements_preinstallation.txt" }} venv_path: ./venv restore_deposit_contract_tester_cached_venv: @@ -85,6 +85,7 @@ jobs: steps: - restore_cache: key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} + - restore_pyspec_cached_venv - run: name: Install pyspec requirements command: make install_test From b8ca7cc87b158e52110db698af5a23cf54c2754c Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 23 Aug 2024 10:12:19 +1200 Subject: [PATCH 42/66] PR comments --- specs/electra/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 3c04947d4b..12de51e290 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -909,9 +909,9 @@ def process_effective_balance_updates(state: BeaconState) -> None: @dataclass class NewPayloadRequest(object): execution_payload: ExecutionPayload - execution_requests: ExecutionLayerRequests versioned_hashes: Sequence[VersionedHash] parent_beacon_block_root: Root + execution_requests: ExecutionLayerRequests # [New in Electra] ``` ### Block processing @@ -1067,7 +1067,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi transactions_root=hash_tree_root(payload.transactions), withdrawals_root=hash_tree_root(payload.withdrawals), blob_gas_used=payload.blob_gas_used, - excess_blob_gas=payload.excess_blob_gas + excess_blob_gas=payload.excess_blob_gas, ) ``` From 725f96349bea21e7f1f0a7f88654874b477354eb Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:02:42 -0500 Subject: [PATCH 43/66] Add blank lines to fix linter --- .../electra/block_processing/test_process_withdrawal_request.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py index ef6de4ff8c..c216b297cb 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_withdrawal_request.py @@ -41,6 +41,7 @@ def test_basic_withdrawal_request(spec, state): spec, state, withdrawal_request ) + @with_electra_and_later @spec_state_test def test_basic_withdrawal_request_with_first_validator(spec, state): @@ -64,6 +65,7 @@ def test_basic_withdrawal_request_with_first_validator(spec, state): spec, state, withdrawal_request ) + @with_electra_and_later @spec_state_test def test_basic_withdrawal_request_with_compounding_credentials(spec, state): From d4f27aff1ffad8e24ed9c09243b3176a5934f1da Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 27 Aug 2024 13:32:46 -0700 Subject: [PATCH 44/66] Fix some EIP-7732 typos --- specs/_features/eip7732/beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index fdcb2b3008..9d7505c2bf 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -184,8 +184,8 @@ class BeaconBlockBody(Container): graffiti: Bytes32 # Arbitrary data # Operations proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] + attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] + attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] deposits: List[Deposit, MAX_DEPOSITS] voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] sync_aggregate: SyncAggregate @@ -662,7 +662,7 @@ def process_execution_payload(state: BeaconState, for_ops(payload.deposit_requests, process_deposit_request) for_ops(payload.withdrawal_requests, process_withdrawal_request) - for_ops(payload, process_consolidation_request) + for_ops(payload.consolidation_requests, process_consolidation_request) # Cache the execution payload header and proposer state.latest_block_hash = payload.block_hash From a5990f99ac2493d4950dcfad6109e3b58be1860d Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Wed, 28 Aug 2024 20:43:34 +0200 Subject: [PATCH 45/66] EIP-7594: PeerDAS explicit csc integer size (#3897) * EIP-7594: PeerDAS explicit csc integer size * add spec test for csc int size * import uint8 * make linter happy * add spec * Update p2p-interface.md * Update specs/_features/eip7594/das-core.md Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> * revert metadata name * Update specs/_features/eip7594/das-core.md Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> * update tests * make linter happy * Make `DATA_COLUMN_SIDECAR_SUBNET_COUNT` in uint8 * add `int` casting for bypassing remerkeable type conversion --------- Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Co-authored-by: Hsiao-Wei Wang --- scripts/build_run_docker_tests.sh | 2 +- specs/_features/eip7594/das-core.md | 12 ++++++------ specs/_features/eip7594/p2p-interface.md | 10 +++++----- .../eip7594/networking/test_get_custody_columns.py | 2 +- .../test/eip7594/unittests/test_config_invariants.py | 4 +++- .../eth2spec/test/eip7594/unittests/test_custody.py | 4 ++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/scripts/build_run_docker_tests.sh b/scripts/build_run_docker_tests.sh index 9d2740ca27..91aa2c8ae1 100755 --- a/scripts/build_run_docker_tests.sh +++ b/scripts/build_run_docker_tests.sh @@ -10,7 +10,7 @@ # Set variables -ALL_EXECUTABLE_SPECS=("phase0" "altair" "bellatrix" "capella" "deneb" "electra" "whisk") +ALL_EXECUTABLE_SPECS=("phase0" "altair" "bellatrix" "capella" "deneb" "electra" "whisk" "eip7594") TEST_PRESET_TYPE=minimal FORK_TO_TEST=phase0 WORKDIR="//consensus-specs//tests//core//pyspec" diff --git a/specs/_features/eip7594/das-core.md b/specs/_features/eip7594/das-core.md index 2096fb9a31..59011cdcd1 100644 --- a/specs/_features/eip7594/das-core.md +++ b/specs/_features/eip7594/das-core.md @@ -67,7 +67,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | Description | | - | - | - | -| `DATA_COLUMN_SIDECAR_SUBNET_COUNT` | `128` | The number of data column sidecar subnets used in the gossipsub protocol | +| `DATA_COLUMN_SIDECAR_SUBNET_COUNT` | `uint8(128)` | The number of data column sidecar subnets used in the gossipsub protocol | ### Custody setting @@ -105,7 +105,7 @@ class MatrixEntry(Container): ### `get_custody_columns` ```python -def get_custody_columns(node_id: NodeID, custody_subnet_count: uint64) -> Sequence[ColumnIndex]: +def get_custody_columns(node_id: NodeID, custody_subnet_count: uint8) -> Sequence[ColumnIndex]: assert custody_subnet_count <= DATA_COLUMN_SIDECAR_SUBNET_COUNT subnet_ids: List[uint64] = [] @@ -113,7 +113,7 @@ def get_custody_columns(node_id: NodeID, custody_subnet_count: uint64) -> Sequen while len(subnet_ids) < custody_subnet_count: subnet_id = ( bytes_to_uint64(hash(uint_to_bytes(uint256(current_id)))[0:8]) - % DATA_COLUMN_SIDECAR_SUBNET_COUNT + % int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) ) if subnet_id not in subnet_ids: subnet_ids.append(subnet_id) @@ -124,9 +124,9 @@ def get_custody_columns(node_id: NodeID, custody_subnet_count: uint64) -> Sequen assert len(subnet_ids) == len(set(subnet_ids)) - columns_per_subnet = NUMBER_OF_COLUMNS // DATA_COLUMN_SIDECAR_SUBNET_COUNT + columns_per_subnet = NUMBER_OF_COLUMNS // int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) return sorted([ - ColumnIndex(DATA_COLUMN_SIDECAR_SUBNET_COUNT * i + subnet_id) + ColumnIndex(int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) * i + subnet_id) for i in range(columns_per_subnet) for subnet_id in subnet_ids ]) @@ -222,7 +222,7 @@ def get_data_column_sidecars(signed_block: SignedBeaconBlock, Each node downloads and custodies a minimum of `CUSTODY_REQUIREMENT` subnets per slot. The particular subnets that the node is required to custody are selected pseudo-randomly (more on this below). -A node *may* choose to custody and serve more than the minimum honesty requirement. Such a node explicitly advertises a number greater than `CUSTODY_REQUIREMENT` via the peer discovery mechanism -- for example, in their ENR (e.g. `custody_subnet_count: 4` if the node custodies `4` subnets each slot) -- up to a `DATA_COLUMN_SIDECAR_SUBNET_COUNT` (i.e. a super-full node). +A node *may* choose to custody and serve more than the minimum honesty requirement. Such a node explicitly advertises a number greater than `CUSTODY_REQUIREMENT` through the peer discovery mechanism, specifically by setting a higher value in the `custody_subnet_count` field within its ENR. This value can be increased up to `DATA_COLUMN_SIDECAR_SUBNET_COUNT`, indicating a super-full node. A node stores the custodied columns for the duration of the pruning period and responds to peer requests for samples on those columns. diff --git a/specs/_features/eip7594/p2p-interface.md b/specs/_features/eip7594/p2p-interface.md index 1b25c5fc5a..38797a2fb0 100644 --- a/specs/_features/eip7594/p2p-interface.md +++ b/specs/_features/eip7594/p2p-interface.md @@ -119,14 +119,14 @@ The `MetaData` stored locally by clients is updated with an additional field to seq_number: uint64 attnets: Bitvector[ATTESTATION_SUBNET_COUNT] syncnets: Bitvector[SYNC_COMMITTEE_SUBNET_COUNT] - custody_subnet_count: uint64 + custody_subnet_count: uint8 # csc ) ``` Where - `seq_number`, `attnets`, and `syncnets` have the same meaning defined in the Altair document. -- `custody_subnet_count` represents the node's custody subnet count. Clients MAY reject ENRs with a value less than `CUSTODY_REQUIREMENT`. +- `csc` represents the node's custody subnet count. Clients MAY reject ENRs with a value less than `CUSTODY_REQUIREMENT`. ### The gossip domain: gossipsub @@ -322,6 +322,6 @@ Requests the MetaData of a peer, using the new `MetaData` definition given above A new field is added to the ENR under the key `csc` to facilitate custody data column discovery. -| Key | Value | -|--------|------------------------------------------| -| `csc` | Custody subnet count, big endian integer | +| Key | Value | +|--------|-------------------------------------| +| `csc` | Custody subnet count, uint8 integer | diff --git a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py index b41f19a6ca..692b73e49d 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py @@ -20,7 +20,7 @@ def _run_get_custody_columns(spec, rng, node_id=None, custody_subnet_count=None) assert len(result) == len(set(result)) assert len(result) == ( - custody_subnet_count * spec.config.NUMBER_OF_COLUMNS // spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT + int(custody_subnet_count) * spec.config.NUMBER_OF_COLUMNS // int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) ) assert all(i < spec.config.NUMBER_OF_COLUMNS for i in result) python_list_result = [int(i) for i in result] diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py index fc54cc3088..fbbae4e8f8 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py @@ -3,6 +3,7 @@ spec_test, with_eip7594_and_later, ) +from eth2spec.utils.ssz.ssz_typing import uint8 @with_eip7594_and_later @@ -12,9 +13,10 @@ def test_invariants(spec): assert spec.FIELD_ELEMENTS_PER_BLOB % spec.FIELD_ELEMENTS_PER_CELL == 0 assert spec.FIELD_ELEMENTS_PER_EXT_BLOB % spec.config.NUMBER_OF_COLUMNS == 0 assert spec.config.SAMPLES_PER_SLOT <= spec.config.NUMBER_OF_COLUMNS + assert spec.config.NUMBER_OF_COLUMNS == uint8(spec.config.NUMBER_OF_COLUMNS) # ENR field is uint8 assert spec.config.CUSTODY_REQUIREMENT <= spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT assert spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT <= spec.config.NUMBER_OF_COLUMNS - assert spec.config.NUMBER_OF_COLUMNS % spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT == 0 + assert spec.config.NUMBER_OF_COLUMNS % int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) == 0 assert spec.config.MAX_REQUEST_DATA_COLUMN_SIDECARS == ( spec.config.MAX_REQUEST_BLOCKS_DENEB * spec.config.NUMBER_OF_COLUMNS ) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py index 5db3635a8e..27aee3457a 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py @@ -9,9 +9,9 @@ def run_get_custody_columns(spec, peer_count, custody_subnet_count): assignments = [spec.get_custody_columns(node_id, custody_subnet_count) for node_id in range(peer_count)] - columns_per_subnet = spec.config.NUMBER_OF_COLUMNS // spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT + columns_per_subnet = spec.config.NUMBER_OF_COLUMNS // int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) for assignment in assignments: - assert len(assignment) == custody_subnet_count * columns_per_subnet + assert len(assignment) == int(custody_subnet_count) * columns_per_subnet assert len(assignment) == len(set(assignment)) From c7631634fb90a13e6f2de0be26b7499f6270bfa8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 28 Aug 2024 16:01:10 -0600 Subject: [PATCH 46/66] harmonize `process_withdrawals` spec with #3761 --- specs/electra/beacon-chain.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index cb5ee6a7a9..b18006b642 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1022,10 +1022,9 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: expected_withdrawals, partial_withdrawals_count = get_expected_withdrawals(state) # [Modified in Electra:EIP7251] - assert len(payload.withdrawals) == len(expected_withdrawals) + assert payload.withdrawals == expected_withdrawals - for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals): - assert withdrawal == expected_withdrawal + for withdrawal in expected_withdrawals: decrease_balance(state, withdrawal.validator_index, withdrawal.amount) # Update pending partial withdrawals [New in Electra:EIP7251] From 78cc0a6e9162e7a48d3debd3ca3046b27942c42b Mon Sep 17 00:00:00 2001 From: Pawan Dhananjay Date: Fri, 30 Aug 2024 12:25:26 -0700 Subject: [PATCH 47/66] Change csc types to uint64 --- specs/_features/eip7594/das-core.md | 10 +++++----- specs/_features/eip7594/p2p-interface.md | 10 +++++----- .../eip7594/networking/test_get_custody_columns.py | 2 +- .../test/eip7594/unittests/test_config_invariants.py | 4 +--- .../eth2spec/test/eip7594/unittests/test_custody.py | 4 ++-- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/specs/_features/eip7594/das-core.md b/specs/_features/eip7594/das-core.md index 59011cdcd1..25e58a1334 100644 --- a/specs/_features/eip7594/das-core.md +++ b/specs/_features/eip7594/das-core.md @@ -67,7 +67,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | Description | | - | - | - | -| `DATA_COLUMN_SIDECAR_SUBNET_COUNT` | `uint8(128)` | The number of data column sidecar subnets used in the gossipsub protocol | +| `DATA_COLUMN_SIDECAR_SUBNET_COUNT` | `uint64(128)` | The number of data column sidecar subnets used in the gossipsub protocol | ### Custody setting @@ -105,7 +105,7 @@ class MatrixEntry(Container): ### `get_custody_columns` ```python -def get_custody_columns(node_id: NodeID, custody_subnet_count: uint8) -> Sequence[ColumnIndex]: +def get_custody_columns(node_id: NodeID, custody_subnet_count: uint64) -> Sequence[ColumnIndex]: assert custody_subnet_count <= DATA_COLUMN_SIDECAR_SUBNET_COUNT subnet_ids: List[uint64] = [] @@ -113,7 +113,7 @@ def get_custody_columns(node_id: NodeID, custody_subnet_count: uint8) -> Sequenc while len(subnet_ids) < custody_subnet_count: subnet_id = ( bytes_to_uint64(hash(uint_to_bytes(uint256(current_id)))[0:8]) - % int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) + % DATA_COLUMN_SIDECAR_SUBNET_COUNT ) if subnet_id not in subnet_ids: subnet_ids.append(subnet_id) @@ -124,9 +124,9 @@ def get_custody_columns(node_id: NodeID, custody_subnet_count: uint8) -> Sequenc assert len(subnet_ids) == len(set(subnet_ids)) - columns_per_subnet = NUMBER_OF_COLUMNS // int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) + columns_per_subnet = NUMBER_OF_COLUMNS // DATA_COLUMN_SIDECAR_SUBNET_COUNT return sorted([ - ColumnIndex(int(DATA_COLUMN_SIDECAR_SUBNET_COUNT) * i + subnet_id) + ColumnIndex(DATA_COLUMN_SIDECAR_SUBNET_COUNT * i + subnet_id) for i in range(columns_per_subnet) for subnet_id in subnet_ids ]) diff --git a/specs/_features/eip7594/p2p-interface.md b/specs/_features/eip7594/p2p-interface.md index 38797a2fb0..7f68f7ba60 100644 --- a/specs/_features/eip7594/p2p-interface.md +++ b/specs/_features/eip7594/p2p-interface.md @@ -119,14 +119,14 @@ The `MetaData` stored locally by clients is updated with an additional field to seq_number: uint64 attnets: Bitvector[ATTESTATION_SUBNET_COUNT] syncnets: Bitvector[SYNC_COMMITTEE_SUBNET_COUNT] - custody_subnet_count: uint8 # csc + custody_subnet_count: uint64 # csc ) ``` Where - `seq_number`, `attnets`, and `syncnets` have the same meaning defined in the Altair document. -- `csc` represents the node's custody subnet count. Clients MAY reject ENRs with a value less than `CUSTODY_REQUIREMENT`. +- `custody_subnet_count` represents the node's custody subnet count. Clients MAY reject peers with a value less than `CUSTODY_REQUIREMENT`. ### The gossip domain: gossipsub @@ -322,6 +322,6 @@ Requests the MetaData of a peer, using the new `MetaData` definition given above A new field is added to the ENR under the key `csc` to facilitate custody data column discovery. -| Key | Value | -|--------|-------------------------------------| -| `csc` | Custody subnet count, uint8 integer | +| Key | Value | +|--------|------------------------------------------| +| `csc` | Custody subnet count, big endian integer | diff --git a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py index 692b73e49d..b41f19a6ca 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py @@ -20,7 +20,7 @@ def _run_get_custody_columns(spec, rng, node_id=None, custody_subnet_count=None) assert len(result) == len(set(result)) assert len(result) == ( - int(custody_subnet_count) * spec.config.NUMBER_OF_COLUMNS // int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) + custody_subnet_count * spec.config.NUMBER_OF_COLUMNS // spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT ) assert all(i < spec.config.NUMBER_OF_COLUMNS for i in result) python_list_result = [int(i) for i in result] diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py index fbbae4e8f8..fc54cc3088 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py @@ -3,7 +3,6 @@ spec_test, with_eip7594_and_later, ) -from eth2spec.utils.ssz.ssz_typing import uint8 @with_eip7594_and_later @@ -13,10 +12,9 @@ def test_invariants(spec): assert spec.FIELD_ELEMENTS_PER_BLOB % spec.FIELD_ELEMENTS_PER_CELL == 0 assert spec.FIELD_ELEMENTS_PER_EXT_BLOB % spec.config.NUMBER_OF_COLUMNS == 0 assert spec.config.SAMPLES_PER_SLOT <= spec.config.NUMBER_OF_COLUMNS - assert spec.config.NUMBER_OF_COLUMNS == uint8(spec.config.NUMBER_OF_COLUMNS) # ENR field is uint8 assert spec.config.CUSTODY_REQUIREMENT <= spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT assert spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT <= spec.config.NUMBER_OF_COLUMNS - assert spec.config.NUMBER_OF_COLUMNS % int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) == 0 + assert spec.config.NUMBER_OF_COLUMNS % spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT == 0 assert spec.config.MAX_REQUEST_DATA_COLUMN_SIDECARS == ( spec.config.MAX_REQUEST_BLOCKS_DENEB * spec.config.NUMBER_OF_COLUMNS ) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py index 27aee3457a..5db3635a8e 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/test_custody.py @@ -9,9 +9,9 @@ def run_get_custody_columns(spec, peer_count, custody_subnet_count): assignments = [spec.get_custody_columns(node_id, custody_subnet_count) for node_id in range(peer_count)] - columns_per_subnet = spec.config.NUMBER_OF_COLUMNS // int(spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT) + columns_per_subnet = spec.config.NUMBER_OF_COLUMNS // spec.config.DATA_COLUMN_SIDECAR_SUBNET_COUNT for assignment in assignments: - assert len(assignment) == int(custody_subnet_count) * columns_per_subnet + assert len(assignment) == custody_subnet_count * columns_per_subnet assert len(assignment) == len(set(assignment)) From 6938dcc2fa2698a58989aa99f29ab3dea270bee9 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 30 Aug 2024 16:16:44 -0600 Subject: [PATCH 48/66] simplify name of helper `get_validator_max_effective_balance` --- specs/electra/beacon-chain.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index b18006b642..8565379ec0 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -50,7 +50,7 @@ - [Modified `is_partially_withdrawable_validator`](#modified-is_partially_withdrawable_validator) - [Misc](#misc-1) - [New `get_committee_indices`](#new-get_committee_indices) - - [New `get_validator_max_effective_balance`](#new-get_validator_max_effective_balance) + - [New `get_max_effective_balance`](#new-get_max_effective_balance) - [Beacon state accessors](#beacon-state-accessors) - [New `get_balance_churn_limit`](#new-get_balance_churn_limit) - [New `get_activation_exit_churn_limit`](#new-get_activation_exit_churn_limit) @@ -512,14 +512,14 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch: #### Modified `is_partially_withdrawable_validator` -*Note*: The function `is_partially_withdrawable_validator` is modified to use `get_validator_max_effective_balance` instead of `MAX_EFFECTIVE_BALANCE` and `has_execution_withdrawal_credential` instead of `has_eth1_withdrawal_credential`. +*Note*: The function `is_partially_withdrawable_validator` is modified to use `get_max_effective_balance` instead of `MAX_EFFECTIVE_BALANCE` and `has_execution_withdrawal_credential` instead of `has_eth1_withdrawal_credential`. ```python def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) -> bool: """ Check if ``validator`` is partially withdrawable. """ - max_effective_balance = get_validator_max_effective_balance(validator) + max_effective_balance = get_max_effective_balance(validator) has_max_effective_balance = validator.effective_balance == max_effective_balance # [Modified in Electra:EIP7251] has_excess_balance = balance > max_effective_balance # [Modified in Electra:EIP7251] return ( @@ -538,10 +538,10 @@ def get_committee_indices(committee_bits: Bitvector) -> Sequence[CommitteeIndex] return [CommitteeIndex(index) for index, bit in enumerate(committee_bits) if bit] ``` -#### New `get_validator_max_effective_balance` +#### New `get_max_effective_balance` ```python -def get_validator_max_effective_balance(validator: Validator) -> Gwei: +def get_max_effective_balance(validator: Validator) -> Gwei: """ Get max effective balance for ``validator``. """ @@ -588,7 +588,7 @@ def get_consolidation_churn_limit(state: BeaconState) -> Gwei: ```python def get_active_balance(state: BeaconState, validator_index: ValidatorIndex) -> Gwei: - max_effective_balance = get_validator_max_effective_balance(state.validators[validator_index]) + max_effective_balance = get_max_effective_balance(state.validators[validator_index]) return min(state.balances[validator_index], max_effective_balance) ``` @@ -875,7 +875,7 @@ def process_pending_balance_deposits(state: BeaconState) -> None: if processed_amount + deposit.amount > available_for_processing: break # Deposit fits in the churn, process it. Increase balance and consume churn. - else: + else: increase_balance(state, deposit.index, deposit.amount) processed_amount += deposit.amount # Regardless of how the deposit was handled, we move on in the queue. @@ -1005,7 +1005,7 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], index=withdrawal_index, validator_index=validator_index, address=ExecutionAddress(validator.withdrawal_credentials[12:]), - amount=balance - get_validator_max_effective_balance(validator), # [Modified in Electra:EIP7251] + amount=balance - get_max_effective_balance(validator), # [Modified in Electra:EIP7251] )) withdrawal_index += WithdrawalIndex(1) if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: @@ -1495,7 +1495,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, balance = state.balances[index] # [Modified in Electra:EIP7251] validator.effective_balance = min( - balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_validator_max_effective_balance(validator)) + balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_max_effective_balance(validator)) if validator.effective_balance >= MIN_ACTIVATION_BALANCE: validator.activation_eligibility_epoch = GENESIS_EPOCH validator.activation_epoch = GENESIS_EPOCH From 38baa573c7bde6df0e1bac8e42a9b32743a19ab3 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 2 Sep 2024 11:30:54 +1200 Subject: [PATCH 49/66] Rename ExecutionLayerRequests to ExecutionRequests --- specs/electra/beacon-chain.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index f93c327caa..f3d5667770 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -30,7 +30,7 @@ - [`WithdrawalRequest`](#withdrawalrequest) - [`ConsolidationRequest`](#consolidationrequest) - [`PendingConsolidation`](#pendingconsolidation) - - [`ExecutionLayerRequests`](#executionlayerrequests) + - [`ExecutionRequests`](#executionrequests) - [Modified Containers](#modified-containers) - [`AttesterSlashing`](#attesterslashing) - [`BeaconBlockBody`](#beaconblockbody) @@ -260,14 +260,14 @@ class PendingConsolidation(Container): target_index: ValidatorIndex ``` -#### `ExecutionLayerRequests` +#### `ExecutionRequests` *Note*: This container holds requests from the execution layer that are received in [ `ExecutionPayloadV4`](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#executionpayloadv4) via the Engine API. These requests are required for CL state transition (see `BeaconBlockBody`). ```python -class ExecutionLayerRequests(Container): +class ExecutionRequests(Container): deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110] withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7002:EIP7251] consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251] @@ -301,7 +301,7 @@ class BeaconBlockBody(Container): execution_payload: ExecutionPayload bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - execution_requests: ExecutionLayerRequests # [New in Electra] + execution_requests: ExecutionRequests # [New in Electra] ``` ### Extended Containers @@ -911,7 +911,7 @@ class NewPayloadRequest(object): execution_payload: ExecutionPayload versioned_hashes: Sequence[VersionedHash] parent_beacon_block_root: Root - execution_requests: ExecutionLayerRequests # [New in Electra] + execution_requests: ExecutionRequests # [New in Electra] ``` ### Block processing From 31225f1acf3f1e3f1e50033fdb314a4a6e82a4bc Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Mon, 2 Sep 2024 13:56:57 +1200 Subject: [PATCH 50/66] Temp fix for linter on eip-7732 beacon chain spec --- specs/_features/eip7732/beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index 6ce30cea72..068fff0b01 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -655,6 +655,7 @@ def process_execution_payload(state: BeaconState, execution_payload=payload, versioned_hashes=versioned_hashes, parent_beacon_block_root=state.latest_block_header.parent_root, + execution_requests=ExecutionRequests(), # TODO: fix me (making linter happy) ) ) From 88a76574b6f6ee3ee63c2e433f67de50d32762e5 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:35:02 -0500 Subject: [PATCH 51/66] Update csc description Co-authored-by: Anton Nashatyrev --- specs/_features/eip7594/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/_features/eip7594/p2p-interface.md b/specs/_features/eip7594/p2p-interface.md index 7f68f7ba60..9087a8210c 100644 --- a/specs/_features/eip7594/p2p-interface.md +++ b/specs/_features/eip7594/p2p-interface.md @@ -324,4 +324,4 @@ A new field is added to the ENR under the key `csc` to facilitate custody data c | Key | Value | |--------|------------------------------------------| -| `csc` | Custody subnet count, big endian integer | +| `csc` | Custody subnet count, `uint64` big endian integer with no leading zero bytes (`0` is encoded as empty byte string) | From abf382a60760a9bf60d660ada6a117f57fb2ac45 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 4 Sep 2024 12:58:50 -0300 Subject: [PATCH 52/66] Fix 7732 --- specs/_features/eip7732/beacon-chain.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index 068fff0b01..9df736750a 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -156,6 +156,7 @@ class SignedExecutionPayloadHeader(Container): ```python class ExecutionPayloadEnvelope(Container): payload: ExecutionPayload + execution_requests: ExecutionRequests builder_index: ValidatorIndex beacon_block_root: Root blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] @@ -175,7 +176,7 @@ class SignedExecutionPayloadEnvelope(Container): #### `BeaconBlockBody` -**Note:** The Beacon Block body is modified to contain a `Signed ExecutionPayloadHeader`. The containers `BeaconBlock` and `SignedBeaconBlock` are modified indirectly. +**Note:** The Beacon Block body is modified to contain a `Signed ExecutionPayloadHeader`. The containers `BeaconBlock` and `SignedBeaconBlock` are modified indirectly. The field `execution_requests` is removed from the beacon block body and moved into the signed execution payload envelope. ```python class BeaconBlockBody(Container): @@ -191,8 +192,9 @@ class BeaconBlockBody(Container): sync_aggregate: SyncAggregate # Execution # Removed execution_payload [Removed in EIP-7732] - # Removed blob_kzg_commitments [Removed in EIP-7732] bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] + # Removed blob_kzg_commitments [Removed in EIP-7732] + # Removed execution_requests [Removed in EIP-7732] # PBS signed_execution_payload_header: SignedExecutionPayloadHeader # [New in EIP-7732] payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS] # [New in EIP-7732] @@ -650,12 +652,13 @@ def process_execution_payload(state: BeaconState, # Verify the execution payload is valid versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in envelope.blob_kzg_commitments] + requests = envelope.execution_requests assert execution_engine.verify_and_notify_new_payload( NewPayloadRequest( execution_payload=payload, versioned_hashes=versioned_hashes, parent_beacon_block_root=state.latest_block_header.parent_root, - execution_requests=ExecutionRequests(), # TODO: fix me (making linter happy) + execution_requests=requests, ) ) @@ -664,9 +667,9 @@ def process_execution_payload(state: BeaconState, for operation in operations: fn(state, operation) - for_ops(payload.deposit_requests, process_deposit_request) - for_ops(payload.withdrawal_requests, process_withdrawal_request) - for_ops(payload.consolidation_requests, process_consolidation_request) + for_ops(requests.deposit_requests, process_deposit_request) + for_ops(requests.withdrawal_requests, process_withdrawal_request) + for_ops(requests.consolidation_requests, process_consolidation_request) # Cache the execution payload header and proposer state.latest_block_hash = payload.block_hash From 07401893a354c44ea8681993b4b74994435f7233 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:51:26 -0500 Subject: [PATCH 53/66] Delete g2_lincomb in poly-commits-sampling spec (#3913) --- .../polynomial-commitments-sampling.md | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 869f471844..ea76243984 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -15,8 +15,6 @@ - [BLS12-381 helpers](#bls12-381-helpers) - [`cell_to_coset_evals`](#cell_to_coset_evals) - [`coset_evals_to_cell`](#coset_evals_to_cell) - - [Linear combinations](#linear-combinations) - - [`g2_lincomb`](#g2_lincomb) - [FFTs](#ffts) - [`_fft_field`](#_fft_field) - [`fft_field`](#fft_field) @@ -125,28 +123,6 @@ def coset_evals_to_cell(coset_evals: CosetEvals) -> Cell: return Cell(cell) ``` -### Linear combinations - -#### `g2_lincomb` - -```python -def g2_lincomb(points: Sequence[G2Point], scalars: Sequence[BLSFieldElement]) -> Bytes96: - """ - BLS multiscalar multiplication in G2. This can be naively implemented using double-and-add. - """ - assert len(points) == len(scalars) - - if len(points) == 0: - return bls.G2_to_bytes96(bls.Z2()) - - points_g2 = [] - for point in points: - points_g2.append(bls.bytes96_to_G2(point)) - - result = bls.multi_exp(points_g2, scalars) - return Bytes96(bls.G2_to_bytes96(result)) -``` - ### FFTs #### `_fft_field` From beff03d4e0b330323a89669754ebdc9a1b308cfb Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 6 Sep 2024 09:18:26 +1200 Subject: [PATCH 54/66] Updated verify_and_notify_new_payload and notify_new_payload --- specs/electra/beacon-chain.md | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index f3d5667770..8f6ef2d351 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -76,6 +76,9 @@ - [Execution engine](#execution-engine) - [Request data](#request-data) - [Modified `NewPayloadRequest`](#modified-newpayloadrequest) + - [Engine APIs](#engine-apis) + - [Modified `notify_new_payload`](#modified-notify_new_payload) + - [Modified `verify_and_notify_new_payload`](#modified-verify_and_notify_new_payload) - [Block processing](#block-processing) - [Withdrawals](#withdrawals) - [Modified `get_expected_withdrawals`](#modified-get_expected_withdrawals) @@ -914,6 +917,51 @@ class NewPayloadRequest(object): execution_requests: ExecutionRequests # [New in Electra] ``` +#### Engine APIs + +##### Modified `notify_new_payload` + +*Note*: The function `notify_new_payload` is modified to include the additional `execution_requests` parameter in Electra. + +```python +def notify_new_payload(self: ExecutionEngine, + execution_payload: ExecutionPayload, + execution_requests: ExecutionRequests, + parent_beacon_block_root: Root) -> bool: + """ + Return ``True`` if and only if ``execution_payload`` and ``execution_requests`` are valid with respect to ``self.execution_state``. + """ + ... +``` + +##### Modified `verify_and_notify_new_payload` + +*Note*: The function `verify_and_notify_new_payload` is modified to pass the additional parameter `execution_requests` +when calling `notify_new_payload` in Electra. + +```python +def verify_and_notify_new_payload(self: ExecutionEngine, + new_payload_request: NewPayloadRequest) -> bool: + """ + Return ``True`` if and only if ``new_payload_request`` is valid with respect to ``self.execution_state``. + """ + execution_payload = new_payload_request.execution_payload + execution_requests = new_payload_request.execution_requests # [New in Electra] + parent_beacon_block_root = new_payload_request.parent_beacon_block_root + + if not self.is_valid_block_hash(execution_payload, parent_beacon_block_root): + return False + + if not self.is_valid_versioned_hashes(new_payload_request): + return False + + # [Modified in Electra] + if not self.notify_new_payload(execution_payload, execution_requests, parent_beacon_block_root): + return False + + return True +``` + ### Block processing ```python From c8dd790484cc75a4d2873b9120cf4928ceb428a6 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 6 Sep 2024 09:51:34 +1200 Subject: [PATCH 55/66] Fix linter --- specs/electra/beacon-chain.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 8f6ef2d351..8e54914367 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -929,7 +929,8 @@ def notify_new_payload(self: ExecutionEngine, execution_requests: ExecutionRequests, parent_beacon_block_root: Root) -> bool: """ - Return ``True`` if and only if ``execution_payload`` and ``execution_requests`` are valid with respect to ``self.execution_state``. + Return ``True`` if and only if ``execution_payload`` and ``execution_requests`` + are valid with respect to ``self.execution_state``. """ ... ``` @@ -956,7 +957,10 @@ def verify_and_notify_new_payload(self: ExecutionEngine, return False # [Modified in Electra] - if not self.notify_new_payload(execution_payload, execution_requests, parent_beacon_block_root): + if not self.notify_new_payload( + execution_payload, + execution_requests, + parent_beacon_block_root): return False return True From 622ccd1d4bd1a06e51a381ecb98fc65ea63aa41b Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Fri, 6 Sep 2024 10:08:36 +1200 Subject: [PATCH 56/66] Updated ElectraSpecBuilder (NoopExecutionEngine#notify_new_payload) --- pysetup/spec_builders/electra.py | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/pysetup/spec_builders/electra.py b/pysetup/spec_builders/electra.py index ca02ee927c..2ab1f5ecfb 100644 --- a/pysetup/spec_builders/electra.py +++ b/pysetup/spec_builders/electra.py @@ -19,3 +19,41 @@ def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]: 'CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(86)', 'NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(87)', } + + + @classmethod + def execution_engine_cls(cls) -> str: + return """ +class NoopExecutionEngine(ExecutionEngine): + + def notify_new_payload(self: ExecutionEngine, + execution_payload: ExecutionPayload, + execution_requests: ExecutionRequests, + parent_beacon_block_root: Root) -> bool: + return True + + def notify_forkchoice_updated(self: ExecutionEngine, + head_block_hash: Hash32, + safe_block_hash: Hash32, + finalized_block_hash: Hash32, + payload_attributes: Optional[PayloadAttributes]) -> Optional[PayloadId]: + pass + + def get_payload(self: ExecutionEngine, payload_id: PayloadId) -> GetPayloadResponse: + # pylint: disable=unused-argument + raise NotImplementedError("no default block production") + + def is_valid_block_hash(self: ExecutionEngine, + execution_payload: ExecutionPayload, + parent_beacon_block_root: Root) -> bool: + return True + + def is_valid_versioned_hashes(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool: + return True + + def verify_and_notify_new_payload(self: ExecutionEngine, + new_payload_request: NewPayloadRequest) -> bool: + return True + + +EXECUTION_ENGINE = NoopExecutionEngine()""" \ No newline at end of file From 1702f88f78541bc44645482db298fa297371adac Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:26:44 -0700 Subject: [PATCH 57/66] Minor fixes --- specs/electra/beacon-chain.md | 4 ++-- tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 42d5f386b6..3dca59e1df 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1145,7 +1145,7 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.proposer_slashings, process_proposer_slashing) for_ops(body.attester_slashings, process_attester_slashing) for_ops(body.attestations, process_attestation) # [Modified in Electra:EIP7549] - for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251] + for_ops(body.deposits, process_deposit) for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251] for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) for_ops(body.execution_payload.deposit_requests, process_deposit_request) # [New in Electra:EIP6110] @@ -1206,7 +1206,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: ###### Modified `apply_deposit` -*Note*: The function `process_deposit` is modified to support EIP7251. +*Note*: The function `apply_deposit` is modified to support EIP7251. ```python def apply_deposit(state: BeaconState, diff --git a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py index c2b7af5a44..5cd8e7de65 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py +++ b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py @@ -36,8 +36,6 @@ def get_process_calls(spec): 'process_participation_record_updates' ), 'process_sync_committee_updates', # altair - 'process_full_withdrawals', # capella - 'process_partial_withdrawals', # capella # TODO: add sharding processing functions when spec stabilizes. ] From 15a5b682609c0df8c87af8360f894f761a53eae6 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 10 Sep 2024 11:41:45 -0600 Subject: [PATCH 58/66] Remove unnecessary signing domain for consolidations --- specs/electra/beacon-chain.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 3dca59e1df..02bd33160f 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -12,7 +12,6 @@ - [Constants](#constants) - [Misc](#misc) - [Withdrawal prefixes](#withdrawal-prefixes) - - [Domains](#domains) - [Preset](#preset) - [Gwei values](#gwei-values) - [Rewards and penalties](#rewards-and-penalties) @@ -130,12 +129,6 @@ The following values are (non-configurable) constants used throughout the specif | - | - | | `COMPOUNDING_WITHDRAWAL_PREFIX` | `Bytes1('0x02')` | -### Domains - -| Name | Value | -| - | - | -| `DOMAIN_CONSOLIDATION` | `DomainType('0x0B000000')` | - ## Preset ### Gwei values From 7cacee6ad64483357a7332be6a11784de1242428 Mon Sep 17 00:00:00 2001 From: Parithosh Jayanthi Date: Mon, 16 Sep 2024 18:16:07 +0200 Subject: [PATCH 59/66] Add cronjob for test vector generation (#3922) --- .github/workflows/generate_vectors.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/generate_vectors.yml b/.github/workflows/generate_vectors.yml index 7a45953b8a..b0af503543 100644 --- a/.github/workflows/generate_vectors.yml +++ b/.github/workflows/generate_vectors.yml @@ -12,6 +12,8 @@ on: default: dev type: string required: true + schedule: + - cron: '0 2 * * *' jobs: generate-tests: @@ -22,7 +24,7 @@ jobs: with: repository: 'ethereum/consensus-specs' path: 'consensus-specs' - ref: ${{ inputs.source_ref }} + ref: ${{ inputs.source_ref || 'dev' }} - name: Checkout consensus-spec-tests repository uses: actions/checkout@v4 with: From ea90d6f27da0202876d07cdc152b6ecfa3523f3f Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Tue, 17 Sep 2024 14:56:59 -0500 Subject: [PATCH 60/66] Fix test vector generators to work with Python 3.12 --- .github/workflows/generate_vectors.yml | 4 ++-- Makefile | 8 ++++++-- requirements_preinstallation.txt | 3 ++- setup.py | 18 +++++++++++------- tests/generators/bls/requirements.txt | 2 -- .../epoch_processing/requirements.txt | 2 -- tests/generators/finality/requirements.txt | 2 -- tests/generators/fork_choice/requirements.txt | 2 -- tests/generators/forks/requirements.txt | 2 -- tests/generators/genesis/requirements.txt | 2 -- tests/generators/kzg_4844/requirements.txt | 2 -- tests/generators/kzg_7594/requirements.txt | 2 -- tests/generators/light_client/requirements.txt | 2 -- tests/generators/merkle_proof/requirements.txt | 2 -- tests/generators/networking/requirements.txt | 2 -- tests/generators/operations/requirements.txt | 2 -- tests/generators/random/requirements.txt | 2 -- tests/generators/rewards/requirements.txt | 2 -- tests/generators/sanity/requirements.txt | 2 -- tests/generators/shuffling/requirements.txt | 2 -- tests/generators/ssz_generic/requirements.txt | 2 -- tests/generators/ssz_static/requirements.txt | 2 -- tests/generators/sync/requirements.txt | 2 -- tests/generators/transition/requirements.txt | 2 -- 24 files changed, 21 insertions(+), 52 deletions(-) delete mode 100644 tests/generators/bls/requirements.txt delete mode 100644 tests/generators/epoch_processing/requirements.txt delete mode 100644 tests/generators/finality/requirements.txt delete mode 100644 tests/generators/fork_choice/requirements.txt delete mode 100644 tests/generators/forks/requirements.txt delete mode 100644 tests/generators/genesis/requirements.txt delete mode 100644 tests/generators/kzg_4844/requirements.txt delete mode 100644 tests/generators/kzg_7594/requirements.txt delete mode 100644 tests/generators/light_client/requirements.txt delete mode 100644 tests/generators/merkle_proof/requirements.txt delete mode 100644 tests/generators/networking/requirements.txt delete mode 100644 tests/generators/operations/requirements.txt delete mode 100644 tests/generators/random/requirements.txt delete mode 100644 tests/generators/rewards/requirements.txt delete mode 100644 tests/generators/sanity/requirements.txt delete mode 100644 tests/generators/shuffling/requirements.txt delete mode 100644 tests/generators/ssz_generic/requirements.txt delete mode 100644 tests/generators/ssz_static/requirements.txt delete mode 100644 tests/generators/sync/requirements.txt delete mode 100644 tests/generators/transition/requirements.txt diff --git a/.github/workflows/generate_vectors.yml b/.github/workflows/generate_vectors.yml index b0af503543..0d8aeb0eed 100644 --- a/.github/workflows/generate_vectors.yml +++ b/.github/workflows/generate_vectors.yml @@ -17,14 +17,14 @@ on: jobs: generate-tests: - runs-on: [self-hosted-ghr-custom, size-chungus-x64, profile-consensusSpecs] + runs-on: [self-hosted-ghr-custom, size-xl-x64, profile-consensusSpecs] steps: - name: Checkout repository uses: actions/checkout@v4 with: repository: 'ethereum/consensus-specs' path: 'consensus-specs' - ref: ${{ inputs.source_ref || 'dev' }} + ref: ${{ inputs.ref || 'dev' }} - name: Checkout consensus-spec-tests repository uses: actions/checkout@v4 with: diff --git a/Makefile b/Makefile index 23b6a6035d..c805b456b0 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,9 @@ dist_check: dist_upload: python3 -m twine upload dist/* +build_wheel: install_test pyspec + . venv/bin/activate && \ + python3 -m build --no-isolation --outdir ./dist ./ # "make generate_tests" to run all generators generate_tests: $(GENERATOR_TARGETS) @@ -195,7 +198,8 @@ define run_generator cd $(GENERATOR_DIR)/$(1); \ if ! test -d venv; then python3 -m venv venv; fi; \ . venv/bin/activate; \ - pip3 install -r requirements.txt; \ + pip3 install ../../../dist/eth2spec-*.whl; \ + pip3 install 'eth2spec[generator]'; \ python3 main.py -o $(CURRENT_DIR)/$(TEST_VECTOR_DIR); \ echo "generator $(1) finished" endef @@ -217,7 +221,7 @@ gen_kzg_setups: # For any generator, build it using the run_generator function. # (creation of output dir is a dependency) -gen_%: $(TEST_VECTOR_DIR) +gen_%: build_wheel $(TEST_VECTOR_DIR) $(call run_generator,$*) detect_generator_incomplete: $(TEST_VECTOR_DIR) diff --git a/requirements_preinstallation.txt b/requirements_preinstallation.txt index 1aca6ad0e0..83128122e5 100644 --- a/requirements_preinstallation.txt +++ b/requirements_preinstallation.txt @@ -1,4 +1,5 @@ pip>=24.0.0 wheel>=0.44.0 setuptools>=72.0.0 -pylint>=3.2.0 \ No newline at end of file +pylint>=3.2.0 +build>=1.2.2 \ No newline at end of file diff --git a/setup.py b/setup.py index 0ae71212cb..eb7a5528af 100644 --- a/setup.py +++ b/setup.py @@ -526,24 +526,28 @@ def run(self): author="ethereum", url="https://github.com/ethereum/eth2.0-specs", include_package_data=False, - package_data={'configs': ['*.yaml'], - 'presets': ['*.yaml'], - 'specs': ['**/*.md'], - 'eth2spec': ['VERSION.txt']}, + package_data={ + 'configs': ['*.yaml'], + 'eth2spec': ['VERSION.txt'], + 'presets': ['**/*.yaml', '**/*.json'], + 'specs': ['**/*.md'], + 'sync': ['optimistic.md'], + }, package_dir={ - "eth2spec": "tests/core/pyspec/eth2spec", "configs": "configs", + "eth2spec": "tests/core/pyspec/eth2spec", "presets": "presets", "specs": "specs", + "sync": "sync", }, - packages=find_packages(where='tests/core/pyspec') + ['configs', 'specs'], + packages=find_packages(where='tests/core/pyspec') + ['configs', 'presets', 'specs', 'presets', 'sync'], py_modules=["eth2spec"], cmdclass=commands, python_requires=">=3.9, <4", extras_require={ "test": ["pytest>=4.4", "pytest-cov", "pytest-xdist"], "lint": ["flake8==5.0.4", "mypy==0.981", "pylint==2.15.3"], - "generator": ["python-snappy==0.6.1", "filelock", "pathos==0.3.0"], + "generator": ["setuptools>=72.0.0", "pytest>4.4", "python-snappy==0.7.3", "filelock", "pathos==0.3.0"], "docs": ["mkdocs==1.4.2", "mkdocs-material==9.1.5", "mdx-truly-sane-lists==1.3", "mkdocs-awesome-pages-plugin==2.8.0"] }, install_requires=[ diff --git a/tests/generators/bls/requirements.txt b/tests/generators/bls/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/bls/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/epoch_processing/requirements.txt b/tests/generators/epoch_processing/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/epoch_processing/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/finality/requirements.txt b/tests/generators/finality/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/finality/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/fork_choice/requirements.txt b/tests/generators/fork_choice/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/fork_choice/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/forks/requirements.txt b/tests/generators/forks/requirements.txt deleted file mode 100644 index 735f863faa..0000000000 --- a/tests/generators/forks/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] \ No newline at end of file diff --git a/tests/generators/genesis/requirements.txt b/tests/generators/genesis/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/genesis/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/kzg_4844/requirements.txt b/tests/generators/kzg_4844/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/kzg_4844/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/kzg_7594/requirements.txt b/tests/generators/kzg_7594/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/kzg_7594/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/light_client/requirements.txt b/tests/generators/light_client/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/light_client/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/merkle_proof/requirements.txt b/tests/generators/merkle_proof/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/merkle_proof/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/networking/requirements.txt b/tests/generators/networking/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/networking/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/operations/requirements.txt b/tests/generators/operations/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/operations/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/random/requirements.txt b/tests/generators/random/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/random/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/rewards/requirements.txt b/tests/generators/rewards/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/rewards/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/sanity/requirements.txt b/tests/generators/sanity/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/sanity/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/shuffling/requirements.txt b/tests/generators/shuffling/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/shuffling/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/ssz_generic/requirements.txt b/tests/generators/ssz_generic/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/ssz_generic/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/ssz_static/requirements.txt b/tests/generators/ssz_static/requirements.txt deleted file mode 100644 index 1822486863..0000000000 --- a/tests/generators/ssz_static/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] diff --git a/tests/generators/sync/requirements.txt b/tests/generators/sync/requirements.txt deleted file mode 100644 index 735f863faa..0000000000 --- a/tests/generators/sync/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] \ No newline at end of file diff --git a/tests/generators/transition/requirements.txt b/tests/generators/transition/requirements.txt deleted file mode 100644 index 735f863faa..0000000000 --- a/tests/generators/transition/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest>=4.4 -../../../[generator] \ No newline at end of file From 36da776a399c597eb8585da8dcb845958b76942c Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Tue, 17 Sep 2024 15:20:59 -0500 Subject: [PATCH 61/66] Update url --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index eb7a5528af..a06a9ffdb4 100644 --- a/setup.py +++ b/setup.py @@ -524,7 +524,7 @@ def run(self): long_description=readme, long_description_content_type="text/markdown", author="ethereum", - url="https://github.com/ethereum/eth2.0-specs", + url="https://github.com/ethereum/consensus-specs", include_package_data=False, package_data={ 'configs': ['*.yaml'], From 666b63ac38f9239eade9ed45e47ef0c1fa6501e9 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 18 Sep 2024 13:35:49 +0100 Subject: [PATCH 62/66] Remove stale comment on latest_execution_payload_header in Electra (#3929) --- specs/electra/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 0659a3f8f3..dbf84d8de8 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -362,7 +362,7 @@ class BeaconState(Container): current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # Execution - latest_execution_payload_header: ExecutionPayloadHeader # [Modified in Electra:EIP6110:EIP7002] + latest_execution_payload_header: ExecutionPayloadHeader # Withdrawals next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex From cb99c5f3023a60511d37f21f57cdf22ff86cc8a4 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 18 Sep 2024 16:01:55 +0200 Subject: [PATCH 63/66] Ensure EL block hash is updated when beacon parent root is overridden (#3881) --- .../test/helpers/execution_payload.py | 28 ++++++++++++++++--- .../test_process_block_header.py | 6 ++++ .../test/phase0/fork_choice/test_on_block.py | 8 ++++++ .../test/phase0/sanity/test_blocks.py | 13 ++++++--- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index c2876133d4..4bad581eef 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -191,17 +191,19 @@ def get_consolidation_request_rlp_bytes(consolidation_request): return b"\x02" + encode(values, sedes) -def compute_el_block_hash(spec, payload, pre_state): +def compute_el_block_hash_with_parent_root(spec, payload, parent_beacon_block_root): + if payload == spec.ExecutionPayload(): + return spec.Hash32() + transactions_trie_root = compute_trie_root_from_indexed_data(payload.transactions) withdrawals_trie_root = None - parent_beacon_block_root = None if is_post_capella(spec): withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals] withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded) - if is_post_deneb(spec): - parent_beacon_block_root = pre_state.latest_block_header.hash_tree_root() + if not is_post_deneb(spec): + parent_beacon_block_root = None payload_header = get_execution_payload_header(spec, payload) @@ -214,6 +216,24 @@ def compute_el_block_hash(spec, payload, pre_state): ) +def compute_el_block_hash(spec, payload, pre_state): + parent_beacon_block_root = None + + if is_post_deneb(spec): + previous_block_header = pre_state.latest_block_header.copy() + if previous_block_header.state_root == spec.Root(): + previous_block_header.state_root = pre_state.hash_tree_root() + parent_beacon_block_root = previous_block_header.hash_tree_root() + + return compute_el_block_hash_with_parent_root( + spec, payload, parent_beacon_block_root) + + +def compute_el_block_hash_for_block(spec, block): + return compute_el_block_hash_with_parent_root( + spec, block.body.execution_payload, block.parent_root) + + def build_empty_post_eip7732_execution_payload_header(spec, state): if not is_post_eip7732(spec): return diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py index 5188d8f91b..a1f1e09a0b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py @@ -2,6 +2,8 @@ from eth2spec.test.context import spec_state_test, expect_assertion_error, with_all_phases from eth2spec.test.helpers.block import build_empty_block_for_next_slot +from eth2spec.test.helpers.execution_payload import compute_el_block_hash_for_block +from eth2spec.test.helpers.forks import is_post_bellatrix from eth2spec.test.helpers.state import next_slot @@ -65,6 +67,8 @@ def test_invalid_proposer_index(spec, state): def test_invalid_parent_root(spec, state): block = build_empty_block_for_next_slot(spec, state) block.parent_root = b'\12' * 32 # invalid prev root + if is_post_bellatrix(spec): + block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) yield from run_block_header_processing(spec, state, block, valid=False) @@ -81,6 +85,8 @@ def test_invalid_multiple_blocks_single_slot(spec, state): child_block = block.copy() child_block.parent_root = block.hash_tree_root() + if is_post_bellatrix(spec): + child_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, child_block) yield from run_block_header_processing(spec, state, child_block, prepare_state=False, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index cd41350496..3a3f60a438 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -18,6 +18,9 @@ transition_unsigned_block, sign_block, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash_for_block, +) from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -28,6 +31,9 @@ is_ready_to_justify, find_next_justifying_slot, ) +from eth2spec.test.helpers.forks import ( + is_post_bellatrix, +) from eth2spec.test.helpers.state import ( next_epoch, next_slots, @@ -152,6 +158,8 @@ def test_on_block_bad_parent_root(spec, state): block.state_root = state.hash_tree_root() block.parent_root = b'\x45' * 32 + if is_post_bellatrix(spec): + block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) signed_block = sign_block(spec, state, block) 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 41ba2e8b71..148cb939d5 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -20,7 +20,10 @@ from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing, check_proposer_slashing_effect from eth2spec.test.helpers.attestations import get_valid_attestation from eth2spec.test.helpers.deposits import prepare_state_and_deposit -from eth2spec.test.helpers.execution_payload import build_empty_execution_payload +from eth2spec.test.helpers.execution_payload import ( + build_empty_execution_payload, + compute_el_block_hash_for_block, +) from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits from eth2spec.test.helpers.multi_operations import ( run_slash_and_exit, @@ -158,7 +161,7 @@ def process_and_sign_block_without_header_validations(spec, state, block): if is_post_altair(spec): spec.process_sync_aggregate(state, block.body.sync_aggregate) - # Insert post-state rot + # Insert post-state root block.state_root = state.hash_tree_root() # Sign block @@ -197,11 +200,13 @@ def test_invalid_parent_from_same_slot(spec, state): signed_parent_block = state_transition_and_sign_block(spec, state, parent_block) child_block = parent_block.copy() - child_block.parent_root = state.latest_block_header.hash_tree_root() - if is_post_bellatrix(spec): child_block.body.execution_payload = build_empty_execution_payload(spec, state) + child_block.parent_root = state.latest_block_header.hash_tree_root() + if is_post_bellatrix(spec): + child_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, child_block) + # Show that normal path through transition fails failed_state = state.copy() expect_assertion_error( From e12b9abbf63997d43828629be79839e5b8c5f906 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Wed, 18 Sep 2024 17:03:26 +0300 Subject: [PATCH 64/66] EIP-7732: Refactor Beacon chain state transition function (#3898) --- specs/_features/eip7732/beacon-chain.md | 98 +++++++++++++------------ 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index 9df736750a..ec38d41674 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -50,10 +50,11 @@ - [Modified `process_operations`](#modified-process_operations) - [Payload Attestations](#payload-attestations) - [`process_payload_attestation`](#process_payload_attestation) - - [Modified `process_execution_payload`](#modified-process_execution_payload) - - [New `verify_execution_payload_envelope_signature`](#new-verify_execution_payload_envelope_signature) - [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete) - [Modified `validate_merge_block`](#modified-validate_merge_block) + - [Execution payload processing](#execution-payload-processing) + - [New `verify_execution_payload_envelope_signature`](#new-verify_execution_payload_envelope_signature) + - [New `process_execution_payload`](#new-process_execution_payload) @@ -429,7 +430,8 @@ The post-state corresponding to a pre-state `state` and a signed execution paylo def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) process_withdrawals(state) # [Modified in EIP-7732] - process_execution_payload_header(state, block) # [Modified in EIP-7732, removed process_execution_payload] + # Removed `process_execution_payload` in EIP-7732 + process_execution_payload_header(state, block) # [New in EIP-7732] process_randao(state, block.body) process_eth1_data(state, block.body) process_operations(state, block.body) # [Modified in EIP-7732] @@ -597,9 +599,51 @@ def process_payload_attestation(state: BeaconState, payload_attestation: Payload increase_balance(state, proposer_index, proposer_reward) ``` -#### Modified `process_execution_payload` +#### Modified `is_merge_transition_complete` + +`is_merge_transition_complete` is modified only for testing purposes to add the blob kzg commitments root for an empty list + +```python +def is_merge_transition_complete(state: BeaconState) -> bool: + header = ExecutionPayloadHeader() + kzgs = List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]() + header.blob_kzg_commitments_root = kzgs.hash_tree_root() + + return state.latest_execution_payload_header != header +``` -##### New `verify_execution_payload_envelope_signature` +#### Modified `validate_merge_block` +`validate_merge_block` is modified to use the new `signed_execution_payload_header` message in the Beacon Block Body + +```python +def validate_merge_block(block: BeaconBlock) -> None: + """ + Check the parent PoW block of execution payload is a valid terminal PoW block. + + Note: Unavailable PoW block(s) may later become available, + and a client software MAY delay a call to ``validate_merge_block`` + until the PoW block(s) become available. + """ + if TERMINAL_BLOCK_HASH != Hash32(): + # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. + assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH + assert block.body.signed_execution_payload_header.message.parent_block_hash == TERMINAL_BLOCK_HASH + return + + # Modified in EIP-7732 + pow_block = get_pow_block(block.body.signed_execution_payload_header.message.parent_block_hash) + # Check if `pow_block` is available + assert pow_block is not None + pow_parent = get_pow_block(pow_block.parent_hash) + # Check if `pow_parent` is available + assert pow_parent is not None + # Check if `pow_block` is a valid terminal PoW block + assert is_valid_terminal_pow_block(pow_block, pow_parent) +``` + +### Execution payload processing + +#### New `verify_execution_payload_envelope_signature` ```python def verify_execution_payload_envelope_signature( @@ -609,6 +653,8 @@ def verify_execution_payload_envelope_signature( return bls.Verify(builder.pubkey, signing_root, signed_envelope.signature) ``` +#### New `process_execution_payload` + *Note*: `process_execution_payload` is now an independent check in state transition. It is called when importing a signed execution payload proposed by the builder of the current slot. ```python @@ -679,45 +725,3 @@ def process_execution_payload(state: BeaconState, if verify: assert envelope.state_root == hash_tree_root(state) ``` - -#### Modified `is_merge_transition_complete` - -`is_merge_transition_complete` is modified only for testing purposes to add the blob kzg commitments root for an empty list - -```python -def is_merge_transition_complete(state: BeaconState) -> bool: - header = ExecutionPayloadHeader() - kzgs = List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]() - header.blob_kzg_commitments_root = kzgs.hash_tree_root() - - return state.latest_execution_payload_header != header -``` - -#### Modified `validate_merge_block` -`validate_merge_block` is modified to use the new `signed_execution_payload_header` message in the Beacon Block Body - -```python -def validate_merge_block(block: BeaconBlock) -> None: - """ - Check the parent PoW block of execution payload is a valid terminal PoW block. - - Note: Unavailable PoW block(s) may later become available, - and a client software MAY delay a call to ``validate_merge_block`` - until the PoW block(s) become available. - """ - if TERMINAL_BLOCK_HASH != Hash32(): - # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. - assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH - assert block.body.signed_execution_payload_header.message.parent_block_hash == TERMINAL_BLOCK_HASH - return - - # Modified in EIP-7732 - pow_block = get_pow_block(block.body.signed_execution_payload_header.message.parent_block_hash) - # Check if `pow_block` is available - assert pow_block is not None - pow_parent = get_pow_block(pow_block.parent_hash) - # Check if `pow_parent` is available - assert pow_parent is not None - # Check if `pow_block` is a valid terminal PoW block - assert is_valid_terminal_pow_block(pow_block, pow_parent) -``` From dbc746fb8b35018e2a1b646e43190c964e58fcc2 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Wed, 18 Sep 2024 09:08:07 -0500 Subject: [PATCH 65/66] bump to 1.5.0-alpha.6 (#3921) --- tests/core/pyspec/eth2spec/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/VERSION.txt b/tests/core/pyspec/eth2spec/VERSION.txt index 8c993fb5e5..f49b638a29 100644 --- a/tests/core/pyspec/eth2spec/VERSION.txt +++ b/tests/core/pyspec/eth2spec/VERSION.txt @@ -1 +1 @@ -1.5.0-alpha.5 +1.5.0-alpha.6 From d14fb522497b5e7322ccf59421fd4b285ec6bcd8 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:12:56 -0500 Subject: [PATCH 66/66] Fix yield statement in test_get_custody_columns (#3931) --- .../test/eip7594/networking/test_get_custody_columns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py index b41f19a6ca..3e1013734d 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/networking/test_get_custody_columns.py @@ -16,7 +16,7 @@ def _run_get_custody_columns(spec, rng, node_id=None, custody_subnet_count=None) result = spec.get_custody_columns(node_id, custody_subnet_count) yield 'node_id', 'meta', node_id - yield 'custody_subnet_count', 'meta', custody_subnet_count + yield 'custody_subnet_count', 'meta', int(custody_subnet_count) assert len(result) == len(set(result)) assert len(result) == (