diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index d9c8d3557f..111dc5b970 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -99,6 +99,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) @@ -627,9 +628,8 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: ```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) + validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] + queue_excess_active_balance(state, index) ``` #### New `queue_excess_active_balance` @@ -858,9 +858,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) - # Calculate the consolidated balance max_effective_balance = get_max_effective_balance(source_validator) source_effective_balance = min(state.balances[pending_consolidation.source_index], max_effective_balance) @@ -1217,14 +1214,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` @@ -1396,6 +1385,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 has not been initiated + if source_validator.exit_epoch != FAR_FUTURE_EPOCH: + return False + + return True +``` + ###### New `process_consolidation_request` ```python @@ -1403,6 +1431,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 @@ -1423,10 +1461,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 = ( @@ -1462,6 +1496,10 @@ def process_consolidation_request( 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 b05c20f565..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 @@ -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 @@ -395,17 +495,32 @@ def test_consolidation_balance_through_two_churn_epochs(spec, state): assert state.consolidation_balance_to_consume == expected_balance -# Failing tests +@with_electra_and_later +@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] + + # 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, + ) + + 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_incorrect_source_equals_target(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] @@ -414,6 +529,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, @@ -421,13 +538,41 @@ def test_incorrect_source_equals_target(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( - spec, state, consolidation, success=False + +@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 + ) + + +# Tests that should fail @with_electra_and_later @with_presets([MINIMAL], "need sufficient consolidation churn limit") @@ -797,6 +942,155 @@ 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, + ) + + # Initiate exit for source + spec.initiate_validator_exit(state, source_index) + + # Check 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] + consolidation = spec.ConsolidationRequest( + source_address=state.validators[source_index].withdrawal_credentials[12:], + 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 + 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, + ) + 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: @@ -805,7 +1099,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)) @@ -815,6 +1108,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() @@ -826,9 +1121,10 @@ def run_consolidation_processing(spec, state, consolidation, success=True): 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) - assert spec.has_execution_withdrawal_credential(target_validator) + # Check target has compounding credentials + 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 @@ -840,11 +1136,74 @@ def run_consolidation_processing(spec, state, consolidation, success=True): 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 == ( + 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))] + else: + 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_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/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 == []