From e1a4d8b60e245984bc157875794c912b4b60db37 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 1 Jul 2024 15:26:56 -0500 Subject: [PATCH 01/30] added some simple tests --- specs/electra/beacon-chain.md | 186 +++++++++--------- .../test_process_pending_deposits.py | 39 ++++ 2 files changed, 133 insertions(+), 92 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 83dd728a77..c903452159 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -8,97 +8,99 @@ -- [Introduction](#introduction) -- [Constants](#constants) - - [Misc](#misc) - - [Withdrawal prefixes](#withdrawal-prefixes) - - [Domains](#domains) -- [Preset](#preset) - - [Gwei values](#gwei-values) - - [Rewards and penalties](#rewards-and-penalties) - - [State list lengths](#state-list-lengths) - - [Max operations per block](#max-operations-per-block) - - [Execution](#execution) - - [Withdrawals processing](#withdrawals-processing) - - [Pending deposits processing](#pending-deposits-processing) -- [Configuration](#configuration) - - [Validator cycle](#validator-cycle) -- [Containers](#containers) - - [New containers](#new-containers) - - [`DepositRequest`](#depositrequest) - - [`PendingDeposit`](#pendingdeposit) - - [`PendingPartialWithdrawal`](#pendingpartialwithdrawal) - - [`WithdrawalRequest`](#withdrawalrequest) - - [`ConsolidationRequest`](#consolidationrequest) - - [`PendingConsolidation`](#pendingconsolidation) - - [Modified Containers](#modified-containers) - - [`AttesterSlashing`](#attesterslashing) - - [Extended Containers](#extended-containers) - - [`Attestation`](#attestation) - - [`IndexedAttestation`](#indexedattestation) - - [`BeaconBlockBody`](#beaconblockbody) - - [`ExecutionPayload`](#executionpayload) - - [`ExecutionPayloadHeader`](#executionpayloadheader) - - [`BeaconState`](#beaconstate) -- [Helper functions](#helper-functions) - - [Predicates](#predicates) - - [Updated `compute_proposer_index`](#updated-compute_proposer_index) - - [Updated `is_eligible_for_activation_queue`](#updated-is_eligible_for_activation_queue) - - [New `is_compounding_withdrawal_credential`](#new-is_compounding_withdrawal_credential) - - [New `has_compounding_withdrawal_credential`](#new-has_compounding_withdrawal_credential) - - [New `has_execution_withdrawal_credential`](#new-has_execution_withdrawal_credential) - - [Updated `is_fully_withdrawable_validator`](#updated-is_fully_withdrawable_validator) - - [Updated `is_partially_withdrawable_validator`](#updated-is_partially_withdrawable_validator) - - [Misc](#misc-1) - - [`get_committee_indices`](#get_committee_indices) - - [`get_validator_max_effective_balance`](#get_validator_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) - - [New `get_consolidation_churn_limit`](#new-get_consolidation_churn_limit) - - [New `get_active_balance`](#new-get_active_balance) - - [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw) - - [Modified `get_attesting_indices`](#modified-get_attesting_indices) - - [New `get_activation_churn_consumption`](#new-get_activation_churn_consumption) - - [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices) - - [Beacon state mutators](#beacon-state-mutators) - - [Updated `initiate_validator_exit`](#updated--initiate_validator_exit) - - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) - - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) - - [New `queue_entire_balance_and_reset_validator`](#new-queue_entire_balance_and_reset_validator) - - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) - - [New `compute_consolidation_epoch_and_update_churn`](#new-compute_consolidation_epoch_and_update_churn) - - [Updated `slash_validator`](#updated-slash_validator) -- [Beacon chain state transition function](#beacon-chain-state-transition-function) - - [Epoch processing](#epoch-processing) - - [Updated `process_epoch`](#updated-process_epoch) - - [Updated `process_registry_updates`](#updated--process_registry_updates) - - [New `apply_pending_deposit`](#new-apply_pending_deposit) - - [New `process_pending_deposits`](#new-process_pending_deposits) - - [New `process_pending_consolidations`](#new-process_pending_consolidations) - - [Updated `process_effective_balance_updates`](#updated-process_effective_balance_updates) - - [Block processing](#block-processing) - - [Withdrawals](#withdrawals) - - [Updated `get_expected_withdrawals`](#updated-get_expected_withdrawals) - - [Updated `process_withdrawals`](#updated-process_withdrawals) - - [Execution payload](#execution-payload) - - [Modified `process_execution_payload`](#modified-process_execution_payload) - - [Operations](#operations) - - [Modified `process_operations`](#modified-process_operations) - - [Attestations](#attestations) - - [Modified `process_attestation`](#modified-process_attestation) - - [Deposits](#deposits) - - [Updated `apply_deposit`](#updated--apply_deposit) - - [New `is_valid_deposit_signature`](#new-is_valid_deposit_signature) - - [Voluntary exits](#voluntary-exits) - - [Updated `process_voluntary_exit`](#updated-process_voluntary_exit) - - [Execution layer withdrawal requests](#execution-layer-withdrawal-requests) - - [New `process_withdrawal_request`](#new-process_withdrawal_request) - - [Deposit requests](#deposit-requests) - - [New `process_deposit_request`](#new-process_deposit_request) - - [Execution layer consolidation requests](#execution-layer-consolidation-requests) - - [New `process_consolidation_request`](#new-process_consolidation_request) -- [Testing](#testing) +- [Electra -- The Beacon Chain](#electra----the-beacon-chain) + - [Table of contents](#table-of-contents) + - [Introduction](#introduction) + - [Constants](#constants) + - [Misc](#misc) + - [Withdrawal prefixes](#withdrawal-prefixes) + - [Domains](#domains) + - [Preset](#preset) + - [Gwei values](#gwei-values) + - [Rewards and penalties](#rewards-and-penalties) + - [State list lengths](#state-list-lengths) + - [Max operations per block](#max-operations-per-block) + - [Execution](#execution) + - [Withdrawals processing](#withdrawals-processing) + - [Pending deposits processing](#pending-deposits-processing) + - [Configuration](#configuration) + - [Validator cycle](#validator-cycle) + - [Containers](#containers) + - [New containers](#new-containers) + - [`DepositRequest`](#depositrequest) + - [`PendingDeposit`](#pendingdeposit) + - [`PendingPartialWithdrawal`](#pendingpartialwithdrawal) + - [`WithdrawalRequest`](#withdrawalrequest) + - [`ConsolidationRequest`](#consolidationrequest) + - [`PendingConsolidation`](#pendingconsolidation) + - [Modified Containers](#modified-containers) + - [`AttesterSlashing`](#attesterslashing) + - [Extended Containers](#extended-containers) + - [`Attestation`](#attestation) + - [`IndexedAttestation`](#indexedattestation) + - [`BeaconBlockBody`](#beaconblockbody) + - [`ExecutionPayload`](#executionpayload) + - [`ExecutionPayloadHeader`](#executionpayloadheader) + - [`BeaconState`](#beaconstate) + - [Helper functions](#helper-functions) + - [Predicates](#predicates) + - [Updated `compute_proposer_index`](#updated-compute_proposer_index) + - [Updated `is_eligible_for_activation_queue`](#updated-is_eligible_for_activation_queue) + - [New `is_compounding_withdrawal_credential`](#new-is_compounding_withdrawal_credential) + - [New `has_compounding_withdrawal_credential`](#new-has_compounding_withdrawal_credential) + - [New `has_execution_withdrawal_credential`](#new-has_execution_withdrawal_credential) + - [Updated `is_fully_withdrawable_validator`](#updated-is_fully_withdrawable_validator) + - [Updated `is_partially_withdrawable_validator`](#updated-is_partially_withdrawable_validator) + - [Misc](#misc-1) + - [`get_committee_indices`](#get_committee_indices) + - [`get_validator_max_effective_balance`](#get_validator_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) + - [New `get_consolidation_churn_limit`](#new-get_consolidation_churn_limit) + - [New `get_active_balance`](#new-get_active_balance) + - [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw) + - [Modified `get_attesting_indices`](#modified-get_attesting_indices) + - [New `get_activation_churn_consumption`](#new-get_activation_churn_consumption) + - [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices) + - [Beacon state mutators](#beacon-state-mutators) + - [Updated `initiate_validator_exit`](#updated--initiate_validator_exit) + - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) + - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) + - [New `queue_entire_balance_and_reset_validator`](#new-queue_entire_balance_and_reset_validator) + - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) + - [New `compute_consolidation_epoch_and_update_churn`](#new-compute_consolidation_epoch_and_update_churn) + - [Updated `slash_validator`](#updated-slash_validator) + - [Beacon chain state transition function](#beacon-chain-state-transition-function) + - [Epoch processing](#epoch-processing) + - [Updated `process_epoch`](#updated-process_epoch) + - [Updated `process_registry_updates`](#updated--process_registry_updates) + - [New `apply_pending_deposit`](#new-apply_pending_deposit) + - [New `process_pending_deposits`](#new-process_pending_deposits) + - [New `process_pending_consolidations`](#new-process_pending_consolidations) + - [Updated `process_effective_balance_updates`](#updated-process_effective_balance_updates) + - [Block processing](#block-processing) + - [Withdrawals](#withdrawals) + - [Updated `get_expected_withdrawals`](#updated-get_expected_withdrawals) + - [Updated `process_withdrawals`](#updated-process_withdrawals) + - [Execution payload](#execution-payload) + - [Modified `process_execution_payload`](#modified-process_execution_payload) + - [Operations](#operations) + - [Modified `process_operations`](#modified-process_operations) + - [Attestations](#attestations) + - [Modified `process_attestation`](#modified-process_attestation) + - [Deposits](#deposits) + - [Updated `apply_deposit`](#updated--apply_deposit) + - [New `is_valid_deposit_signature`](#new-is_valid_deposit_signature) + - [Voluntary exits](#voluntary-exits) + - [Updated `process_voluntary_exit`](#updated-process_voluntary_exit) + - [Execution layer withdrawal requests](#execution-layer-withdrawal-requests) + - [New `process_withdrawal_request`](#new-process_withdrawal_request) + - [Deposit requests](#deposit-requests) + - [New `process_deposit_request`](#new-process_deposit_request) + - [Execution layer consolidation requests](#execution-layer-consolidation-requests) + - [New `process_consolidation_request`](#new-process_consolidation_request) + - [Testing](#testing) @@ -954,7 +956,7 @@ def process_pending_deposits(state: BeaconState) -> None: break # Check if number of processed deposits has not reached the limit, otherwise, stop processing. - if next_deposit_index > MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING: + if next_deposit_index > MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING-1: break # Check if deposit fits in the churn, otherwise, do no more deposit processing in this epoch. diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 1318f7f6f2..25352a05a0 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -279,3 +279,42 @@ def test_processing_deposit_of_withdrawable_validator_does_not_get_churned(spec, # First deposit does not consume any. assert state.deposit_balance_to_consume == spec.get_activation_exit_churn_limit(state) assert state.pending_deposits == [build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount)] + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_over_max(spec, state): + # pick an amount that adds to less than churn limit + amount = 100 + overmax = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + 1 + for i in range(overmax): + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[i].pubkey, + withdrawal_credentials=state.validators[i].withdrawal_credentials, + amount=amount, + slot=state.slot + )) + + assert len(state.pending_deposits) == overmax,"pending deposits is not over max" + yield from run_process_pending_deposits(spec, state) + # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING should remain in pending_deposits + assert len(state.pending_deposits) == 1 + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_deposit_not_finalized(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + slot=spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch) + # deposit is not finalized yet, so it is postponed + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=slot, + )) + # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + state.deposit_balance_to_consume = amount + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was postponed and not processed + assert len(state.pending_deposits) == 1 From 2af84d833292e314e79107eebf516ee6c008878f Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Tue, 2 Jul 2024 08:58:30 -0500 Subject: [PATCH 02/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py Co-authored-by: Mikhail Kalinin --- .../electra/epoch_processing/test_process_pending_deposits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 25352a05a0..d8f211fd4a 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -291,7 +291,7 @@ def test_pending_deposit_over_max(spec, state): pubkey=state.validators[i].pubkey, withdrawal_credentials=state.validators[i].withdrawal_credentials, amount=amount, - slot=state.slot + slot=spec.GENESIS_SLOT )) assert len(state.pending_deposits) == overmax,"pending deposits is not over max" From 750f7a1bd6878e5842e96aec4dd47920dec4908f Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 2 Jul 2024 12:02:40 -0500 Subject: [PATCH 03/30] adding new test --- .../test_process_pending_deposits.py | 103 +++++++++++------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 25352a05a0..33eeca52cc 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -11,6 +11,71 @@ def run_process_pending_deposits(spec, state): yield from run_epoch_processing_with(spec, state, 'process_pending_deposits') +@with_electra_and_later +@spec_state_test +def test_pending_deposit_over_max(spec, state): + # pick an amount that adds to less than churn limit + amount = 100 + overmax = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + 1 + for i in range(overmax): + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[i].pubkey, + withdrawal_credentials=state.validators[i].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + )) + assert len(state.pending_deposits) == overmax,"pending deposits is not over max" + yield from run_process_pending_deposits(spec, state) + # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING should remain in pending_deposits + assert len(state.pending_deposits) == 1 + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_eth1_bridge_not_applied(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + # deposit is not finalized yet, so it is postponed + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=1, + )) + # set deposit_requests_start_index to something high so that deposit is not processed + state.deposit_requests_start_index = 100000000000000000 + # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + state.deposit_balance_to_consume = amount + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was postponed and not processed + assert len(state.pending_deposits) == 1 + + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_deposit_not_finalized(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + # set slot to something not finalized + slot=spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch+1) + # deposit is not finalized yet, so it is postponed + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=slot, + )) + # set deposit_requests_start_index to something low so that we skip the bridge validation + state.deposit_requests_start_index = 0 + print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) + # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + state.deposit_balance_to_consume = amount + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was postponed and not processed + assert len(state.pending_deposits) == 1 + + @with_electra_and_later @spec_state_test @@ -280,41 +345,3 @@ def test_processing_deposit_of_withdrawable_validator_does_not_get_churned(spec, assert state.deposit_balance_to_consume == spec.get_activation_exit_churn_limit(state) assert state.pending_deposits == [build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount)] -@with_electra_and_later -@spec_state_test -def test_pending_deposit_over_max(spec, state): - # pick an amount that adds to less than churn limit - amount = 100 - overmax = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + 1 - for i in range(overmax): - state.pending_deposits.append(spec.PendingDeposit( - pubkey=state.validators[i].pubkey, - withdrawal_credentials=state.validators[i].withdrawal_credentials, - amount=amount, - slot=state.slot - )) - - assert len(state.pending_deposits) == overmax,"pending deposits is not over max" - yield from run_process_pending_deposits(spec, state) - # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING should remain in pending_deposits - assert len(state.pending_deposits) == 1 - -@with_electra_and_later -@spec_state_test -def test_pending_deposit_deposit_not_finalized(spec, state): - amount = spec.MIN_ACTIVATION_BALANCE - slot=spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch) - # deposit is not finalized yet, so it is postponed - state.pending_deposits.append(spec.PendingDeposit( - pubkey=state.validators[0].pubkey, - withdrawal_credentials=state.validators[0].withdrawal_credentials, - amount=amount, - slot=slot, - )) - # set deposit_balance_to_consume to some initial amount to see its removal later on in the test - state.deposit_balance_to_consume = amount - yield from run_process_pending_deposits(spec, state) - # deposit_balance_to_consume was reset to 0 - assert state.deposit_balance_to_consume == 0 - # deposit was postponed and not processed - assert len(state.pending_deposits) == 1 From b31fa63a4a07f68327a6eebc205ac2ea098b2738 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 2 Jul 2024 15:50:01 -0500 Subject: [PATCH 04/30] apply pending deposit tests --- .../test_apply_pending_deposit.py | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py new file mode 100644 index 0000000000..a521079bbf --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -0,0 +1,116 @@ +from eth2spec.test.context import ( + spec_state_test, + with_electra_and_later, +) +from eth2spec.test.helpers.keys import privkeys, pubkeys +from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data + +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_add_validator_to_registry(spec, state): + amount = 100 + + # choose a value public key that's not in the validator set outside of the mainnet preset of 256 + index = 2000 + withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + withdrawal_credentials, + signed=True) + deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials= withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + ) + old_validator_count = len(state.validators) + assert spec.apply_pending_deposit(state,deposit) == True + # validator count should increase by 1 + assert len(state.validators) == old_validator_count+1 + +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_not_withdrawable_epoch_while_exiting(spec, state): + amount = 100 + # validator exit epoch must be less than far future + state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 + state.validators[0].withdrawable_epoch = spec.FAR_FUTURE_EPOCH + + deposit = spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials= state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + ) + assert spec.apply_pending_deposit(state,deposit) == False + +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_withdrawable_epoch_while_exiting(spec, state): + amount = 100 + state.slot = spec.SLOTS_PER_EPOCH * 2 + # validator exit epoch must be less than far future + state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 + state.validators[0].withdrawable_epoch = 0 + + deposit = spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials= state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + ) + # reset the balance + state.balances[0] = 0 + assert spec.apply_pending_deposit(state,deposit) == True + assert state.balances[0] == amount + +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_withdrawable_epoch_while_exited(spec, state): + amount = 100 + state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH + # signature doesn't matter here as it's interpreted as a top-up + deposit = spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials= state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + ) + # reset the balance + state.balances[0] = 0 + assert spec.apply_pending_deposit(state,deposit) == True + assert state.balances[0] == amount + + +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_switch_to_compounding(spec, state): + amount = 100 + + # choose a value public key that's not in the validator set + index = 0 + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + state.validators[index].withdrawal_credentials = withdrawal_credentials + state.validators[index].exit_epoch = spec.FAR_FUTURE_EPOCH + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) + deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials= compounding_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + ) + state.balances[0] = 0 + assert spec.apply_pending_deposit(state,deposit) == True + # validator count should increase by 1 + assert state.balances[0] == amount + assert state.validators[0].withdrawal_credentials == compounding_credentials \ No newline at end of file From b2cd3ce9a7058d233f891af9f9e1e061e6c1cb72 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 2 Jul 2024 15:51:29 -0500 Subject: [PATCH 05/30] fixing comment --- .../electra/epoch_processing/test_apply_pending_deposit.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index a521079bbf..548116eba9 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -90,7 +90,7 @@ def test_apply_pending_deposit_withdrawable_epoch_while_exited(spec, state): def test_apply_pending_deposit_switch_to_compounding(spec, state): amount = 100 - # choose a value public key that's not in the validator set + # choose a value public key that's in the validator set index = 0 withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] @@ -113,4 +113,5 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): assert spec.apply_pending_deposit(state,deposit) == True # validator count should increase by 1 assert state.balances[0] == amount - assert state.validators[0].withdrawal_credentials == compounding_credentials \ No newline at end of file + assert state.validators[0].withdrawal_credentials == compounding_credentials + \ No newline at end of file From 03071df6e39ba764ac94dcc44a0fbe74e219bd1f Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 2 Jul 2024 22:10:15 -0500 Subject: [PATCH 06/30] preston's feedback --- .../test_apply_pending_deposit.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 548116eba9..ef40a030fd 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -47,6 +47,22 @@ def test_apply_pending_deposit_not_withdrawable_epoch_while_exiting(spec, state) ) assert spec.apply_pending_deposit(state,deposit) == False +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_not_withdrawable_epoch_at_current_epoch_while_exiting(spec, state): + amount = 100 + # validator exit epoch must be less than far future + state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 + state.validators[0].withdrawable_epoch = spec.get_current_epoch(state) + + deposit = spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials= state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + ) + assert spec.apply_pending_deposit(state,deposit) == False + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_withdrawable_epoch_while_exiting(spec, state): @@ -67,6 +83,7 @@ def test_apply_pending_deposit_withdrawable_epoch_while_exiting(spec, state): assert spec.apply_pending_deposit(state,deposit) == True assert state.balances[0] == amount + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_withdrawable_epoch_while_exited(spec, state): From 1a19d82bbcc74c59a55336a5a03a7e1f3bf48765 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 8 Jul 2024 23:15:03 -0500 Subject: [PATCH 07/30] updating tests based on mikhail changes --- .../test_apply_pending_deposit.py | 86 ++++++++----------- .../test_process_pending_deposits.py | 61 ++++++++++++- 2 files changed, 95 insertions(+), 52 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index ef40a030fd..e564284c58 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -33,45 +33,10 @@ def test_apply_pending_deposit_add_validator_to_registry(spec, state): @with_electra_and_later @spec_state_test -def test_apply_pending_deposit_not_withdrawable_epoch_while_exiting(spec, state): +def test_apply_pending_deposit_increases_balance(spec, state): amount = 100 - # validator exit epoch must be less than far future - state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 - state.validators[0].withdrawable_epoch = spec.FAR_FUTURE_EPOCH - - deposit = spec.PendingDeposit( - pubkey=state.validators[0].pubkey, - withdrawal_credentials= state.validators[0].withdrawal_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - ) - assert spec.apply_pending_deposit(state,deposit) == False - -@with_electra_and_later -@spec_state_test -def test_apply_pending_deposit_not_withdrawable_epoch_at_current_epoch_while_exiting(spec, state): - amount = 100 - # validator exit epoch must be less than far future - state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 - state.validators[0].withdrawable_epoch = spec.get_current_epoch(state) - - deposit = spec.PendingDeposit( - pubkey=state.validators[0].pubkey, - withdrawal_credentials= state.validators[0].withdrawal_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - ) - assert spec.apply_pending_deposit(state,deposit) == False - -@with_electra_and_later -@spec_state_test -def test_apply_pending_deposit_withdrawable_epoch_while_exiting(spec, state): - amount = 100 - state.slot = spec.SLOTS_PER_EPOCH * 2 - # validator exit epoch must be less than far future - state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - 1 - state.validators[0].withdrawable_epoch = 0 - + state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH + # signature doesn't matter here as it's interpreted as a top-up deposit = spec.PendingDeposit( pubkey=state.validators[0].pubkey, withdrawal_credentials= state.validators[0].withdrawal_credentials, @@ -80,31 +45,47 @@ def test_apply_pending_deposit_withdrawable_epoch_while_exiting(spec, state): ) # reset the balance state.balances[0] = 0 - assert spec.apply_pending_deposit(state,deposit) == True + # run test + spec.apply_pending_deposit(state,deposit) assert state.balances[0] == amount @with_electra_and_later @spec_state_test -def test_apply_pending_deposit_withdrawable_epoch_while_exited(spec, state): +def test_apply_pending_deposit_switch_to_compounding(spec, state): amount = 100 - state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH - # signature doesn't matter here as it's interpreted as a top-up + + # choose a value public key that's in the validator set + index = 0 + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + state.slot = spec.SLOTS_PER_EPOCH * 2 + state.validators[index].withdrawal_credentials = withdrawal_credentials + # set validator to be exited by current epoch + state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) deposit = spec.PendingDeposit( - pubkey=state.validators[0].pubkey, - withdrawal_credentials= state.validators[0].withdrawal_credentials, + pubkey=pubkeys[index], + withdrawal_credentials= compounding_credentials, amount=amount, slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, ) - # reset the balance state.balances[0] = 0 - assert spec.apply_pending_deposit(state,deposit) == True + # run test + spec.apply_pending_deposit(state,deposit) + # validator balance should increase assert state.balances[0] == amount - + assert state.validators[0].withdrawal_credentials == compounding_credentials @with_electra_and_later @spec_state_test -def test_apply_pending_deposit_switch_to_compounding(spec, state): +def test_apply_pending_deposit_switch_to_compounding_while_validator_not_exited(spec, state): amount = 100 # choose a value public key that's in the validator set @@ -112,6 +93,7 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] state.validators[index].withdrawal_credentials = withdrawal_credentials + # set validator to not be exited state.validators[index].exit_epoch = spec.FAR_FUTURE_EPOCH deposit_data = build_deposit_data(spec, pubkeys[index], @@ -127,8 +109,10 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): signature=deposit_data.signature, ) state.balances[0] = 0 - assert spec.apply_pending_deposit(state,deposit) == True - # validator count should increase by 1 + # run test + spec.apply_pending_deposit(state,deposit) + # validator balance should increase assert state.balances[0] == amount - assert state.validators[0].withdrawal_credentials == compounding_credentials + # make sure validator did not switch to compounding if not exited + assert state.validators[0].withdrawal_credentials == withdrawal_credentials \ No newline at end of file diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index ecd33d0bb3..6d27d23311 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -53,7 +53,7 @@ def test_pending_deposit_eth1_bridge_not_applied(spec, state): @with_electra_and_later @spec_state_test -def test_pending_deposit_deposit_not_finalized(spec, state): +def test_pending_deposit_not_finalized(spec, state): amount = spec.MIN_ACTIVATION_BALANCE # set slot to something not finalized slot=spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch+1) @@ -75,6 +75,65 @@ def test_pending_deposit_deposit_not_finalized(spec, state): # deposit was postponed and not processed assert len(state.pending_deposits) == 1 +@with_electra_and_later +@spec_state_test +def test_pending_deposit_validator_withdrawn(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(state.validators[0].pubkey)[1:] + state.slot = spec.SLOTS_PER_EPOCH * 2 + state.validators[0].withdrawal_credentials = withdrawal_credentials + # set validator to be withdrawable by current epoch + state.validators[0].withdrawable_epoch = spec.get_current_epoch(state) - 1 + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + )) + # set deposit_requests_start_index to something low so that we skip the bridge validation + state.deposit_requests_start_index = 0 + print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) + # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + state.deposit_balance_to_consume = amount + # reset balance for assert + state.balances[0] = 0 + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was processed + assert state.pending_deposits == [] + # balance increases because of withdraw + assert state.balances[0] == amount + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(state.validators[0].pubkey)[1:] + state.slot = spec.SLOTS_PER_EPOCH * 2 + state.validators[0].withdrawal_credentials = withdrawal_credentials + # set validator to be withdrawable by current epoch + state.validators[0].exit_epoch = spec.get_current_epoch(state) - 1 + state.validators[0].withdrawable_epoch = spec.FAR_FUTURE_EPOCH + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + )) + # set deposit_requests_start_index to something low so that we skip the bridge validation + state.deposit_requests_start_index = 0 + print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) + # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + state.deposit_balance_to_consume = amount + + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was postponed and not processed + assert len(state.pending_deposits) == 1 @with_electra_and_later From 1e9337ef194d26faf592fa2582349f729beba3c2 Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:42:10 -0500 Subject: [PATCH 08/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py Co-authored-by: Mikhail Kalinin --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index e564284c58..019db4f873 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -27,7 +27,7 @@ def test_apply_pending_deposit_add_validator_to_registry(spec, state): signature=deposit_data.signature, ) old_validator_count = len(state.validators) - assert spec.apply_pending_deposit(state,deposit) == True + spec.apply_pending_deposit(state,deposit) # validator count should increase by 1 assert len(state.validators) == old_validator_count+1 From 577b0289c07a0d733edf55dd301756b1cd491b2f Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:44:47 -0500 Subject: [PATCH 09/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py Co-authored-by: Mikhail Kalinin --- .../electra/epoch_processing/test_process_pending_deposits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 6d27d23311..e6319aa6ba 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -62,7 +62,7 @@ def test_pending_deposit_not_finalized(spec, state): pubkey=state.validators[0].pubkey, withdrawal_credentials=state.validators[0].withdrawal_credentials, amount=amount, - slot=slot, + slot=spec.get_current_epoch(state), )) # set deposit_requests_start_index to something low so that we skip the bridge validation state.deposit_requests_start_index = 0 From 8b191e679d017c9a616a0a680e1f4ccb298b595c Mon Sep 17 00:00:00 2001 From: james-prysm Date: Wed, 10 Jul 2024 11:41:18 -0500 Subject: [PATCH 10/30] fixing linting --- .../test_apply_pending_deposit.py | 101 ++++++----- .../test_process_pending_deposits.py | 170 +++++++++++------- 2 files changed, 167 insertions(+), 104 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 019db4f873..c5ed4aa3a7 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -5,114 +5,129 @@ from eth2spec.test.helpers.keys import privkeys, pubkeys from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_add_validator_to_registry(spec, state): - amount = 100 + amount = 100 - # choose a value public key that's not in the validator set outside of the mainnet preset of 256 + # select validator set outside of the mainnet preset of 256 index = 2000 - withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + withdrawal_credentials = ( + spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + ) deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - withdrawal_credentials, - signed=True) + pubkeys[index], + privkeys[index], + amount, + withdrawal_credentials, + signed=True) deposit = spec.PendingDeposit( pubkey=pubkeys[index], - withdrawal_credentials= withdrawal_credentials, + withdrawal_credentials=withdrawal_credentials, amount=amount, slot=spec.GENESIS_SLOT, signature=deposit_data.signature, - ) + ) old_validator_count = len(state.validators) - spec.apply_pending_deposit(state,deposit) + spec.apply_pending_deposit(state, deposit) # validator count should increase by 1 - assert len(state.validators) == old_validator_count+1 + assert len(state.validators) == old_validator_count + 1 + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_increases_balance(spec, state): - amount = 100 + amount = 100 state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH # signature doesn't matter here as it's interpreted as a top-up deposit = spec.PendingDeposit( pubkey=state.validators[0].pubkey, - withdrawal_credentials= state.validators[0].withdrawal_credentials, + withdrawal_credentials=state.validators[0].withdrawal_credentials, amount=amount, - slot=spec.GENESIS_SLOT, - ) - # reset the balance + slot=spec.GENESIS_SLOT + ) + # reset the balance state.balances[0] = 0 # run test - spec.apply_pending_deposit(state,deposit) + spec.apply_pending_deposit(state, deposit) assert state.balances[0] == amount @with_electra_and_later @spec_state_test def test_apply_pending_deposit_switch_to_compounding(spec, state): - amount = 100 + amount = 100 # choose a value public key that's in the validator set index = 0 - withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] - compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) state.slot = spec.SLOTS_PER_EPOCH * 2 state.validators[index].withdrawal_credentials = withdrawal_credentials # set validator to be exited by current epoch state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - compounding_credentials, - signed=True) + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) deposit = spec.PendingDeposit( pubkey=pubkeys[index], - withdrawal_credentials= compounding_credentials, + withdrawal_credentials=compounding_credentials, amount=amount, slot=spec.GENESIS_SLOT, signature=deposit_data.signature, - ) + ) state.balances[0] = 0 # run test - spec.apply_pending_deposit(state,deposit) + spec.apply_pending_deposit(state, deposit) # validator balance should increase assert state.balances[0] == amount - assert state.validators[0].withdrawal_credentials == compounding_credentials + current_credentials = state.validators[0].withdrawal_credentials + assert current_credentials == compounding_credentials + @with_electra_and_later @spec_state_test -def test_apply_pending_deposit_switch_to_compounding_while_validator_not_exited(spec, state): - amount = 100 +def test_apply_pending_deposit_switch_to_compounding_not_exited(spec, state): + amount = 100 # choose a value public key that's in the validator set index = 0 - withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] - compounding_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + ) + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] + ) state.validators[index].withdrawal_credentials = withdrawal_credentials # set validator to not be exited state.validators[index].exit_epoch = spec.FAR_FUTURE_EPOCH deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - compounding_credentials, - signed=True) + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) deposit = spec.PendingDeposit( pubkey=pubkeys[index], - withdrawal_credentials= compounding_credentials, + withdrawal_credentials=compounding_credentials, amount=amount, slot=spec.GENESIS_SLOT, signature=deposit_data.signature, - ) + ) state.balances[0] = 0 # run test - spec.apply_pending_deposit(state,deposit) + spec.apply_pending_deposit(state, deposit) # validator balance should increase assert state.balances[0] == amount # make sure validator did not switch to compounding if not exited assert state.validators[0].withdrawal_credentials == withdrawal_credentials - \ No newline at end of file diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index e6319aa6ba..207bf89400 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -9,26 +9,35 @@ def run_process_pending_deposits(spec, state): - yield from run_epoch_processing_with(spec, state, 'process_pending_deposits') + yield from run_epoch_processing_with( + spec, state, 'process_pending_deposits') + @with_electra_and_later @spec_state_test def test_pending_deposit_over_max(spec, state): # pick an amount that adds to less than churn limit - amount = 100 + amount = 100 overmax = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + 1 for i in range(overmax): - state.pending_deposits.append(spec.PendingDeposit( - pubkey=state.validators[i].pubkey, - withdrawal_credentials=state.validators[i].withdrawal_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - )) - assert len(state.pending_deposits) == overmax,"pending deposits is not over max" + state.pending_deposits.append( + spec.PendingDeposit( + pubkey=state.validators[i].pubkey, + withdrawal_credentials=( + state.validators[i].withdrawal_credentials + ), + amount=amount, + slot=spec.GENESIS_SLOT, + ) + ) + assert len(state.pending_deposits) == overmax, \ + "pending deposits is not overmax" + # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + # should remain in pending_deposits yield from run_process_pending_deposits(spec, state) - # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING should remain in pending_deposits assert len(state.pending_deposits) == 1 + @with_electra_and_later @spec_state_test def test_pending_deposit_eth1_bridge_not_applied(spec, state): @@ -40,9 +49,9 @@ def test_pending_deposit_eth1_bridge_not_applied(spec, state): amount=amount, slot=1, )) - # set deposit_requests_start_index to something high so that deposit is not processed + # set deposit_requests_start_index to something high state.deposit_requests_start_index = 100000000000000000 - # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + # set deposit_balance_to_consume to some initial amount state.deposit_balance_to_consume = amount yield from run_process_pending_deposits(spec, state) # deposit_balance_to_consume was reset to 0 @@ -56,18 +65,16 @@ def test_pending_deposit_eth1_bridge_not_applied(spec, state): def test_pending_deposit_not_finalized(spec, state): amount = spec.MIN_ACTIVATION_BALANCE # set slot to something not finalized - slot=spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch+1) # deposit is not finalized yet, so it is postponed state.pending_deposits.append(spec.PendingDeposit( pubkey=state.validators[0].pubkey, withdrawal_credentials=state.validators[0].withdrawal_credentials, amount=amount, - slot=spec.get_current_epoch(state), + slot=spec.get_current_epoch(state) + 1, )) - # set deposit_requests_start_index to something low so that we skip the bridge validation + # skip the bridge validation state.deposit_requests_start_index = 0 - print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) - # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + # set deposit_balance_to_consume to some initial amount state.deposit_balance_to_consume = amount yield from run_process_pending_deposits(spec, state) # deposit_balance_to_consume was reset to 0 @@ -75,12 +82,13 @@ def test_pending_deposit_not_finalized(spec, state): # deposit was postponed and not processed assert len(state.pending_deposits) == 1 + @with_electra_and_later @spec_state_test def test_pending_deposit_validator_withdrawn(spec, state): amount = spec.MIN_ACTIVATION_BALANCE - - withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(state.validators[0].pubkey)[1:] + hash = spec.hash(state.validators[0].pubkey)[1:] + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + hash state.slot = spec.SLOTS_PER_EPOCH * 2 state.validators[0].withdrawal_credentials = withdrawal_credentials # set validator to be withdrawable by current epoch @@ -91,10 +99,9 @@ def test_pending_deposit_validator_withdrawn(spec, state): amount=amount, slot=spec.GENESIS_SLOT, )) - # set deposit_requests_start_index to something low so that we skip the bridge validation + # skip the bridge validation state.deposit_requests_start_index = 0 - print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) - # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + # set deposit_balance_to_consume to some initial amount state.deposit_balance_to_consume = amount # reset balance for assert state.balances[0] = 0 @@ -106,12 +113,13 @@ def test_pending_deposit_validator_withdrawn(spec, state): # balance increases because of withdraw assert state.balances[0] == amount + @with_electra_and_later @spec_state_test def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): amount = spec.MIN_ACTIVATION_BALANCE - - withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(state.validators[0].pubkey)[1:] + hash = spec.hash(state.validators[0].pubkey)[1:] + withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + hash state.slot = spec.SLOTS_PER_EPOCH * 2 state.validators[0].withdrawal_credentials = withdrawal_credentials # set validator to be withdrawable by current epoch @@ -123,16 +131,15 @@ def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): amount=amount, slot=spec.GENESIS_SLOT, )) - # set deposit_requests_start_index to something low so that we skip the bridge validation + # skip the bridge validation state.deposit_requests_start_index = 0 - print("deposit indexes",state.eth1_deposit_index,state.deposit_requests_start_index) - # set deposit_balance_to_consume to some initial amount to see its removal later on in the test + # set deposit_balance_to_consume to some initial amount state.deposit_balance_to_consume = amount yield from run_process_pending_deposits(spec, state) # deposit_balance_to_consume was reset to 0 assert state.deposit_balance_to_consume == 0 - # deposit was postponed and not processed + # deposit was postponed and not processed assert len(state.pending_deposits) == 1 @@ -149,7 +156,7 @@ def test_pending_deposit_min_activation_balance(spec, state): yield from run_process_pending_deposits(spec, state) assert state.balances[index] == pre_balance + amount - # No leftover deposit balance to consume when there are no deposits left to process + # No leftover deposit balance to consume assert state.deposit_balance_to_consume == 0 assert state.pending_deposits == [] @@ -186,9 +193,8 @@ def test_pending_deposit_balance_above_churn(spec, state): # deposit was above churn, balance hasn't changed assert state.balances[index] == pre_balance # deposit balance to consume is the full churn limit - assert state.deposit_balance_to_consume == spec.get_activation_exit_churn_limit( - state - ) + wantedBalanceToConsume = spec.get_activation_exit_churn_limit(state) + assert state.deposit_balance_to_consume == wantedBalanceToConsume # deposit is still in the queue assert state.pending_deposits == [ build_pending_deposit_top_up(spec, state, index, amount) @@ -210,7 +216,7 @@ def test_pending_deposit_preexisting_churn(spec, state): # balance was deposited correctly assert state.balances[index] == pre_balance + amount - # No leftover deposit balance to consume when there are no deposits left to process + # No leftover deposit balance to consume assert state.deposit_balance_to_consume == 0 # queue emptied assert state.pending_deposits == [] @@ -221,10 +227,12 @@ def test_pending_deposit_preexisting_churn(spec, state): def test_multiple_pending_deposits_below_churn(spec, state): amount = 10**9 state.pending_deposits.append( - build_pending_deposit_top_up(spec, state, validator_index=0, amount=amount) + build_pending_deposit_top_up(spec, state, + validator_index=0, amount=amount) ) state.pending_deposits.append( - build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount) + build_pending_deposit_top_up(spec, state, + validator_index=1, amount=amount) ) pre_balances = state.balances.copy() @@ -232,7 +240,7 @@ def test_multiple_pending_deposits_below_churn(spec, state): for i in [0, 1]: assert state.balances[i] == pre_balances[i] + amount - # No leftover deposit balance to consume when there are no deposits left to process + # No leftover deposit balance to consume assert state.deposit_balance_to_consume == 0 assert state.pending_deposits == [] @@ -244,7 +252,8 @@ def test_multiple_pending_deposits_above_churn(spec, state): amount = (spec.get_activation_exit_churn_limit(state) // 3) + 1 for i in [0, 1, 2]: state.pending_deposits.append( - build_pending_deposit_top_up(spec, state, validator_index=i, amount=amount) + build_pending_deposit_top_up(spec, state, + validator_index=i, amount=amount) ) pre_balances = state.balances.copy() @@ -261,7 +270,8 @@ def test_multiple_pending_deposits_above_churn(spec, state): ) # third deposit is still in the queue assert state.pending_deposits == [ - build_pending_deposit_top_up(spec, state, validator_index=2, amount=amount) + build_pending_deposit_top_up(spec, state, + validator_index=2, amount=amount) ] @@ -270,7 +280,10 @@ def test_multiple_pending_deposits_above_churn(spec, state): def test_skipped_deposit_exiting_validator(spec, state): index = 0 amount = spec.MIN_ACTIVATION_BALANCE - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=index, amount=amount)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=index, amount=amount) + ) pre_pending_deposits = state.pending_deposits.copy() pre_balance = state.balances[index] # Initiate the validator's exit @@ -280,7 +293,7 @@ def test_skipped_deposit_exiting_validator(spec, state): # Deposit is skipped because validator is exiting assert state.balances[index] == pre_balance - # All deposits either processed or postponed, no leftover deposit balance to consume + # All deposits either processed or postponed assert state.deposit_balance_to_consume == 0 # The deposit is still in the queue assert state.pending_deposits == pre_pending_deposits @@ -292,7 +305,10 @@ def test_multiple_skipped_deposits_exiting_validators(spec, state): amount = spec.EFFECTIVE_BALANCE_INCREMENT for i in [0, 1, 2]: # Append pending deposit for validator i - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=i, amount=amount)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=i, amount=amount) + ) # Initiate the exit of validator i spec.initiate_validator_exit(state, i) @@ -314,7 +330,10 @@ def test_multiple_skipped_deposits_exiting_validators(spec, state): def test_multiple_pending_one_skipped(spec, state): amount = spec.EFFECTIVE_BALANCE_INCREMENT for i in [0, 1, 2]: - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=i, amount=amount)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=i, amount=amount) + ) pre_balances = state.balances.copy() # Initiate the second validator's exit spec.initiate_validator_exit(state, 1) @@ -325,10 +344,13 @@ def test_multiple_pending_one_skipped(spec, state): for i in [0, 2]: assert state.balances[i] == pre_balances[i] + amount assert state.balances[1] == pre_balances[1] - # All deposits either processed or postponed, no leftover deposit balance to consume + # All deposits either processed or postponed assert state.deposit_balance_to_consume == 0 # second deposit is still in the queue - assert state.pending_deposits == [build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount)] + assert state.pending_deposits == [ + build_pending_deposit_top_up(spec, state, + validator_index=1, amount=amount) + ] @with_electra_and_later @@ -338,8 +360,16 @@ def test_mixture_of_skipped_and_above_churn(spec, state): amount2 = spec.MAX_EFFECTIVE_BALANCE_ELECTRA # First two validators have small deposit, third validators a large one for i in [0, 1]: - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=i, amount=amount01)) - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=2, amount=amount2)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=i, + amount=amount01) + ) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=2, + amount=amount2) + ) pre_balances = state.balances.copy() # Initiate the second validator's exit spec.initiate_validator_exit(state, 1) @@ -352,11 +382,16 @@ def test_mixture_of_skipped_and_above_churn(spec, state): for i in [1, 2]: assert state.balances[i] == pre_balances[i] # First deposit consumes some deposit balance - # Deposit balance to consume is not reset because third deposit is not processed - assert state.deposit_balance_to_consume == spec.get_activation_exit_churn_limit(state) - amount01 - # second and third deposit still in the queue, but second is appended at the end - assert state.pending_deposits == [build_pending_deposit_top_up(spec, state, validator_index=2, amount=amount2), - build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount01)] + # Deposit is not processed + wanted_balance = spec.get_activation_exit_churn_limit(state) - amount01 + assert state.deposit_balance_to_consume == wanted_balance + # second and third deposit still in the queue + assert state.pending_deposits == [ + build_pending_deposit_top_up(spec, state, + validator_index=2, amount=amount2), + build_pending_deposit_top_up(spec, state, + validator_index=1, amount=amount01) + ] @with_electra_and_later @@ -364,42 +399,55 @@ def test_mixture_of_skipped_and_above_churn(spec, state): def test_processing_deposit_of_withdrawable_validator(spec, state): index = 0 amount = spec.MIN_ACTIVATION_BALANCE - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=index, amount=amount)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=index, + amount=amount) + ) pre_balance = state.balances[index] # Initiate the validator's exit spec.initiate_validator_exit(state, index) # Set epoch to withdrawable epoch + 1 to allow processing of the deposit - state.slot = spec.SLOTS_PER_EPOCH * (state.validators[index].withdrawable_epoch + 1) + withdrawable_epoch = state.validators[index].withdrawable_epoch + state.slot = spec.SLOTS_PER_EPOCH * (withdrawable_epoch + 1) yield from run_process_pending_deposits(spec, state) # Deposit is correctly processed assert state.balances[index] == pre_balance + amount - # No leftover deposit balance to consume when there are no deposits left to process + # No leftover deposit balance to consume assert state.deposit_balance_to_consume == 0 assert state.pending_deposits == [] @with_electra_and_later @spec_state_test -def test_processing_deposit_of_withdrawable_validator_does_not_get_churned(spec, state): +def test_processing_deposit_of_withdrawable_validator_not_churned(spec, state): amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA for i in [0, 1]: - state.pending_deposits.append(build_pending_deposit_top_up(spec, state, validator_index=i, amount=amount)) + state.pending_deposits.append( + build_pending_deposit_top_up(spec, state, + validator_index=i, amount=amount) + ) pre_balances = state.balances.copy() # Initiate the first validator's exit spec.initiate_validator_exit(state, 0) # Set epoch to withdrawable epoch + 1 to allow processing of the deposit - state.slot = spec.SLOTS_PER_EPOCH * (state.validators[0].withdrawable_epoch + 1) + withdraw_epoch = state.validators[0].withdrawable_epoch + state.slot = spec.SLOTS_PER_EPOCH * (withdraw_epoch + 1) # Don't use run_epoch_processing_with to avoid penalties being applied yield 'pre', state spec.process_pending_deposits(state) yield 'post', state - # First deposit is processed though above churn limit, because validator is withdrawable + # First deposit is processed though above churn limit assert state.balances[0] == pre_balances[0] + amount # Second deposit is not processed because above churn assert state.balances[1] == pre_balances[1] - # Second deposit is not processed, so there's leftover deposit balance to consume. + # Second deposit is not processed # First deposit does not consume any. - assert state.deposit_balance_to_consume == spec.get_activation_exit_churn_limit(state) - assert state.pending_deposits == [build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount)] + wantedLimit = spec.get_activation_exit_churn_limit(state) + assert state.deposit_balance_to_consume == wantedLimit + assert state.pending_deposits == [ + build_pending_deposit_top_up(spec, state, + validator_index=1, amount=amount) + ] From 2c8dd39429517ad568845f8ba80c494ae45f32af Mon Sep 17 00:00:00 2001 From: james-prysm Date: Thu, 11 Jul 2024 15:15:23 -0500 Subject: [PATCH 11/30] updating tests --- .../test_apply_pending_deposit.py | 17 +++--- .../test_process_pending_deposits.py | 53 +++++++++++++++---- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index c5ed4aa3a7..43ad420247 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -4,6 +4,7 @@ ) from eth2spec.test.helpers.keys import privkeys, pubkeys from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data +from eth2spec.test.helpers.state import next_epoch_via_block @with_electra_and_later @@ -69,7 +70,8 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] ) - state.slot = spec.SLOTS_PER_EPOCH * 2 + # advance the state + next_epoch_via_block(spec, state) state.validators[index].withdrawal_credentials = withdrawal_credentials # set validator to be exited by current epoch state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 @@ -86,11 +88,11 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): slot=spec.GENESIS_SLOT, signature=deposit_data.signature, ) - state.balances[0] = 0 + state.balances[index] = 0 # run test spec.apply_pending_deposit(state, deposit) # validator balance should increase - assert state.balances[0] == amount + assert state.balances[index] == amount current_credentials = state.validators[0].withdrawal_credentials assert current_credentials == compounding_credentials @@ -124,10 +126,13 @@ def test_apply_pending_deposit_switch_to_compounding_not_exited(spec, state): slot=spec.GENESIS_SLOT, signature=deposit_data.signature, ) - state.balances[0] = 0 + state.balances[index] = 0 # run test spec.apply_pending_deposit(state, deposit) # validator balance should increase - assert state.balances[0] == amount + assert state.balances[index] == amount # make sure validator did not switch to compounding if not exited - assert state.validators[0].withdrawal_credentials == withdrawal_credentials + current_credentials = state.validators[0].withdrawal_credentials + assert current_credentials == withdrawal_credentials + # postpone pending_deposit + assert len(state.pending_deposits) == 0 diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 207bf89400..53bfd8979c 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -6,6 +6,10 @@ from eth2spec.test.helpers.deposits import ( build_pending_deposit_top_up, ) +from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data +from eth2spec.test.helpers.state import next_epoch_via_block + +from eth2spec.test.helpers.keys import privkeys, pubkeys def run_process_pending_deposits(spec, state): @@ -87,17 +91,37 @@ def test_pending_deposit_not_finalized(spec, state): @spec_state_test def test_pending_deposit_validator_withdrawn(spec, state): amount = spec.MIN_ACTIVATION_BALANCE - hash = spec.hash(state.validators[0].pubkey)[1:] - withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + hash - state.slot = spec.SLOTS_PER_EPOCH * 2 - state.validators[0].withdrawal_credentials = withdrawal_credentials + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + # advance the state + next_epoch_via_block(spec, state) + state.validators[index].withdrawal_credentials = withdrawal_credentials + previous_epoch = spec.get_current_epoch(state) - 1 + # set validator to be exited by current epoch + state.validators[index].exit_epoch = previous_epoch # set validator to be withdrawable by current epoch - state.validators[0].withdrawable_epoch = spec.get_current_epoch(state) - 1 + state.validators[index].withdrawable_epoch = previous_epoch + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) + # set withdrawal credentials to compounding but should not switch since + # validator is already withdrawing state.pending_deposits.append(spec.PendingDeposit( - pubkey=state.validators[0].pubkey, - withdrawal_credentials=state.validators[0].withdrawal_credentials, + pubkey=pubkeys[index], + withdrawal_credentials=compounding_credentials, amount=amount, slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, )) # skip the bridge validation state.deposit_requests_start_index = 0 @@ -105,13 +129,19 @@ def test_pending_deposit_validator_withdrawn(spec, state): state.deposit_balance_to_consume = amount # reset balance for assert state.balances[0] = 0 + old_validator_count = len(state.validators) yield from run_process_pending_deposits(spec, state) + btc = state.deposit_balance_to_consume # deposit_balance_to_consume was reset to 0 - assert state.deposit_balance_to_consume == 0 + assert btc == 0 # deposit was processed assert state.pending_deposits == [] # balance increases because of withdraw assert state.balances[0] == amount + # churn limit was not reached + assert not amount > spec.get_activation_exit_churn_limit(state) + # validator count should stay the same + assert len(state.validators) == old_validator_count @with_electra_and_later @@ -120,7 +150,8 @@ def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): amount = spec.MIN_ACTIVATION_BALANCE hash = spec.hash(state.validators[0].pubkey)[1:] withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + hash - state.slot = spec.SLOTS_PER_EPOCH * 2 + # advance the state + next_epoch_via_block(spec, state) state.validators[0].withdrawal_credentials = withdrawal_credentials # set validator to be withdrawable by current epoch state.validators[0].exit_epoch = spec.get_current_epoch(state) - 1 @@ -445,8 +476,8 @@ def test_processing_deposit_of_withdrawable_validator_not_churned(spec, state): assert state.balances[1] == pre_balances[1] # Second deposit is not processed # First deposit does not consume any. - wantedLimit = spec.get_activation_exit_churn_limit(state) - assert state.deposit_balance_to_consume == wantedLimit + wanted_limit = spec.get_activation_exit_churn_limit(state) + assert state.deposit_balance_to_consume == wanted_limit assert state.pending_deposits == [ build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount) From 320a692bec59ba707d2b9bbd442f582c9ca06b88 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 12 Jul 2024 14:11:52 -0500 Subject: [PATCH 12/30] adding test for chrun --- .../test_process_pending_deposits.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 53bfd8979c..c2c463dab6 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -209,6 +209,47 @@ def test_pending_deposit_balance_equal_churn(spec, state): assert state.pending_deposits == [] +@with_electra_and_later +@spec_state_test +def test_pending_deposit_balance_equal_churn_with_compounding(spec, state): + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + amount = spec.get_activation_exit_churn_limit(state) + state.validators[index].withdrawal_credentials = withdrawal_credentials + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) + # set withdrawal credentials to compounding but should not switch since + # validator is already withdrawing + state.pending_deposits.append(spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=compounding_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + )) + pre_balance = state.balances[index] + + yield from run_process_pending_deposits(spec, state) + + assert state.balances[index] == pre_balance + amount + assert state.deposit_balance_to_consume == 0 + assert state.pending_deposits == [] + current_credentials = state.validators[0].withdrawal_credentials + # validator is not exited, so it should not switch to compounding + assert current_credentials == withdrawal_credentials + + @with_electra_and_later @spec_state_test def test_pending_deposit_balance_above_churn(spec, state): From 48b9928194099be110e18bf8392cb2f8ed1a6b10 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 12 Jul 2024 14:30:49 -0500 Subject: [PATCH 13/30] adding out of validator range test --- .../test_process_pending_deposits.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index c2c463dab6..f4f6b70fb9 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -15,6 +15,8 @@ def run_process_pending_deposits(spec, state): yield from run_epoch_processing_with( spec, state, 'process_pending_deposits') + + @with_electra_and_later @@ -174,6 +176,37 @@ def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): assert len(state.pending_deposits) == 1 +@with_electra_and_later +@spec_state_test +def test_pending_deposit_not_in_validator_set(spec, state): + index = 2000 + amount = spec.MIN_ACTIVATION_BALANCE + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + withdrawal_credentials, + signed=True) + state.pending_deposits.append(spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=withdrawal_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + )) + value_error = False + try: + yield from run_process_pending_deposits(spec, state) + except ValueError: + value_error = True + + assert value_error + + @with_electra_and_later @spec_state_test def test_pending_deposit_min_activation_balance(spec, state): From bf03d78a3aa6aa25d75884d0f38e835413a65ed2 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 12 Jul 2024 14:32:06 -0500 Subject: [PATCH 14/30] fixing linting --- .../electra/epoch_processing/test_process_pending_deposits.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index f4f6b70fb9..2ec57db975 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -15,8 +15,6 @@ def run_process_pending_deposits(spec, state): yield from run_epoch_processing_with( spec, state, 'process_pending_deposits') - - @with_electra_and_later From ea33eac282f2d4e1eaffe00188a2bd8c65d2e8e8 Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:57:57 -0500 Subject: [PATCH 15/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py Co-authored-by: Mikhail Kalinin --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 43ad420247..bcf1af84f3 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -10,7 +10,7 @@ @with_electra_and_later @spec_state_test def test_apply_pending_deposit_add_validator_to_registry(spec, state): - amount = 100 + amount = spec.MIN_ACTIVATION_BALANCE # select validator set outside of the mainnet preset of 256 index = 2000 From 1feb1fbc0fc40f1f0248373ea24700f3a074ff4a Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:58:25 -0500 Subject: [PATCH 16/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py Co-authored-by: Mikhail Kalinin --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index bcf1af84f3..7f4ca30ecc 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -13,7 +13,7 @@ def test_apply_pending_deposit_add_validator_to_registry(spec, state): amount = spec.MIN_ACTIVATION_BALANCE # select validator set outside of the mainnet preset of 256 - index = 2000 + index = len(state.validators) withdrawal_credentials = ( spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] ) From d62559fe90a80363ac3b0b88ee1fbb8f469dbd35 Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:59:12 -0500 Subject: [PATCH 17/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py Co-authored-by: Mikhail Kalinin --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 7f4ca30ecc..5dc1b3b1d8 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -40,7 +40,6 @@ def test_apply_pending_deposit_add_validator_to_registry(spec, state): @spec_state_test def test_apply_pending_deposit_increases_balance(spec, state): amount = 100 - state.validators[0].exit_epoch = spec.FAR_FUTURE_EPOCH # signature doesn't matter here as it's interpreted as a top-up deposit = spec.PendingDeposit( pubkey=state.validators[0].pubkey, From 6903babf7d1ed90bedfcf0f33c938519844753b4 Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:01:58 -0500 Subject: [PATCH 18/30] Update tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py Co-authored-by: Mikhail Kalinin --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 5dc1b3b1d8..d7ad5dd6d3 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -110,8 +110,6 @@ def test_apply_pending_deposit_switch_to_compounding_not_exited(spec, state): spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] ) state.validators[index].withdrawal_credentials = withdrawal_credentials - # set validator to not be exited - state.validators[index].exit_epoch = spec.FAR_FUTURE_EPOCH deposit_data = build_deposit_data(spec, pubkeys[index], privkeys[index], From 4a4cdfc1e7fb6a213e9e65d9679ac5a55974665e Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 26 Jul 2024 11:35:59 -0500 Subject: [PATCH 19/30] revert beacon-chain.md changes --- specs/electra/beacon-chain.md | 182 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 92 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 5fdefeb93a..bce8ed2a39 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -8,98 +8,96 @@ -- [Electra -- The Beacon Chain](#electra----the-beacon-chain) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Constants](#constants) - - [Misc](#misc) - - [Withdrawal prefixes](#withdrawal-prefixes) - - [Domains](#domains) - - [Preset](#preset) - - [Gwei values](#gwei-values) - - [Rewards and penalties](#rewards-and-penalties) - - [State list lengths](#state-list-lengths) - - [Max operations per block](#max-operations-per-block) - - [Execution](#execution) - - [Withdrawals processing](#withdrawals-processing) - - [Pending deposits processing](#pending-deposits-processing) - - [Configuration](#configuration) - - [Validator cycle](#validator-cycle) - - [Containers](#containers) - - [New containers](#new-containers) - - [`DepositRequest`](#depositrequest) - - [`PendingDeposit`](#pendingdeposit) - - [`PendingPartialWithdrawal`](#pendingpartialwithdrawal) - - [`WithdrawalRequest`](#withdrawalrequest) - - [`ConsolidationRequest`](#consolidationrequest) - - [`PendingConsolidation`](#pendingconsolidation) - - [Modified Containers](#modified-containers) - - [`AttesterSlashing`](#attesterslashing) - - [Extended Containers](#extended-containers) - - [`Attestation`](#attestation) - - [`IndexedAttestation`](#indexedattestation) - - [`BeaconBlockBody`](#beaconblockbody) - - [`ExecutionPayload`](#executionpayload) - - [`ExecutionPayloadHeader`](#executionpayloadheader) - - [`BeaconState`](#beaconstate) - - [Helper functions](#helper-functions) - - [Predicates](#predicates) - - [Modified `compute_proposer_index`](#modified-compute_proposer_index) - - [Modified `is_eligible_for_activation_queue`](#modified-is_eligible_for_activation_queue) - - [New `is_compounding_withdrawal_credential`](#new-is_compounding_withdrawal_credential) - - [New `has_compounding_withdrawal_credential`](#new-has_compounding_withdrawal_credential) - - [New `has_execution_withdrawal_credential`](#new-has_execution_withdrawal_credential) - - [Modified `is_fully_withdrawable_validator`](#modified-is_fully_withdrawable_validator) - - [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) - - [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) - - [New `get_consolidation_churn_limit`](#new-get_consolidation_churn_limit) - - [New `get_active_balance`](#new-get_active_balance) - - [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw) - - [Modified `get_attesting_indices`](#modified-get_attesting_indices) - - [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices) - - [Beacon state mutators](#beacon-state-mutators) - - [Modified `initiate_validator_exit`](#modified-initiate_validator_exit) - - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) - - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) - - [New `queue_entire_balance_and_reset_validator`](#new-queue_entire_balance_and_reset_validator) - - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) - - [New `compute_consolidation_epoch_and_update_churn`](#new-compute_consolidation_epoch_and_update_churn) - - [Modified `slash_validator`](#modified-slash_validator) - - [Beacon chain state transition function](#beacon-chain-state-transition-function) - - [Epoch processing](#epoch-processing) - - [Modified `process_epoch`](#modified-process_epoch) - - [Modified `process_registry_updates`](#modified-process_registry_updates) - - [New `apply_pending_deposit`](#new-apply_pending_deposit) - - [New `process_pending_deposits`](#new-process_pending_deposits) - - [New `process_pending_consolidations`](#new-process_pending_consolidations) - - [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates) - - [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) - - [Modified `process_attestation`](#modified-process_attestation) - - [Deposits](#deposits) - - [Modified `apply_deposit`](#modified-apply_deposit) - - [New `is_valid_deposit_signature`](#new-is_valid_deposit_signature) - - [Voluntary exits](#voluntary-exits) - - [Modified `process_voluntary_exit`](#modified-process_voluntary_exit) - - [Execution layer withdrawal requests](#execution-layer-withdrawal-requests) - - [New `process_withdrawal_request`](#new-process_withdrawal_request) - - [Deposit requests](#deposit-requests) - - [New `process_deposit_request`](#new-process_deposit_request) - - [Execution layer consolidation requests](#execution-layer-consolidation-requests) - - [New `process_consolidation_request`](#new-process_consolidation_request) - - [Testing](#testing) +- [Introduction](#introduction) +- [Constants](#constants) + - [Misc](#misc) + - [Withdrawal prefixes](#withdrawal-prefixes) + - [Domains](#domains) +- [Preset](#preset) + - [Gwei values](#gwei-values) + - [Rewards and penalties](#rewards-and-penalties) + - [State list lengths](#state-list-lengths) + - [Max operations per block](#max-operations-per-block) + - [Execution](#execution) + - [Withdrawals processing](#withdrawals-processing) + - [Pending deposits processing](#pending-deposits-processing) +- [Configuration](#configuration) + - [Validator cycle](#validator-cycle) +- [Containers](#containers) + - [New containers](#new-containers) + - [`DepositRequest`](#depositrequest) + - [`PendingDeposit`](#pendingdeposit) + - [`PendingPartialWithdrawal`](#pendingpartialwithdrawal) + - [`WithdrawalRequest`](#withdrawalrequest) + - [`ConsolidationRequest`](#consolidationrequest) + - [`PendingConsolidation`](#pendingconsolidation) + - [Modified Containers](#modified-containers) + - [`AttesterSlashing`](#attesterslashing) + - [Extended Containers](#extended-containers) + - [`Attestation`](#attestation) + - [`IndexedAttestation`](#indexedattestation) + - [`BeaconBlockBody`](#beaconblockbody) + - [`ExecutionPayload`](#executionpayload) + - [`ExecutionPayloadHeader`](#executionpayloadheader) + - [`BeaconState`](#beaconstate) +- [Helper functions](#helper-functions) + - [Predicates](#predicates) + - [Modified `compute_proposer_index`](#modified-compute_proposer_index) + - [Modified `is_eligible_for_activation_queue`](#modified-is_eligible_for_activation_queue) + - [New `is_compounding_withdrawal_credential`](#new-is_compounding_withdrawal_credential) + - [New `has_compounding_withdrawal_credential`](#new-has_compounding_withdrawal_credential) + - [New `has_execution_withdrawal_credential`](#new-has_execution_withdrawal_credential) + - [Modified `is_fully_withdrawable_validator`](#modified-is_fully_withdrawable_validator) + - [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) + - [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) + - [New `get_consolidation_churn_limit`](#new-get_consolidation_churn_limit) + - [New `get_active_balance`](#new-get_active_balance) + - [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw) + - [Modified `get_attesting_indices`](#modified-get_attesting_indices) + - [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices) + - [Beacon state mutators](#beacon-state-mutators) + - [Modified `initiate_validator_exit`](#modified-initiate_validator_exit) + - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) + - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) + - [New `queue_entire_balance_and_reset_validator`](#new-queue_entire_balance_and_reset_validator) + - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) + - [New `compute_consolidation_epoch_and_update_churn`](#new-compute_consolidation_epoch_and_update_churn) + - [Modified `slash_validator`](#modified-slash_validator) +- [Beacon chain state transition function](#beacon-chain-state-transition-function) + - [Epoch processing](#epoch-processing) + - [Modified `process_epoch`](#modified-process_epoch) + - [Modified `process_registry_updates`](#modified-process_registry_updates) + - [New `apply_pending_deposit`](#new-apply_pending_deposit) + - [New `process_pending_deposits`](#new-process_pending_deposits) + - [New `process_pending_consolidations`](#new-process_pending_consolidations) + - [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates) + - [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) + - [Modified `process_attestation`](#modified-process_attestation) + - [Deposits](#deposits) + - [Modified `apply_deposit`](#modified-apply_deposit) + - [New `is_valid_deposit_signature`](#new-is_valid_deposit_signature) + - [Voluntary exits](#voluntary-exits) + - [Modified `process_voluntary_exit`](#modified-process_voluntary_exit) + - [Execution layer withdrawal requests](#execution-layer-withdrawal-requests) + - [New `process_withdrawal_request`](#new-process_withdrawal_request) + - [Deposit requests](#deposit-requests) + - [New `process_deposit_request`](#new-process_deposit_request) + - [Execution layer consolidation requests](#execution-layer-consolidation-requests) + - [New `process_consolidation_request`](#new-process_consolidation_request) +- [Testing](#testing) From e80c39b1edb4ada4a61f07aef42c0a117746e534 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 29 Jul 2024 09:32:18 -0500 Subject: [PATCH 20/30] mikhail's feedback --- .../test/electra/epoch_processing/test_apply_pending_deposit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index d7ad5dd6d3..33dc775a51 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -87,7 +87,6 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): slot=spec.GENESIS_SLOT, signature=deposit_data.signature, ) - state.balances[index] = 0 # run test spec.apply_pending_deposit(state, deposit) # validator balance should increase From 6a7bfe9b341baa5db9e8426430d16667a71bb467 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 29 Jul 2024 10:49:57 -0500 Subject: [PATCH 21/30] removed wrong balance --- .../electra/epoch_processing/test_apply_pending_deposit.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 33dc775a51..a84153b514 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -47,8 +47,6 @@ def test_apply_pending_deposit_increases_balance(spec, state): amount=amount, slot=spec.GENESIS_SLOT ) - # reset the balance - state.balances[0] = 0 # run test spec.apply_pending_deposit(state, deposit) assert state.balances[0] == amount @@ -87,6 +85,7 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): slot=spec.GENESIS_SLOT, signature=deposit_data.signature, ) + state.balances[index] = 0 # run test spec.apply_pending_deposit(state, deposit) # validator balance should increase From 824e37467928ff91c67f3544d810387cac673204 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 30 Jul 2024 10:00:47 -0500 Subject: [PATCH 22/30] applying feedback fir add validator test --- .../epoch_processing/test_apply_pending_deposit.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index a84153b514..4de4f624e2 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -1,3 +1,4 @@ +from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with from eth2spec.test.context import ( spec_state_test, with_electra_and_later, @@ -7,6 +8,11 @@ from eth2spec.test.helpers.state import next_epoch_via_block +def run_process_pending_deposits(spec, state): + yield from run_epoch_processing_with( + spec, state, 'process_pending_deposits') + + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_add_validator_to_registry(spec, state): @@ -31,7 +37,8 @@ def test_apply_pending_deposit_add_validator_to_registry(spec, state): signature=deposit_data.signature, ) old_validator_count = len(state.validators) - spec.apply_pending_deposit(state, deposit) + state.pending_deposits.append(deposit) + yield from run_process_pending_deposits(spec, state) # validator count should increase by 1 assert len(state.validators) == old_validator_count + 1 From 0a51fe032d9d4a0b5fef6b67bb46234edba56579 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 2 Aug 2024 16:46:16 -0500 Subject: [PATCH 23/30] updating tests --- .../test_process_pending_deposits.py | 165 ++++++++++++------ .../pyspec/eth2spec/test/helpers/deposits.py | 36 ++++ 2 files changed, 151 insertions(+), 50 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 2ec57db975..78fe4463b8 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -4,12 +4,12 @@ with_electra_and_later, ) from eth2spec.test.helpers.deposits import ( + build_pending_deposit, build_pending_deposit_top_up, ) -from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data from eth2spec.test.helpers.state import next_epoch_via_block -from eth2spec.test.helpers.keys import privkeys, pubkeys +from eth2spec.test.helpers.keys import pubkeys def run_process_pending_deposits(spec, state): @@ -17,6 +17,59 @@ def run_process_pending_deposits(spec, state): spec, state, 'process_pending_deposits') +@with_electra_and_later +@spec_state_test +def test_pending_deposit_under_max(spec, state): + # pick an amount that adds to less than churn limit + amount = 100 + undermax = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING - 1 + for i in range(undermax): + print(i) + state.pending_deposits.append( + spec.PendingDeposit( + pubkey=state.validators[i].pubkey, + withdrawal_credentials=( + state.validators[i].withdrawal_credentials + ), + amount=amount, + slot=spec.GENESIS_SLOT, + ) + ) + assert len(state.pending_deposits) == undermax, \ + "pending deposits is not undermax" + yield from run_process_pending_deposits(spec, state) + assert len(state.pending_deposits) == 0 + assert state.balances[0] == amount + spec.MIN_ACTIVATION_BALANCE + assert state.balances[undermax - 1] == amount + spec.MIN_ACTIVATION_BALANCE + assert state.balances[undermax] == spec.MIN_ACTIVATION_BALANCE + + +@with_electra_and_later +@spec_state_test +def test_pending_deposit_max(spec, state): + # pick an amount that adds to less than churn limit + amount = 100 + max = spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING + for i in range(max): + state.pending_deposits.append( + spec.PendingDeposit( + pubkey=state.validators[i].pubkey, + withdrawal_credentials=( + state.validators[i].withdrawal_credentials + ), + amount=amount, + slot=spec.GENESIS_SLOT, + ) + ) + assert len(state.pending_deposits) == max, \ + "pending deposits is not max" + yield from run_process_pending_deposits(spec, state) + assert len(state.pending_deposits) == 0 + assert state.balances[0] == amount + spec.MIN_ACTIVATION_BALANCE + assert state.balances[max - 1] == amount + spec.MIN_ACTIVATION_BALANCE + assert state.balances[max] == spec.MIN_ACTIVATION_BALANCE + + @with_electra_and_later @spec_state_test def test_pending_deposit_over_max(spec, state): @@ -36,10 +89,47 @@ def test_pending_deposit_over_max(spec, state): ) assert len(state.pending_deposits) == overmax, \ "pending deposits is not overmax" - # the remaining deposit over MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING - # should remain in pending_deposits yield from run_process_pending_deposits(spec, state) assert len(state.pending_deposits) == 1 + assert state.balances[overmax - 1] == spec.MIN_ACTIVATION_BALANCE + amount + + +@with_electra_and_later +@spec_state_test +def test_new_deposit_eth1_withdrawal_credentials(spec, state): + state.validators[0].withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + b'\x00' * 11 # specified 0s + + b'\x59' * 20 # a 20-byte eth1 address + ) + amount = spec.MAX_EFFECTIVE_BALANCE + + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=1, + )) + + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): + state.validators[0].withdrawal_credentials = ( + b'\xFF' # Non specified withdrawal credentials version + + b'\x02' * 31 # Garabage bytes + ) + amount = spec.MAX_EFFECTIVE_BALANCE + state.pending_deposits.append(spec.PendingDeposit( + pubkey=state.validators[0].pubkey, + withdrawal_credentials=state.validators[0].withdrawal_credentials, + amount=amount, + slot=1, + )) + + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -108,21 +198,13 @@ def test_pending_deposit_validator_withdrawn(spec, state): state.validators[index].exit_epoch = previous_epoch # set validator to be withdrawable by current epoch state.validators[index].withdrawable_epoch = previous_epoch - deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - compounding_credentials, - signed=True) # set withdrawal credentials to compounding but should not switch since # validator is already withdrawing - state.pending_deposits.append(spec.PendingDeposit( - pubkey=pubkeys[index], - withdrawal_credentials=compounding_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - signature=deposit_data.signature, - )) + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=compounding_credentials, + signed=True) + state.pending_deposits.append(pd) # skip the bridge validation state.deposit_requests_start_index = 0 # set deposit_balance_to_consume to some initial amount @@ -179,30 +261,20 @@ def test_pending_deposit_validator_exiting_but_not_withdrawn(spec, state): def test_pending_deposit_not_in_validator_set(spec, state): index = 2000 amount = spec.MIN_ACTIVATION_BALANCE - withdrawal_credentials = ( + wc = ( spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:] ) - deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - withdrawal_credentials, - signed=True) - state.pending_deposits.append(spec.PendingDeposit( - pubkey=pubkeys[index], - withdrawal_credentials=withdrawal_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - signature=deposit_data.signature, - )) - value_error = False - try: - yield from run_process_pending_deposits(spec, state) - except ValueError: - value_error = True + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + signed=True) - assert value_error + state.pending_deposits.append(pd) + old_length = len(state.validators) + yield from run_process_pending_deposits(spec, state) + # new validator activated + assert len(state.validators) == old_length + 1 @with_electra_and_later @@ -254,21 +326,14 @@ def test_pending_deposit_balance_equal_churn_with_compounding(spec, state): ) amount = spec.get_activation_exit_churn_limit(state) state.validators[index].withdrawal_credentials = withdrawal_credentials - deposit_data = build_deposit_data(spec, - pubkeys[index], - privkeys[index], - amount, - compounding_credentials, - signed=True) + # set withdrawal credentials to compounding but should not switch since # validator is already withdrawing - state.pending_deposits.append(spec.PendingDeposit( - pubkey=pubkeys[index], - withdrawal_credentials=compounding_credentials, - amount=amount, - slot=spec.GENESIS_SLOT, - signature=deposit_data.signature, - )) + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=compounding_credentials, + signed=True) + state.pending_deposits.append(pd) pre_balance = state.balances[index] yield from run_process_pending_deposits(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index ae50f6b38a..fc6e6b5d27 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -235,6 +235,42 @@ def build_pending_deposit_top_up(spec, state, validator_index, amount, slot=None slot=slot, ) + +def build_pending_deposit(spec, validator_index, amount, + index=None, + pubkey=None, + privkey=None, + withdrawal_credentials=None, + slot=None, + signed=False): + if index is None: + index = validator_index + + if pubkey is None: + pubkey = pubkeys[validator_index] + + if privkey is None: + privkey = privkeys[validator_index] + + if slot is None: + slot = spec.GENESIS_SLOT + + pending_deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=withdrawal_credentials, + amount=amount, + slot=slot, + ) + if signed: + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + withdrawal_credentials, + signed=True) + pending_deposit.signature = deposit_data.signature + return pending_deposit + # # Run processing # From 1afa51420edcbb6698ab59b12a208bb988f9a228 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Fri, 2 Aug 2024 17:21:48 -0500 Subject: [PATCH 24/30] adding test_process_pending_deposits_limit_is_reached --- .../test_process_pending_deposits.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 78fe4463b8..89da0ea2bb 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -177,6 +177,27 @@ def test_pending_deposit_not_finalized(spec, state): assert len(state.pending_deposits) == 1 +@with_electra_and_later +@spec_state_test +def test_process_pending_deposits_limit_is_reached(spec, state): + amount = 5000 + cumulative_amount = 0 + # set pending deposits to the maximum + for i in range(spec.MAX_PENDING_DEPOSITS_PER_EPOCH_PROCESSING+1): + wc = state.validators[i].withdrawal_credentials + pd = build_pending_deposit(spec, i, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + cumulative_amount += amount + # churn limit was not reached + assert cumulative_amount < spec.get_activation_exit_churn_limit(state) + yield from run_process_pending_deposits(spec, state) + # no deposits above limit were processed + assert len(state.pending_deposits) == 1 + + @with_electra_and_later @spec_state_test def test_pending_deposit_validator_withdrawn(spec, state): From 336c6f15101e150907b6533be84f675ac702f939 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 5 Aug 2024 14:14:03 -0500 Subject: [PATCH 25/30] adding some more tests based on test plan --- .../test_apply_pending_deposit.py | 43 +++++++++++++++++++ .../test_process_pending_deposits.py | 26 +++++++++++ 2 files changed, 69 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 4de4f624e2..0cf9cd3a95 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -101,6 +101,49 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): assert current_credentials == compounding_credentials +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_switch_to_compounding_invalid_sig(spec, state): + amount = 100 + + # choose a value public key that's in the validator set + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + # advance the state + next_epoch_via_block(spec, state) + state.validators[index].withdrawal_credentials = withdrawal_credentials + # set validator to be exited by current epoch + state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 + # creates wrong signature + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + withdrawal_credentials, + signed=True) + deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=compounding_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + ) + state.balances[index] = 0 + # run test + spec.apply_pending_deposit(state, deposit) + # validator balance should increase + assert state.balances[index] == amount + current_credentials = state.validators[0].withdrawal_credentials + assert current_credentials == withdrawal_credentials + + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_switch_to_compounding_not_exited(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 89da0ea2bb..05e8de00b5 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -154,6 +154,32 @@ def test_pending_deposit_eth1_bridge_not_applied(spec, state): assert len(state.pending_deposits) == 1 +@with_electra_and_later +@spec_state_test +def test_no_pending_deposit_eth1_bridge(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + # there is no pending eth1 bridge deposits + # state.eth1_deposit_index == state.deposit_requests_start_index + state.deposit_requests_start_index = state.eth1_deposit_index + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=withdrawal_credentials, + signed=True) + state.pending_deposits.append(pd) + # set deposit_balance_to_consume to some initial amount + state.deposit_balance_to_consume = amount + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # all pending deposits processed + assert len(state.pending_deposits) == 0 + + @with_electra_and_later @spec_state_test def test_pending_deposit_not_finalized(spec, state): From 3593a0cb3451a3c60ae37092594d4ef07207fa93 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Mon, 5 Aug 2024 16:38:51 -0500 Subject: [PATCH 26/30] adding 3 more tests --- .../test_apply_pending_deposit.py | 39 +++++++ .../test_process_pending_deposits.py | 108 ++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 0cf9cd3a95..3b8588ecce 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -101,6 +101,45 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): assert current_credentials == compounding_credentials +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_switch_to_compounding_has_bls(spec, state): + amount = 100 + + # choose a value public key that's in the validator set + index = 0 + compounding_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + # advance the state + next_epoch_via_block(spec, state) + bls_credentials = state.validators[index].withdrawal_credentials + # set validator to be exited by current epoch + state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) + deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=compounding_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + ) + state.balances[index] = 0 + # run test + spec.apply_pending_deposit(state, deposit) + # validator balance should increase + assert state.balances[index] == amount + current_credentials = state.validators[index].withdrawal_credentials + # does not switch to compounding + assert current_credentials == bls_credentials + + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_switch_to_compounding_invalid_sig(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 05e8de00b5..5babd66c86 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -393,6 +393,71 @@ def test_pending_deposit_balance_equal_churn_with_compounding(spec, state): assert current_credentials == withdrawal_credentials +@with_electra_and_later +@spec_state_test +def test_top_up__zero_balance(spec, state): + validator_index = 0 + amount = spec.MAX_EFFECTIVE_BALANCE // 4 + + initial_balance = 0 + initial_effective_balance = 0 + state.balances[validator_index] = initial_balance + val = state.validators[validator_index] + val.effective_balance = initial_effective_balance + wc = val.withdrawal_credentials + pd = build_pending_deposit(spec, validator_index, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + + yield from run_process_pending_deposits(spec, state) + + deposits_len = len(state.pending_deposits) + assert state.pending_deposits[deposits_len - 1].amount == amount + # unchanged effective balance + assert val.effective_balance == initial_effective_balance + + +@with_electra_and_later +@spec_state_test +def test_incorrect_sig_top_up(spec, state): + validator_index = 0 + amount = spec.MAX_EFFECTIVE_BALANCE // 4 + + val = state.validators[validator_index] + wc = val.withdrawal_credentials + pd = build_pending_deposit(spec, validator_index, + amount=amount, + withdrawal_credentials=wc, + signed=False) + state.pending_deposits.append(pd) + + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +def test_incorrect_withdrawal_credentials_top_up(spec, state): + validator_index = 0 + amount = spec.MAX_EFFECTIVE_BALANCE // 4 + + initial_balance = 0 + initial_effective_balance = 0 + state.balances[validator_index] = initial_balance + val = state.validators[validator_index] + val.effective_balance = initial_effective_balance + wc = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:] + + pd = build_pending_deposit(spec, validator_index, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + + yield from run_process_pending_deposits(spec, state) + + @with_electra_and_later @spec_state_test def test_pending_deposit_balance_above_churn(spec, state): @@ -416,6 +481,49 @@ def test_pending_deposit_balance_above_churn(spec, state): ] +@with_electra_and_later +@spec_state_test +def test_top_up__max_effective_balance(spec, state): + validator_index = 0 + amount = spec.MAX_EFFECTIVE_BALANCE // 4 + wc = state.validators[validator_index].withdrawal_credentials + pd = build_pending_deposit(spec, validator_index, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + + state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE + state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE + + yield from run_process_pending_deposits(spec, state) + + assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE + + +@with_electra_and_later +@spec_state_test +def test_top_up__less_effective_balance(spec, state): + validator_index = 0 + amount = spec.MAX_EFFECTIVE_BALANCE // 4 + wc = state.validators[validator_index].withdrawal_credentials + pd = build_pending_deposit(spec, validator_index, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + + initial_balance = spec.MAX_EFFECTIVE_BALANCE - 1000 + initial_effective_balance = spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT + state.balances[validator_index] = initial_balance + state.validators[validator_index].effective_balance = initial_effective_balance + + yield from run_process_pending_deposits(spec, state) + + # unchanged effective balance + assert state.validators[validator_index].effective_balance == initial_effective_balance + + @with_electra_and_later @spec_state_test def test_pending_deposit_preexisting_churn(spec, state): From 2cf7de96cdca2d53c8fd1f56dbe024ca9991a9c7 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 6 Aug 2024 11:44:43 -0500 Subject: [PATCH 27/30] updating bridge tests --- .../test_process_pending_deposits.py | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 5babd66c86..8b502c60fe 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -132,6 +132,33 @@ def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): yield from run_process_pending_deposits(spec, state) +@with_electra_and_later +@spec_state_test +def test_pending_deposit_eth1_bridge_pending(spec, state): + amount = spec.MIN_ACTIVATION_BALANCE + # There are pending Eth1 bridge deposits + # state.eth1_deposit_index < state.deposit_requests_start_index + state.deposit_requests_start_index = state.eth1_deposit_index + 1 + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=withdrawal_credentials, + signed=True, + slot=1) + state.pending_deposits.append(pd) + # set deposit_balance_to_consume to some initial amount + state.deposit_balance_to_consume = amount + yield from run_process_pending_deposits(spec, state) + # deposit_balance_to_consume was reset to 0 + assert state.deposit_balance_to_consume == 0 + # deposit was postponed and not processed + assert len(state.pending_deposits) == 1 + + @with_electra_and_later @spec_state_test def test_pending_deposit_eth1_bridge_not_applied(spec, state): @@ -156,7 +183,7 @@ def test_pending_deposit_eth1_bridge_not_applied(spec, state): @with_electra_and_later @spec_state_test -def test_no_pending_deposit_eth1_bridge(spec, state): +def test_pending_deposit_no_eth1_bridge_pending(spec, state): amount = spec.MIN_ACTIVATION_BALANCE # there is no pending eth1 bridge deposits # state.eth1_deposit_index == state.deposit_requests_start_index From 337726cbaea061e30541280acb88ec453220563e Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 6 Aug 2024 12:04:46 -0500 Subject: [PATCH 28/30] adding no compounding test --- .../test_apply_pending_deposit.py | 42 +++++++++++++++++++ .../test_process_pending_deposits.py | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py index 3b8588ecce..942fe9ab72 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_apply_pending_deposit.py @@ -101,6 +101,48 @@ def test_apply_pending_deposit_switch_to_compounding(spec, state): assert current_credentials == compounding_credentials +@with_electra_and_later +@spec_state_test +def test_apply_pending_deposit_switch_to_compounding_no_compounding(spec, state): + amount = 100 + + # choose a value public key that's in the validator set + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + # wrong compounding + compounding_credentials = ( + spec.hash(b"wrong compounding address")[:] + ) + # advance the state + next_epoch_via_block(spec, state) + state.validators[index].withdrawal_credentials = withdrawal_credentials + # set validator to be exited by current epoch + state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1 + deposit_data = build_deposit_data(spec, + pubkeys[index], + privkeys[index], + amount, + compounding_credentials, + signed=True) + deposit = spec.PendingDeposit( + pubkey=pubkeys[index], + withdrawal_credentials=compounding_credentials, + amount=amount, + slot=spec.GENESIS_SLOT, + signature=deposit_data.signature, + ) + state.balances[index] = 0 + # run test + spec.apply_pending_deposit(state, deposit) + # validator balance should increase + assert state.balances[index] == amount + current_credentials = state.validators[0].withdrawal_credentials + assert current_credentials == withdrawal_credentials + + @with_electra_and_later @spec_state_test def test_apply_pending_deposit_switch_to_compounding_has_bls(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 8b502c60fe..aecfbd35d1 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -137,7 +137,7 @@ def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): def test_pending_deposit_eth1_bridge_pending(spec, state): amount = spec.MIN_ACTIVATION_BALANCE # There are pending Eth1 bridge deposits - # state.eth1_deposit_index < state.deposit_requests_start_index + # state.eth1_deposit_index < state.deposit_requests_start_index state.deposit_requests_start_index = state.eth1_deposit_index + 1 index = 0 withdrawal_credentials = ( From 56fe31031ceb6b162a2d2a7e0d089c3d137e424e Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 6 Aug 2024 14:10:23 -0500 Subject: [PATCH 29/30] adding run_process_pending_deposits to deposit request tests to properly test changes --- .../test_process_deposit_request.py | 15 ++++ .../test_process_pending_deposits.py | 70 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_deposit_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_deposit_request.py index 737fbcabb1..559b1c1bd1 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_deposit_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_deposit_request.py @@ -6,6 +6,12 @@ ) from eth2spec.test.helpers.state import next_epoch_via_block from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable +from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with + + +def run_process_pending_deposits(spec, state): + yield from run_epoch_processing_with( + spec, state, 'process_pending_deposits') @with_electra_and_later @@ -18,6 +24,7 @@ def test_new_deposit_under_max(spec, state): deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -30,6 +37,7 @@ def test_new_deposit_max(spec, state): deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -42,6 +50,7 @@ def test_new_deposit_over_max(spec, state): deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -64,6 +73,7 @@ def test_new_deposit_eth1_withdrawal_credentials(spec, state): ) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -85,6 +95,7 @@ def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): ) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -177,6 +188,7 @@ def test_incorrect_sig_top_up(spec, state): # invalid signatures, in top-ups, are allowed! yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -194,6 +206,7 @@ def test_incorrect_withdrawal_credentials_top_up(spec, state): # inconsistent withdrawal credentials, in top-ups, are allowed! yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -208,6 +221,7 @@ def test_key_validate_invalid_subgroup(spec, state): deposit_request = prepare_deposit_request(spec, validator_index, amount, pubkey=pubkey, signed=True) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later @@ -224,6 +238,7 @@ def test_key_validate_invalid_decompression(spec, state): deposit_request = prepare_deposit_request(spec, validator_index, amount, pubkey=pubkey, signed=True) yield from run_deposit_request_processing(spec, state, deposit_request, validator_index) + yield from run_process_pending_deposits(spec, state) @with_electra_and_later diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index aecfbd35d1..6d4b903545 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -1,6 +1,7 @@ from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with from eth2spec.test.context import ( spec_state_test, + always_bls, with_electra_and_later, ) from eth2spec.test.helpers.deposits import ( @@ -801,3 +802,72 @@ def test_processing_deposit_of_withdrawable_validator_not_churned(spec, state): build_pending_deposit_top_up(spec, state, validator_index=1, amount=amount) ] + + +@with_electra_and_later +@spec_state_test +@always_bls +def test_correct_sig_but_forked_state(spec, state): + amount = spec.MAX_EFFECTIVE_BALANCE + # deposits will always be valid, regardless of the current fork + state.fork.current_version = spec.Version('0x1234abcd') + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +def test_key_validate_invalid_subgroup(spec, state): + amount = spec.MAX_EFFECTIVE_BALANCE + + # All-zero pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception. + pubkey = b'\x00' * 48 + + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkey)[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + pubkey=pubkey, + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +def test_key_validate_invalid_decompression(spec, state): + amount = spec.MAX_EFFECTIVE_BALANCE + + # `deserialization_fails_infinity_with_true_b_flag` BLS G1 deserialization test case. + # This pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception. + pubkey_hex = 'c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + pubkey = bytes.fromhex(pubkey_hex) + + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkey)[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + pubkey=pubkey, + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) From c5db6dfcfb509462d9bc870847e0cbab196d7174 Mon Sep 17 00:00:00 2001 From: james-prysm Date: Tue, 6 Aug 2024 14:36:20 -0500 Subject: [PATCH 30/30] adding fork version tests --- .../test_process_pending_deposits.py | 65 +++++++++++++++++++ .../pyspec/eth2spec/test/helpers/deposits.py | 13 ++-- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py index 6d4b903545..8f27c7db10 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_deposits.py @@ -871,3 +871,68 @@ def test_key_validate_invalid_decompression(spec, state): signed=True) state.pending_deposits.append(pd) yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +@always_bls +def test_apply_pending_deposit_with_previous_fork_version(spec, state): + # Since deposits are valid across forks, the domain is always set with `GENESIS_FORK_VERSION`. + assert state.fork.previous_version != state.fork.current_version + amount = spec.MAX_EFFECTIVE_BALANCE + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + fork_version=state.fork.previous_version, + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +@always_bls +def test_apply_pending_deposit_with_genesis_fork_version(spec, state): + assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version) + + assert state.fork.previous_version != state.fork.current_version + amount = spec.MAX_EFFECTIVE_BALANCE + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + fork_version=spec.GENESIS_FORK_VERSION, + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) + + +@with_electra_and_later +@spec_state_test +@always_bls +def test_apply_pending_deposit_with_bad_fork_version(spec, state): + amount = spec.MAX_EFFECTIVE_BALANCE + index = 0 + withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + + spec.hash(pubkeys[index])[1:] + ) + wc = withdrawal_credentials + pd = build_pending_deposit(spec, index, + amount=amount, + withdrawal_credentials=wc, + fork_version=spec.Version('0xAaBbCcDd'), + signed=True) + state.pending_deposits.append(pd) + yield from run_process_pending_deposits(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index fc6e6b5d27..72311be22f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -23,23 +23,26 @@ def mock_deposit(spec, state, index): assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) -def build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, signed=False): +def build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, fork_version, signed=False): deposit_data = spec.DepositData( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount, ) if signed: - sign_deposit_data(spec, deposit_data, privkey) + sign_deposit_data(spec, deposit_data, privkey, fork_version) return deposit_data -def sign_deposit_data(spec, deposit_data, privkey): +def sign_deposit_data(spec, deposit_data, privkey, fork_version): deposit_message = spec.DepositMessage( pubkey=deposit_data.pubkey, withdrawal_credentials=deposit_data.withdrawal_credentials, amount=deposit_data.amount) - domain = spec.compute_domain(spec.DOMAIN_DEPOSIT) + if fork_version is not None: + domain = spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=fork_version) + else: + domain = spec.compute_domain(spec.DOMAIN_DEPOSIT) signing_root = spec.compute_signing_root(deposit_message, domain) deposit_data.signature = bls.Sign(privkey, signing_root) @@ -241,6 +244,7 @@ def build_pending_deposit(spec, validator_index, amount, pubkey=None, privkey=None, withdrawal_credentials=None, + fork_version=None, slot=None, signed=False): if index is None: @@ -267,6 +271,7 @@ def build_pending_deposit(spec, validator_index, amount, privkeys[index], amount, withdrawal_credentials, + fork_version, signed=True) pending_deposit.signature = deposit_data.signature return pending_deposit