From 0eda70cfcbf31f5eabe95339fd43d962b00f915e Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 12 Sep 2024 20:02:39 +0600 Subject: [PATCH 01/10] Switch to compounding when consolidating with source==target --- specs/electra/beacon-chain.md | 41 +++------ .../test_process_consolidation_request.py | 84 +++++++++++++++---- .../test_process_pending_consolidations.py | 55 +----------- 3 files changed, 83 insertions(+), 97 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 3dca59e1df..d00c969f1f 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -61,7 +61,6 @@ - [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) @@ -678,16 +677,6 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY) ``` -#### New `switch_to_compounding_validator` - -```python -def switch_to_compounding_validator(state: BeaconState, index: ValidatorIndex) -> None: - validator = state.validators[index] - if has_eth1_withdrawal_credential(validator): - validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] - queue_excess_active_balance(state, index) -``` - #### New `queue_excess_active_balance` ```python @@ -928,8 +917,6 @@ def process_pending_consolidations(state: BeaconState) -> None: if source_validator.withdrawable_epoch > next_epoch: break - # Churn any target excess active balance of target and raise its max - switch_to_compounding_validator(state, pending_consolidation.target_index) # Move active balance to target. Excess balance is withdrawable. active_balance = get_active_balance(state, pending_consolidation.source_index) decrease_balance(state, pending_consolidation.source_index, active_balance) @@ -1225,14 +1212,6 @@ def apply_deposit(state: BeaconState, state.pending_balance_deposits.append( PendingBalanceDeposit(index=index, amount=amount) ) # [Modified in Electra:EIP7251] - # Check if valid deposit switch to compounding credentials - if ( - is_compounding_withdrawal_credential(withdrawal_credentials) - and has_eth1_withdrawal_credential(state.validators[index]) - and is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature) - ): - switch_to_compounding_validator(state, index) - ``` ###### New `is_valid_deposit_signature` @@ -1431,10 +1410,6 @@ def process_consolidation_request( source_validator = state.validators[source_index] target_validator = state.validators[target_index] - # Verify that source != target, so a consolidation cannot be used as an exit. - if source_index == target_index: - return - # Verify source withdrawal credentials has_correct_credential = has_execution_withdrawal_credential(source_validator) is_correct_source_address = ( @@ -1459,12 +1434,22 @@ def process_consolidation_request( if target_validator.exit_epoch != FAR_FUTURE_EPOCH: return + # Churn any target excess active balance of target and raise its max + if has_eth1_withdrawal_credential(target_validator): + state.validators[target_index].withdrawal_credentials = ( + COMPOUNDING_WITHDRAWAL_PREFIX + target_validator.withdrawal_credentials[1:]) + queue_excess_active_balance(state, target_index) + + # Verify that source != target, so a consolidation cannot be used as an exit. + if source_index == target_index: + return + # Initiate source validator exit and append pending consolidation - source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn( + state.validators[source_index].exit_epoch = compute_consolidation_epoch_and_update_churn( state, source_validator.effective_balance ) - source_validator.withdrawable_epoch = Epoch( - source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY + state.validators[source_index].withdrawable_epoch = Epoch( + state.validators[source_index].exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY ) state.pending_consolidations.append(PendingConsolidation( source_index=source_index, diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index b05c20f565..1c6d8d22ae 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -395,7 +395,37 @@ def test_consolidation_balance_through_two_churn_epochs(spec, state): assert state.consolidation_balance_to_consume == expected_balance -# Failing tests +@with_electra_and_later +@with_presets([MINIMAL], "need sufficient consolidation churn limit") +@with_custom_state( + balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit, + threshold_fn=default_activation_threshold, +) +@spec_test +@single_phase +def test_source_equals_target_switches_to_compounding(spec, state): + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + + # Set source to eth1 credentials + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Make consolidation from source to source + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + # Check the the return condition + assert consolidation.source_pubkey == consolidation.target_pubkey + + yield from run_consolidation_processing( + spec, state, consolidation, success=True + ) + @with_electra_and_later @with_presets([MINIMAL], "need sufficient consolidation churn limit") @@ -405,7 +435,7 @@ def test_consolidation_balance_through_two_churn_epochs(spec, state): ) @spec_test @single_phase -def test_incorrect_source_equals_target(spec, state): +def test_source_equals_target_switches_to_compounding_with_excess(spec, state): current_epoch = spec.get_current_epoch(state) source_index = spec.get_active_validator_indices(state, current_epoch)[0] @@ -414,6 +444,8 @@ def test_incorrect_source_equals_target(spec, state): set_eth1_withdrawal_credential_with_balance( spec, state, source_index, address=source_address ) + # Add excess balance + state.balances[source_index] = state.balances[source_index] + spec.EFFECTIVE_BALANCE_INCREMENT # Make consolidation from source to source consolidation = spec.ConsolidationRequest( source_address=source_address, @@ -425,10 +457,12 @@ def test_incorrect_source_equals_target(spec, state): assert consolidation.source_pubkey == consolidation.target_pubkey yield from run_consolidation_processing( - spec, state, consolidation, success=False + spec, state, consolidation, success=True ) +# Failing tests + @with_electra_and_later @with_presets([MINIMAL], "need sufficient consolidation churn limit") @with_custom_state( @@ -815,6 +849,8 @@ def run_consolidation_processing(spec, state, consolidation, success=True): pre_exit_epoch_source = source_validator.exit_epoch pre_exit_epoch_target = target_validator.exit_epoch pre_pending_consolidations = state.pending_consolidations.copy() + pre_target_withdrawal_credentials = target_validator.withdrawal_credentials + pre_target_balance = state.balances[target_index] else: pre_state = state.copy() @@ -822,29 +858,45 @@ def run_consolidation_processing(spec, state, consolidation, success=True): yield 'consolidation_request', consolidation spec.process_consolidation_request(state, consolidation) + # print(state.validators[target_index].withdrawal_credentials) yield 'post', state if success: - # Check source and target have execution credentials + # Check source has execution credentials assert spec.has_execution_withdrawal_credential(source_validator) + # Check target has compounding credentials assert spec.has_execution_withdrawal_credential(target_validator) # Check source address in the consolidation fits the withdrawal credentials assert source_validator.withdrawal_credentials[12:] == consolidation.source_address - # Check source and target are not the same - assert source_index != target_index # Check source and target were not exiting assert pre_exit_epoch_source == spec.FAR_FUTURE_EPOCH assert pre_exit_epoch_target == spec.FAR_FUTURE_EPOCH - # Check source is now exiting - assert state.validators[source_index].exit_epoch < spec.FAR_FUTURE_EPOCH - # Check that the exit epoch matches earliest_consolidation_epoch - assert state.validators[source_index].exit_epoch == state.earliest_consolidation_epoch - # Check that the correct consolidation has been appended - expected_new_pending_consolidation = spec.PendingConsolidation( - source_index=source_index, - target_index=target_index, - ) - assert state.pending_consolidations == pre_pending_consolidations + [expected_new_pending_consolidation] + # Check excess balance is queued if the target switched to compounding + if pre_target_withdrawal_credentials[:1] == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX: + assert state.validators[target_index].withdrawal_credentials == ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + pre_target_withdrawal_credentials[1:]) + assert state.balances[target_index] == spec.MIN_ACTIVATION_BALANCE + if pre_target_balance > spec.MIN_ACTIVATION_BALANCE: + assert state.pending_balance_deposits == [spec.PendingBalanceDeposit( + index=target_index, amount=(pre_target_balance - spec.MIN_ACTIVATION_BALANCE))] + # If source and target are same, no consolidation must have been initiated + if source_index == target_index: + assert state.validators[source_index].exit_epoch == spec.FAR_FUTURE_EPOCH + assert state.pending_consolidations == [] + else: + # Check source is now exiting + assert state.validators[source_index].exit_epoch < spec.FAR_FUTURE_EPOCH + # Check that the exit epoch matches earliest_consolidation_epoch + assert state.validators[source_index].exit_epoch == state.earliest_consolidation_epoch + # Check that the withdrawable_epoch is set correctly + assert state.validators[source_index].withdrawable_epoch == ( + state.validators[source_index].exit_epoch + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY) + # Check that the correct consolidation has been appended + expected_new_pending_consolidation = spec.PendingConsolidation( + source_index=source_index, + target_index=target_index, + ) + assert state.pending_consolidations == pre_pending_consolidations + [expected_new_pending_consolidation] else: assert pre_state == state diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py index 14e151e2e2..61714562d9 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_pending_consolidations.py @@ -36,10 +36,6 @@ def test_basic_pending_consolidation(spec, state): yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") # Pending consolidation was successfully processed - assert ( - state.validators[target_index].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) assert state.balances[target_index] == 2 * spec.MIN_ACTIVATION_BALANCE assert state.balances[source_index] == 0 assert state.pending_consolidations == [] @@ -65,9 +61,6 @@ def test_consolidation_not_yet_withdrawable_validator(spec, state): pre_pending_consolidations = state.pending_consolidations.copy() pre_balances = state.balances.copy() - pre_target_withdrawal_credential = state.validators[ - target_index - ].withdrawal_credentials[:1] yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") @@ -75,11 +68,6 @@ def test_consolidation_not_yet_withdrawable_validator(spec, state): # Balances are unchanged assert state.balances[source_index] == pre_balances[0] assert state.balances[target_index] == pre_balances[1] - # Target withdrawal credential is unchanged - assert ( - state.validators[target_index].withdrawal_credentials[:1] - == pre_target_withdrawal_credential - ) # Pending consolidation is still in the queue assert state.pending_consolidations == pre_pending_consolidations @@ -121,17 +109,9 @@ def test_skip_consolidation_when_source_slashed(spec, state): # first pending consolidation should not be processed assert state.balances[target0_index] == spec.MIN_ACTIVATION_BALANCE assert state.balances[source0_index] == spec.MIN_ACTIVATION_BALANCE - assert ( - state.validators[target0_index].withdrawal_credentials[:1] - == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX - ) # second pending consolidation should be processed: first one is skipped and doesn't block the queue assert state.balances[target1_index] == 2 * spec.MIN_ACTIVATION_BALANCE assert state.balances[source1_index] == 0 - assert ( - state.validators[target1_index].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) @with_electra_and_later @@ -167,26 +147,14 @@ def test_all_consolidation_cases_together(spec, state): spec.initiate_validator_exit(state, 2) pre_balances = state.balances.copy() - pre_target_withdrawal_prefixes = [ - state.validators[target_index[i]].withdrawal_credentials[:1] - for i in [0, 1, 2, 3] - ] pre_pending_consolidations = state.pending_consolidations.copy() yield from run_epoch_processing_with(spec, state, "process_pending_consolidations") # First consolidation is successfully processed - assert ( - state.validators[target_index[0]].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) assert state.balances[target_index[0]] == 2 * spec.MIN_ACTIVATION_BALANCE assert state.balances[source_index[0]] == 0 # All other consolidations are not processed for i in [1, 2, 3]: - assert ( - state.validators[target_index[i]].withdrawal_credentials[:1] - == pre_target_withdrawal_prefixes[i] - ) assert state.balances[source_index[i]] == pre_balances[source_index[i]] assert state.balances[target_index[i]] == pre_balances[target_index[i]] # First consolidation is processed, second is skipped, last two are left in the queue @@ -226,22 +194,11 @@ def test_pending_consolidation_future_epoch(spec, state): # Pending consolidation was successfully processed expected_source_balance = state_before_consolidation.balances[source_index] - spec.MIN_ACTIVATION_BALANCE - assert ( - state.validators[target_index].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) - assert state.balances[target_index] == 2 * spec.MIN_ACTIVATION_BALANCE + expected_target_balance = state_before_consolidation.balances[target_index] + spec.MIN_ACTIVATION_BALANCE assert state.balances[source_index] == expected_source_balance + assert state.balances[target_index] == expected_target_balance assert state.pending_consolidations == [] - # Pending balance deposit to the target is created as part of `switch_to_compounding_validator`. - # The excess balance to queue are the rewards accumulated over the previous epoch transitions. - expected_pending_balance = state_before_consolidation.balances[target_index] - spec.MIN_ACTIVATION_BALANCE - assert len(state.pending_balance_deposits) > 0 - pending_balance_deposit = state.pending_balance_deposits[len(state.pending_balance_deposits) - 1] - assert pending_balance_deposit.index == target_index - assert pending_balance_deposit.amount == expected_pending_balance - @with_electra_and_later @spec_state_test @@ -280,10 +237,6 @@ def test_pending_consolidation_compounding_creds(spec, state): expected_target_balance = ( state_before_consolidation.balances[source_index] + state_before_consolidation.balances[target_index] ) - assert ( - state.validators[target_index].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) assert state.balances[target_index] == expected_target_balance # All source balance is active and moved to the target, # because the source validator has compounding credentials @@ -336,10 +289,6 @@ def test_pending_consolidation_with_pending_deposit(spec, state): expected_target_balance = ( state_before_consolidation.balances[source_index] + state_before_consolidation.balances[target_index] ) - assert ( - state.validators[target_index].withdrawal_credentials[:1] - == spec.COMPOUNDING_WITHDRAWAL_PREFIX - ) assert state.balances[target_index] == expected_target_balance assert state.balances[source_index] == 0 assert state.pending_consolidations == [] From 747a5a7891a35b6dccbd8b6379ecb9c24936f4ee Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Mon, 16 Sep 2024 11:01:06 +0400 Subject: [PATCH 02/10] Apply suggestions from @dapplion Co-authored-by: Lion - dapplion <35266934+dapplion@users.noreply.github.com> --- specs/electra/beacon-chain.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index d00c969f1f..9037dd74df 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1437,7 +1437,8 @@ def process_consolidation_request( # Churn any target excess active balance of target and raise its max if has_eth1_withdrawal_credential(target_validator): state.validators[target_index].withdrawal_credentials = ( - COMPOUNDING_WITHDRAWAL_PREFIX + target_validator.withdrawal_credentials[1:]) + COMPOUNDING_WITHDRAWAL_PREFIX + target_validator.withdrawal_credentials[1:] + ) queue_excess_active_balance(state, target_index) # Verify that source != target, so a consolidation cannot be used as an exit. From 1bf8ca5777cab1327036cea52d559ceee76e47f5 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 18 Sep 2024 09:20:42 +0400 Subject: [PATCH 03/10] Apply suggestions by @ralexstokes Co-authored-by: Alex Stokes --- .../block_processing/test_process_consolidation_request.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index 1c6d8d22ae..dd4f0b944b 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -858,7 +858,6 @@ def run_consolidation_processing(spec, state, consolidation, success=True): yield 'consolidation_request', consolidation spec.process_consolidation_request(state, consolidation) - # print(state.validators[target_index].withdrawal_credentials) yield 'post', state From b29a1d36d1a119db2bebd8e10d3244551be3c3f0 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 18 Sep 2024 13:27:03 +0400 Subject: [PATCH 04/10] Isolate switch to compounding flow --- specs/electra/beacon-chain.md | 81 +++- .../test_process_consolidation_request.py | 396 ++++++++++++++++-- .../eth2spec/test/helpers/withdrawals.py | 5 +- 3 files changed, 425 insertions(+), 57 deletions(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 9037dd74df..10c0eebf3a 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -61,6 +61,7 @@ - [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) @@ -96,6 +97,7 @@ - [Deposit requests](#deposit-requests) - [New `process_deposit_request`](#new-process_deposit_request) - [Execution layer consolidation requests](#execution-layer-consolidation-requests) + - [New `is_valid_switch_to_compounding_request`](#new-is_valid_switch_to_compounding_request) - [New `process_consolidation_request`](#new-process_consolidation_request) - [Testing](#testing) @@ -677,6 +679,15 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY) ``` +#### New `switch_to_compounding_validator` + +```python +def switch_to_compounding_validator(state: BeaconState, index: ValidatorIndex) -> None: + validator = state.validators[index] + validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] + queue_excess_active_balance(state, index) +``` + #### New `queue_excess_active_balance` ```python @@ -1383,6 +1394,45 @@ def process_deposit_request(state: BeaconState, deposit_request: DepositRequest) ##### Execution layer consolidation requests +###### New `is_valid_switch_to_compounding_request` + +```python +def is_valid_switch_to_compounding_request( + state: BeaconState, + consolidation_request: ConsolidationRequest +) -> bool: + # Switch to compounding requires source and target be equal + if consolidation_request.source_pubkey != consolidation_request.target_pubkey: + return False + + # Verify pubkey exists + source_pubkey = consolidation_request.source_pubkey + validator_pubkeys = [v.pubkey for v in state.validators] + if source_pubkey not in validator_pubkeys: + return False + + source_validator = state.validators[ValidatorIndex(validator_pubkeys.index(source_pubkey))] + + # Verify request has been authorized + if source_validator.withdrawal_credentials[12:] != consolidation_request.source_address: + return False + + # Verify source withdrawal credentials + if not has_eth1_withdrawal_credential(source_validator): + return False + + # Verify the source is active + current_epoch = get_current_epoch(state) + if not is_active_validator(source_validator, current_epoch): + return False + + # Verify exit for source have not been initiated + if source_validator.exit_epoch != FAR_FUTURE_EPOCH: + return False + + return True +``` + ###### New `process_consolidation_request` ```python @@ -1390,6 +1440,16 @@ def process_consolidation_request( state: BeaconState, consolidation_request: ConsolidationRequest ) -> None: + if is_valid_switch_to_compounding_request(state, consolidation_request): + validator_pubkeys = [v.pubkey for v in state.validators] + request_source_pubkey = consolidation_request.source_pubkey + source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey)) + switch_to_compounding_validator(state, source_index) + return + + # Verify that source != target, so a consolidation cannot be used as an exit. + if consolidation_request.source_pubkey == consolidation_request.target_pubkey: + return # If the pending consolidations queue is full, consolidation requests are ignored if len(state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT: return @@ -1434,28 +1494,21 @@ def process_consolidation_request( if target_validator.exit_epoch != FAR_FUTURE_EPOCH: return - # Churn any target excess active balance of target and raise its max - if has_eth1_withdrawal_credential(target_validator): - state.validators[target_index].withdrawal_credentials = ( - COMPOUNDING_WITHDRAWAL_PREFIX + target_validator.withdrawal_credentials[1:] - ) - queue_excess_active_balance(state, target_index) - - # Verify that source != target, so a consolidation cannot be used as an exit. - if source_index == target_index: - return - # Initiate source validator exit and append pending consolidation - state.validators[source_index].exit_epoch = compute_consolidation_epoch_and_update_churn( + source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn( state, source_validator.effective_balance ) - state.validators[source_index].withdrawable_epoch = Epoch( - state.validators[source_index].exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY + source_validator.withdrawable_epoch = Epoch( + source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY ) state.pending_consolidations.append(PendingConsolidation( source_index=source_index, target_index=target_index )) + + # Churn any target excess active balance of target and raise its max + if has_eth1_withdrawal_credential(target_validator): + switch_to_compounding_validator(state, target_index) ``` ## Testing diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index dd4f0b944b..4bc4617c82 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -66,6 +66,106 @@ def test_basic_consolidation_in_current_consolidation_epoch(spec, state): assert state.validators[source_index].exit_epoch == expected_exit_epoch +@with_electra_and_later +@with_presets([MINIMAL], "need sufficient consolidation churn limit") +@with_custom_state( + balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit, + threshold_fn=default_activation_threshold, +) +@spec_test +@single_phase +def test_basic_consolidation_with_excess_target_balance(spec, state): + # This state has 256 validators each with 32 ETH in MINIMAL preset, 128 ETH consolidation churn + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + target_index = spec.get_active_validator_indices(state, current_epoch)[1] + + # Set source to eth1 credentials + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Make consolidation with source address + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[target_index].pubkey, + ) + + # Set target to eth1 credentials + set_eth1_withdrawal_credential_with_balance(spec, state, target_index) + + # Set earliest consolidation epoch to the expected exit epoch + expected_exit_epoch = spec.compute_activation_exit_epoch(current_epoch) + state.earliest_consolidation_epoch = expected_exit_epoch + consolidation_churn_limit = spec.get_consolidation_churn_limit(state) + # Set the consolidation balance to consume equal to churn limit + state.consolidation_balance_to_consume = consolidation_churn_limit + + # Add excess balance + state.balances[target_index] = state.balances[target_index] + spec.EFFECTIVE_BALANCE_INCREMENT + + yield from run_consolidation_processing(spec, state, consolidation) + + # Check consolidation churn is decremented correctly + assert ( + state.consolidation_balance_to_consume + == consolidation_churn_limit - spec.MIN_ACTIVATION_BALANCE + ) + # Check exit epoch + assert state.validators[source_index].exit_epoch == expected_exit_epoch + + +@with_electra_and_later +@with_presets([MINIMAL], "need sufficient consolidation churn limit") +@with_custom_state( + balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit, + threshold_fn=default_activation_threshold, +) +@spec_test +@single_phase +def test_basic_consolidation_with_excess_target_balance_and_compounding_credentials(spec, state): + # This state has 256 validators each with 32 ETH in MINIMAL preset, 128 ETH consolidation churn + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + target_index = spec.get_active_validator_indices(state, current_epoch)[1] + + # Set source to eth1 credentials + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Make consolidation with source address + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[target_index].pubkey, + ) + + # Set target to eth1 credentials + set_compounding_withdrawal_credential(spec, state, target_index) + + # Set earliest consolidation epoch to the expected exit epoch + expected_exit_epoch = spec.compute_activation_exit_epoch(current_epoch) + state.earliest_consolidation_epoch = expected_exit_epoch + consolidation_churn_limit = spec.get_consolidation_churn_limit(state) + # Set the consolidation balance to consume equal to churn limit + state.consolidation_balance_to_consume = consolidation_churn_limit + + # Add excess balance + state.balances[target_index] = state.balances[target_index] + spec.EFFECTIVE_BALANCE_INCREMENT + + yield from run_consolidation_processing(spec, state, consolidation) + + # Check consolidation churn is decremented correctly + assert ( + state.consolidation_balance_to_consume + == consolidation_churn_limit - spec.MIN_ACTIVATION_BALANCE + ) + # Check exit epoch + assert state.validators[source_index].exit_epoch == expected_exit_epoch + + @with_electra_and_later @with_presets([MINIMAL], "need sufficient consolidation churn limit") @with_custom_state( @@ -235,7 +335,7 @@ def test_basic_consolidation_with_compounding_credentials(spec, state): target_pubkey=state.validators[target_index].pubkey, ) - # Set target to eth1 credentials + # Set target to compounding credentials set_compounding_withdrawal_credential(spec, state, target_index) # Set the consolidation balance to consume equal to churn limit @@ -396,14 +496,8 @@ def test_consolidation_balance_through_two_churn_epochs(spec, state): @with_electra_and_later -@with_presets([MINIMAL], "need sufficient consolidation churn limit") -@with_custom_state( - balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit, - threshold_fn=default_activation_threshold, -) -@spec_test -@single_phase -def test_source_equals_target_switches_to_compounding(spec, state): +@spec_state_test +def test_basic_switch_to_compounding(spec, state): current_epoch = spec.get_current_epoch(state) source_index = spec.get_active_validator_indices(state, current_epoch)[0] @@ -419,23 +513,14 @@ def test_source_equals_target_switches_to_compounding(spec, state): target_pubkey=state.validators[source_index].pubkey, ) - # Check the the return condition - assert consolidation.source_pubkey == consolidation.target_pubkey - - yield from run_consolidation_processing( + yield from run_switch_to_compounding_processing( spec, state, consolidation, success=True ) @with_electra_and_later -@with_presets([MINIMAL], "need sufficient consolidation churn limit") -@with_custom_state( - balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit, - threshold_fn=default_activation_threshold, -) -@spec_test -@single_phase -def test_source_equals_target_switches_to_compounding_with_excess(spec, state): +@spec_state_test +def test_switch_to_compounding_with_excess(spec, state): current_epoch = spec.get_current_epoch(state) source_index = spec.get_active_validator_indices(state, current_epoch)[0] @@ -453,10 +538,36 @@ def test_source_equals_target_switches_to_compounding_with_excess(spec, state): target_pubkey=state.validators[source_index].pubkey, ) - # Check the the return condition - assert consolidation.source_pubkey == consolidation.target_pubkey + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=True + ) - yield from run_consolidation_processing( + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_with_pending_consolidations_at_limit(spec, state): + state.pending_consolidations = [ + spec.PendingConsolidation(source_index=0, target_index=1) + ] * spec.PENDING_CONSOLIDATIONS_LIMIT + + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + + # Set source to eth1 credentials + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Add excess balance + state.balances[source_index] = state.balances[source_index] + spec.EFFECTIVE_BALANCE_INCREMENT + # Make consolidation from source to source + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + yield from run_switch_to_compounding_processing( spec, state, consolidation, success=True ) @@ -831,6 +942,156 @@ def test_incorrect_unknown_target_pubkey(spec, state): ) +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_exited_source(spec, state): + # Set up an otherwise correct request + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + # exit source + spec.initiate_validator_exit(state, source_index) + + # Check the the return condition + assert state.validators[source_index].exit_epoch != spec.FAR_FUTURE_EPOCH + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_inactive_source(spec, state): + # Set up an otherwise correct request + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + # set source validator as not yet activated + state.validators[source_index].activation_epoch = spec.FAR_FUTURE_EPOCH + + # Check the the return condition + assert not spec.is_active_validator(state.validators[source_index], current_epoch) + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_source_bls_withdrawal_credential(spec, state): + # Set up a correct request, but source does have + # a bls withdrawal credential + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + # Check the the return condition + assert not spec.has_eth1_withdrawal_credential(state.validators[source_index]) + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_source_coumpounding_withdrawal_credential(spec, state): + # Set up a correct request, but source does have + # a compounding withdrawal credential and excess balance + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + set_compounding_withdrawal_credential(spec, state, source_index) + state.balances[source_index] = spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT + + # Check the the return condition + assert not spec.has_eth1_withdrawal_credential(state.validators[source_index]) + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_not_authorized(spec, state): + # Set up an otherwise correct request + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Make request with different source address + consolidation = spec.ConsolidationRequest( + source_address=b"\x33" * 20, + source_pubkey=state.validators[source_index].pubkey, + target_pubkey=state.validators[source_index].pubkey, + ) + + # Check the the return condition + assert not state.validators[source_index].withdrawal_credentials[12:] == consolidation.source_address + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + +@with_electra_and_later +@spec_state_test +def test_switch_to_compounding_unknown_source_pubkey(spec, state): + # Set up an otherwise correct request + current_epoch = spec.get_current_epoch(state) + source_index = spec.get_active_validator_indices(state, current_epoch)[0] + source_address = b"\x22" * 20 + set_eth1_withdrawal_credential_with_balance( + spec, state, source_index, address=source_address + ) + # Make consolidation with different source pubkey + consolidation = spec.ConsolidationRequest( + source_address=source_address, + source_pubkey=b"\x00" * 48, + target_pubkey=b"\x00" * 48, + ) + + # Check the the return condition + assert not state.validators[source_index].pubkey == consolidation.source_pubkey + + yield from run_switch_to_compounding_processing( + spec, state, consolidation, success=False + ) + + def run_consolidation_processing(spec, state, consolidation, success=True): """ Run ``process_consolidation``, yielding: @@ -865,12 +1126,28 @@ def run_consolidation_processing(spec, state, consolidation, success=True): # Check source has execution credentials assert spec.has_execution_withdrawal_credential(source_validator) # Check target has compounding credentials - assert spec.has_execution_withdrawal_credential(target_validator) + assert spec.has_compounding_withdrawal_credential(state.validators[target_index]) # Check source address in the consolidation fits the withdrawal credentials assert source_validator.withdrawal_credentials[12:] == consolidation.source_address + # Check source and target are not the same + assert source_index != target_index # Check source and target were not exiting assert pre_exit_epoch_source == spec.FAR_FUTURE_EPOCH assert pre_exit_epoch_target == spec.FAR_FUTURE_EPOCH + # Check source is now exiting + assert state.validators[source_index].exit_epoch < spec.FAR_FUTURE_EPOCH + # Check that the exit epoch matches earliest_consolidation_epoch + assert state.validators[source_index].exit_epoch == state.earliest_consolidation_epoch + # Check that the withdrawable_epoch is set correctly + assert state.validators[source_index].withdrawable_epoch == ( + state.validators[source_index].exit_epoch + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + ) + # Check that the correct consolidation has been appended + expected_new_pending_consolidation = spec.PendingConsolidation( + source_index=source_index, + target_index=target_index, + ) + assert state.pending_consolidations == pre_pending_consolidations + [expected_new_pending_consolidation] # Check excess balance is queued if the target switched to compounding if pre_target_withdrawal_credentials[:1] == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX: assert state.validators[target_index].withdrawal_credentials == ( @@ -879,23 +1156,58 @@ def run_consolidation_processing(spec, state, consolidation, success=True): if pre_target_balance > spec.MIN_ACTIVATION_BALANCE: assert state.pending_balance_deposits == [spec.PendingBalanceDeposit( index=target_index, amount=(pre_target_balance - spec.MIN_ACTIVATION_BALANCE))] - # If source and target are same, no consolidation must have been initiated - if source_index == target_index: - assert state.validators[source_index].exit_epoch == spec.FAR_FUTURE_EPOCH - assert state.pending_consolidations == [] else: - # Check source is now exiting - assert state.validators[source_index].exit_epoch < spec.FAR_FUTURE_EPOCH - # Check that the exit epoch matches earliest_consolidation_epoch - assert state.validators[source_index].exit_epoch == state.earliest_consolidation_epoch - # Check that the withdrawable_epoch is set correctly - assert state.validators[source_index].withdrawable_epoch == ( - state.validators[source_index].exit_epoch + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY) - # Check that the correct consolidation has been appended - expected_new_pending_consolidation = spec.PendingConsolidation( - source_index=source_index, - target_index=target_index, - ) - assert state.pending_consolidations == pre_pending_consolidations + [expected_new_pending_consolidation] + assert state.balances[target_index] == pre_target_balance + else: + assert pre_state == state + + +def run_switch_to_compounding_processing(spec, state, consolidation, success=True): + """ + Run ``process_consolidation``, yielding: + - pre-state ('pre') + - consolidation_request ('consolidation_request') + - post-state ('post'). + If ``success == False``, ``process_consolidation_request`` would return without any state change. + """ + + if success: + validator_pubkeys = [v.pubkey for v in state.validators] + source_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.source_pubkey)) + target_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.target_pubkey)) + source_validator = state.validators[source_index] + pre_exit_epoch = source_validator.exit_epoch + pre_pending_consolidations = state.pending_consolidations.copy() + pre_withdrawal_credentials = source_validator.withdrawal_credentials + pre_balance = state.balances[source_index] + else: + pre_state = state.copy() + + yield 'pre', state + yield 'consolidation_request', consolidation + + spec.process_consolidation_request(state, consolidation) + + yield 'post', state + + if success: + # Check that source and target are same + assert source_index == target_index + # Check that the credentials before the switch are of ETH1 type + assert pre_withdrawal_credentials[:1] == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + # Check source address in the consolidation fits the withdrawal credentials + assert state.validators[source_index].withdrawal_credentials[12:] == consolidation.source_address + # Check that the source has switched to compounding + assert state.validators[source_index].withdrawal_credentials == ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + pre_withdrawal_credentials[1:] + ) + # Check excess balance is queued + assert state.balances[source_index] == spec.MIN_ACTIVATION_BALANCE + if pre_balance > spec.MIN_ACTIVATION_BALANCE: + assert state.pending_balance_deposits == [spec.PendingBalanceDeposit( + index=source_index, amount=(pre_balance - spec.MIN_ACTIVATION_BALANCE))] + # Check no consolidation has been initiated + assert state.validators[source_index].exit_epoch == spec.FAR_FUTURE_EPOCH + assert state.pending_consolidations == pre_pending_consolidations else: assert pre_state == state diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index 0ce476c86f..6247c54761 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -30,7 +30,10 @@ def set_validator_fully_withdrawable(spec, state, index, withdrawable_epoch=None def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance=None, address=None): if balance is None: - balance = spec.MAX_EFFECTIVE_BALANCE + if is_post_electra(spec): + balance = spec.MIN_ACTIVATION_BALANCE + else: + balance = spec.MAX_EFFECTIVE_BALANCE if address is None: address = b'\x11' * 20 From d71d9dda9e093b1421f2077be1ba4c316852811a Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 18 Sep 2024 13:33:18 +0400 Subject: [PATCH 05/10] Fix lint --- .../block_processing/test_process_consolidation_request.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index 4bc4617c82..3259bc2d11 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -1176,7 +1176,6 @@ def run_switch_to_compounding_processing(spec, state, consolidation, success=Tru source_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.source_pubkey)) target_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.target_pubkey)) source_validator = state.validators[source_index] - pre_exit_epoch = source_validator.exit_epoch pre_pending_consolidations = state.pending_consolidations.copy() pre_withdrawal_credentials = source_validator.withdrawal_credentials pre_balance = state.balances[source_index] From 23699f596da62980d650c63f9a47feec247c8f56 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 19 Sep 2024 10:44:38 +0400 Subject: [PATCH 06/10] Undo MAX_EB to MIN_AB switch in withdrawal helper --- tests/core/pyspec/eth2spec/test/helpers/withdrawals.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index 6247c54761..0ce476c86f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -30,10 +30,7 @@ def set_validator_fully_withdrawable(spec, state, index, withdrawable_epoch=None def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance=None, address=None): if balance is None: - if is_post_electra(spec): - balance = spec.MIN_ACTIVATION_BALANCE - else: - balance = spec.MAX_EFFECTIVE_BALANCE + balance = spec.MAX_EFFECTIVE_BALANCE if address is None: address = b'\x11' * 20 From 2bc260470671a548de0f612fe2d8311a3ae528a8 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 27 Sep 2024 11:02:22 +0400 Subject: [PATCH 07/10] Apply suggestions from @jtraglia Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> --- specs/electra/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 10c0eebf3a..e89f5ccce9 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1426,7 +1426,7 @@ def is_valid_switch_to_compounding_request( if not is_active_validator(source_validator, current_epoch): return False - # Verify exit for source have not been initiated + # Verify exit for source has not been initiated if source_validator.exit_epoch != FAR_FUTURE_EPOCH: return False From a7b0d6f416eec4a54dab2eb4a8a318af052453a6 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Tue, 1 Oct 2024 15:37:53 +0400 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Alex Stokes Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com> --- .../test_process_consolidation_request.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index 3259bc2d11..cdaf786fef 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -572,7 +572,7 @@ def test_switch_to_compounding_with_pending_consolidations_at_limit(spec, state) ) -# Failing tests +# Tests that should fail @with_electra_and_later @with_presets([MINIMAL], "need sufficient consolidation churn limit") @@ -958,10 +958,10 @@ def test_switch_to_compounding_exited_source(spec, state): target_pubkey=state.validators[source_index].pubkey, ) - # exit source + # Initiate exit for source spec.initiate_validator_exit(state, source_index) - # Check the the return condition + # Check the return condition assert state.validators[source_index].exit_epoch != spec.FAR_FUTURE_EPOCH yield from run_switch_to_compounding_processing( @@ -985,7 +985,7 @@ def test_switch_to_compounding_inactive_source(spec, state): target_pubkey=state.validators[source_index].pubkey, ) - # set source validator as not yet activated + # Set source validator as not yet activated state.validators[source_index].activation_epoch = spec.FAR_FUTURE_EPOCH # Check the the return condition From 2dd9e82306dd4a1a9a91877b7267087b1b21d13f Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 3 Oct 2024 17:51:48 +0400 Subject: [PATCH 09/10] Remove blank lines --- .../block_processing/test_process_consolidation_request.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index cdaf786fef..b1ee7e1213 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -1100,7 +1100,6 @@ def run_consolidation_processing(spec, state, consolidation, success=True): - post-state ('post'). If ``success == False``, ``process_consolidation_request`` would return without any state change. """ - if success: validator_pubkeys = [v.pubkey for v in state.validators] source_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.source_pubkey)) @@ -1170,7 +1169,6 @@ def run_switch_to_compounding_processing(spec, state, consolidation, success=Tru - post-state ('post'). If ``success == False``, ``process_consolidation_request`` would return without any state change. """ - if success: validator_pubkeys = [v.pubkey for v in state.validators] source_index = spec.ValidatorIndex(validator_pubkeys.index(consolidation.source_pubkey)) From 66f5c3776cf9aa62e0b324c658bd3dc276a8775c Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 3 Oct 2024 17:55:39 +0400 Subject: [PATCH 10/10] Fix switch to compounding tests --- .../block_processing/test_process_consolidation_request.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py index b1ee7e1213..426f4fbe79 100644 --- a/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py +++ b/tests/core/pyspec/eth2spec/test/electra/block_processing/test_process_consolidation_request.py @@ -1003,9 +1003,8 @@ def test_switch_to_compounding_source_bls_withdrawal_credential(spec, state): # a bls withdrawal credential current_epoch = spec.get_current_epoch(state) source_index = spec.get_active_validator_indices(state, current_epoch)[0] - source_address = b"\x22" * 20 consolidation = spec.ConsolidationRequest( - source_address=source_address, + source_address=state.validators[source_index].withdrawal_credentials[12:], source_pubkey=state.validators[source_index].pubkey, target_pubkey=state.validators[source_index].pubkey, ) @@ -1026,12 +1025,12 @@ def test_switch_to_compounding_source_coumpounding_withdrawal_credential(spec, s current_epoch = spec.get_current_epoch(state) source_index = spec.get_active_validator_indices(state, current_epoch)[0] source_address = b"\x22" * 20 + set_compounding_withdrawal_credential(spec, state, source_index, address=source_address) consolidation = spec.ConsolidationRequest( source_address=source_address, source_pubkey=state.validators[source_index].pubkey, target_pubkey=state.validators[source_index].pubkey, ) - set_compounding_withdrawal_credential(spec, state, source_index) state.balances[source_index] = spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT # Check the the return condition