From 4d9b5b371a27aeb4d520431b0315342d54898801 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 27 Mar 2025 16:48:51 -0700 Subject: [PATCH 1/8] Round down EB when setting validator's balance --- .../block_processing/test_process_withdrawals.py | 3 ++- .../pyspec/eth2spec/test/capella/sanity/test_blocks.py | 2 +- .../epoch_processing/test_process_registry_updates.py | 10 +++++++++- tests/core/pyspec/eth2spec/test/helpers/withdrawals.py | 4 ++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index 3a762fba3a..21c1817380 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -601,7 +601,8 @@ def test_success_no_max_effective_balance(spec, state): set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE - 1) validator = state.validators[validator_index] - assert validator.effective_balance < spec.MAX_EFFECTIVE_BALANCE + # Effective balance should be 1 increment lower than MAX_EFFECTIVE_BALANCE + assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT assert not spec.is_partially_withdrawable_validator(validator, state.balances[validator_index]) execution_payload = build_empty_execution_payload(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index 796364c802..302675b5f0 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -439,7 +439,7 @@ def test_top_up_to_fully_withdrawn_validator(spec, state): def _insert_validator(spec, state, balance): - effective_balance = balance if balance < spec.MAX_EFFECTIVE_BALANCE else spec.MAX_EFFECTIVE_BALANCE + effective_balance = balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT if balance < spec.MAX_EFFECTIVE_BALANCE else spec.MAX_EFFECTIVE_BALANCE validator_index = len(state.validators) validator = spec.Validator( pubkey=pubkeys[validator_index], diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py index df7764befd..67470c699b 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py @@ -14,7 +14,7 @@ def run_test_activation_queue_eligibility(spec, state, validator_index, balance) next_epoch(spec, state) state.balances[validator_index] = balance - state.validators[validator_index].effective_balance = balance + state.validators[validator_index].effective_balance = balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT # ready for entrance into activation queue mock_deposit(spec, state, validator_index) @@ -70,3 +70,11 @@ def test_activation_queue_eligibility__greater_than_min_activation_balance(spec, balance = spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT set_compounding_withdrawal_credential_with_balance(spec, state, index) yield from run_test_activation_queue_eligibility(spec, state, index, balance) + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__fractional_greater_than_min_activation_balance(spec, state): + index = 15 + balance = spec.MIN_ACTIVATION_BALANCE + (spec.EFFECTIVE_BALANCE_INCREMENT * 0.6) + set_compounding_withdrawal_credential_with_balance(spec, state, index) + yield from run_test_activation_queue_eligibility(spec, state, index, balance) diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index a30f56690e..f5678bba50 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -37,7 +37,7 @@ def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance=None validator = state.validators[index] validator.withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + address - validator.effective_balance = min(balance, spec.MAX_EFFECTIVE_BALANCE) + validator.effective_balance = min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE) state.balances[index] = balance @@ -104,7 +104,7 @@ def set_compounding_withdrawal_credential_with_balance(spec, state, index, if balance is None: balance = effective_balance - state.validators[index].effective_balance = effective_balance + state.validators[index].effective_balance = effective_balance - effective_balance % spec.EFFECTIVE_BALANCE_INCREMENT state.balances[index] = balance From e145e48f0f1934a3f0815d44df978f789de25249 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 27 Mar 2025 16:54:26 -0700 Subject: [PATCH 2/8] Update `run_test_activation_queue_eligibility` --- .../electra/epoch_processing/test_process_registry_updates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py index 67470c699b..67d33ca42d 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py @@ -23,7 +23,7 @@ def run_test_activation_queue_eligibility(spec, state, validator_index, balance) # validator moved into activation queue if eligible validator = state.validators[validator_index] - if validator.effective_balance < spec.MIN_ACTIVATION_BALANCE: + if validator.effective_balance <= (spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT): assert validator.activation_eligibility_epoch == spec.FAR_FUTURE_EPOCH else: assert validator.activation_eligibility_epoch < spec.FAR_FUTURE_EPOCH From 2dae6771e473026b699924ffdbad31cfffa45f0d Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:05:30 -0700 Subject: [PATCH 3/8] lint --- .../pyspec/eth2spec/test/capella/sanity/test_blocks.py | 7 ++++++- .../epoch_processing/test_process_registry_updates.py | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index 302675b5f0..f219da3a9a 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -439,7 +439,12 @@ def test_top_up_to_fully_withdrawn_validator(spec, state): def _insert_validator(spec, state, balance): - effective_balance = balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT if balance < spec.MAX_EFFECTIVE_BALANCE else spec.MAX_EFFECTIVE_BALANCE + effective_balance = ( + balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT + if balance < spec.MAX_EFFECTIVE_BALANCE + else spec.MAX_EFFECTIVE_BALANCE + ) + validator_index = len(state.validators) validator = spec.Validator( pubkey=pubkeys[validator_index], diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py index 67d33ca42d..9da161620e 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py @@ -71,6 +71,7 @@ def test_activation_queue_eligibility__greater_than_min_activation_balance(spec, set_compounding_withdrawal_credential_with_balance(spec, state, index) yield from run_test_activation_queue_eligibility(spec, state, index, balance) + @with_electra_and_later @spec_state_test def test_activation_queue_eligibility__fractional_greater_than_min_activation_balance(spec, state): From 44c2533786396a4c33e0211efb4a22c211f7d2da Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:08:09 -0700 Subject: [PATCH 4/8] Make EB configurable in set_eth1_withdrawal_credential_with_balance --- .../block_processing/test_process_withdrawals.py | 7 ++++--- .../eth2spec/test/capella/sanity/test_blocks.py | 2 +- .../test_process_consolidation_request.py | 4 ++-- .../test/electra/sanity/blocks/test_blocks.py | 4 ++-- .../pyspec/eth2spec/test/helpers/withdrawals.py | 14 ++++++++++---- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index 21c1817380..8c7f1d0fe6 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -598,10 +598,9 @@ def test_random_full_withdrawals_3(spec, state): def test_success_no_max_effective_balance(spec, state): validator_index = len(state.validators) // 2 # To be partially withdrawable, the validator's effective balance must be maxed out - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE - 1) + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, balance=spec.MAX_EFFECTIVE_BALANCE - 1) validator = state.validators[validator_index] - # Effective balance should be 1 increment lower than MAX_EFFECTIVE_BALANCE assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT assert not spec.is_partially_withdrawable_validator(validator, state.balances[validator_index]) @@ -615,7 +614,7 @@ def test_success_no_max_effective_balance(spec, state): def test_success_no_excess_balance(spec, state): validator_index = len(state.validators) // 2 # To be partially withdrawable, the validator needs an excess balance - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE) + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, balance=spec.MAX_EFFECTIVE_BALANCE) validator = state.validators[validator_index] assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE @@ -824,6 +823,7 @@ def test_partially_withdrawable_validator_legacy_max_plus_one(spec, state): set_eth1_withdrawal_credential_with_balance( spec, state, validator_index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=spec.MAX_EFFECTIVE_BALANCE + 1 ) assert spec.is_partially_withdrawable_validator( @@ -873,6 +873,7 @@ def test_partially_withdrawable_validator_legacy_max_minus_one(spec, state): set_eth1_withdrawal_credential_with_balance( spec, state, validator_index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, balance=spec.MAX_EFFECTIVE_BALANCE - 1 ) assert not spec.is_partially_withdrawable_validator( diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index f219da3a9a..92878d9495 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -351,7 +351,7 @@ def test_top_up_and_partial_withdrawable_validator(spec, state): next_withdrawal_validator_index = 0 validator_index = next_withdrawal_validator_index + 1 - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE) + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, balance=spec.MAX_EFFECTIVE_BALANCE) validator = state.validators[validator_index] balance = state.balances[validator_index] assert not spec.is_partially_withdrawable_validator(validator, balance) 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 e12bad541f..23ee1c9911 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 @@ -1079,7 +1079,7 @@ def test_incorrect_source_has_pending_withdrawal(spec, state): source_address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT // 4 set_eth1_withdrawal_credential_with_balance( - spec, state, source_index, address=source_address, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance + spec, state, source_index, address=source_address, effective_balance=spec.MIN_ACTIVATION_BALANCE, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance ) consolidation = spec.ConsolidationRequest( source_address=source_address, @@ -1118,7 +1118,7 @@ def test_incorrect_source_not_active_long_enough(spec, state): source_address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT // 4 set_eth1_withdrawal_credential_with_balance( - spec, state, source_index, address=source_address, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance + spec, state, source_index, address=source_address, effective_balance=spec.MIN_ACTIVATION_BALANCE, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance ) consolidation = spec.ConsolidationRequest( source_address=source_address, diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 64bb633369..a08f92f0ec 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -264,7 +264,7 @@ def test_withdrawal_and_withdrawal_request_same_validator(spec, state): excess_balance = 200000 balance = spec.MAX_EFFECTIVE_BALANCE + excess_balance address = b'\x22' * 20 - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, balance, address) + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=balance, address=address) # Ensure the validator has an upcoming withdrawal # This will happen before the withdrawal request @@ -301,7 +301,7 @@ def test_withdrawal_and_switch_to_compounding_request_same_validator(spec, state excess_balance = 200000 balance = spec.MAX_EFFECTIVE_BALANCE + excess_balance address = b'\x22' * 20 - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, balance, address) + set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=balance, address=address) # Ensure the validator has an upcoming withdrawal # This will happen before the withdrawal request diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index f5678bba50..dd16099eb9 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -29,15 +29,21 @@ def set_validator_fully_withdrawable(spec, state, index, withdrawable_epoch=None assert spec.is_fully_withdrawable_validator(validator, state.balances[index], withdrawable_epoch) -def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance=None, address=None): - if balance is None: +def set_eth1_withdrawal_credential_with_balance(spec, state, index, effective_balance=None, balance=None, address=None): + if balance is None and effective_balance is None: balance = spec.MAX_EFFECTIVE_BALANCE + effective_balance = spec.MAX_EFFECTIVE_BALANCE + elif balance is None: + balance = effective_balance + elif effective_balance is None: + effective_balance = min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE) + if address is None: address = b'\x11' * 20 validator = state.validators[index] validator.withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + address - validator.effective_balance = min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE) + validator.effective_balance = effective_balance state.balances[index] = balance @@ -47,7 +53,7 @@ def set_validator_partially_withdrawable(spec, state, index, excess_balance=1000 validator.effective_balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA state.balances[index] = validator.effective_balance + excess_balance else: - set_eth1_withdrawal_credential_with_balance(spec, state, index, spec.MAX_EFFECTIVE_BALANCE + excess_balance) + set_eth1_withdrawal_credential_with_balance(spec, state, index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=spec.MAX_EFFECTIVE_BALANCE + excess_balance) assert spec.is_partially_withdrawable_validator(state.validators[index], state.balances[index]) From 9b34fe5b63b0a3baf0b766115c6c2eda6e32e43e Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:21:22 -0700 Subject: [PATCH 5/8] Lint --- .../test_process_withdrawals.py | 8 +++++++- .../test_process_consolidation_request.py | 14 ++++++++++++-- .../test/electra/sanity/blocks/test_blocks.py | 18 ++++++++++++++++-- .../eth2spec/test/helpers/withdrawals.py | 8 +++++++- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index 8c7f1d0fe6..c880d7e960 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -598,7 +598,13 @@ def test_random_full_withdrawals_3(spec, state): def test_success_no_max_effective_balance(spec, state): validator_index = len(state.validators) // 2 # To be partially withdrawable, the validator's effective balance must be maxed out - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, balance=spec.MAX_EFFECTIVE_BALANCE - 1) + set_eth1_withdrawal_credential_with_balance( + spec, + state, + validator_index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, + balance=spec.MAX_EFFECTIVE_BALANCE - 1, + ) validator = state.validators[validator_index] assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT 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 23ee1c9911..6da362fae2 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 @@ -1079,7 +1079,12 @@ def test_incorrect_source_has_pending_withdrawal(spec, state): source_address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT // 4 set_eth1_withdrawal_credential_with_balance( - spec, state, source_index, address=source_address, effective_balance=spec.MIN_ACTIVATION_BALANCE, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance + spec, + state, + source_index, + address=source_address, + effective_balance=spec.MIN_ACTIVATION_BALANCE, + balance=spec.MIN_ACTIVATION_BALANCE + excess_balance, ) consolidation = spec.ConsolidationRequest( source_address=source_address, @@ -1118,7 +1123,12 @@ def test_incorrect_source_not_active_long_enough(spec, state): source_address = b"\x22" * 20 excess_balance = spec.EFFECTIVE_BALANCE_INCREMENT // 4 set_eth1_withdrawal_credential_with_balance( - spec, state, source_index, address=source_address, effective_balance=spec.MIN_ACTIVATION_BALANCE, balance=spec.MIN_ACTIVATION_BALANCE + excess_balance + spec, + state, + source_index, + address=source_address, + effective_balance=spec.MIN_ACTIVATION_BALANCE, + balance=spec.MIN_ACTIVATION_BALANCE + excess_balance, ) consolidation = spec.ConsolidationRequest( source_address=source_address, diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index a08f92f0ec..0c7e9b8ea6 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -264,7 +264,14 @@ def test_withdrawal_and_withdrawal_request_same_validator(spec, state): excess_balance = 200000 balance = spec.MAX_EFFECTIVE_BALANCE + excess_balance address = b'\x22' * 20 - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=balance, address=address) + set_eth1_withdrawal_credential_with_balance( + spec, + state, + validator_index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE, + balance=balance, + address=address, + ) # Ensure the validator has an upcoming withdrawal # This will happen before the withdrawal request @@ -301,7 +308,14 @@ def test_withdrawal_and_switch_to_compounding_request_same_validator(spec, state excess_balance = 200000 balance = spec.MAX_EFFECTIVE_BALANCE + excess_balance address = b'\x22' * 20 - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=balance, address=address) + set_eth1_withdrawal_credential_with_balance( + spec, + state, + validator_index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE, + balance=balance, + address=address, + ) # Ensure the validator has an upcoming withdrawal # This will happen before the withdrawal request diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index dd16099eb9..7ba39cd182 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -53,7 +53,13 @@ def set_validator_partially_withdrawable(spec, state, index, excess_balance=1000 validator.effective_balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA state.balances[index] = validator.effective_balance + excess_balance else: - set_eth1_withdrawal_credential_with_balance(spec, state, index, effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=spec.MAX_EFFECTIVE_BALANCE + excess_balance) + set_eth1_withdrawal_credential_with_balance( + spec, + state, + index, + effective_balance=spec.MAX_EFFECTIVE_BALANCE, + balance=spec.MAX_EFFECTIVE_BALANCE + excess_balance, + ) assert spec.is_partially_withdrawable_validator(state.validators[index], state.balances[index]) From caecb3e10d1a9ffb4e0ce88d8b4f66664f6be335 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 31 Mar 2025 10:59:52 -0500 Subject: [PATCH 6/8] Fix some nits --- .../test_process_withdrawals.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index c880d7e960..710257666d 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -602,8 +602,10 @@ def test_success_no_max_effective_balance(spec, state): spec, state, validator_index, + # Reduce validator's effective balance to make it ineligible for withdrawals effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, - balance=spec.MAX_EFFECTIVE_BALANCE - 1, + # Give the validator an excess balance, so this isn't the reason it fails + balance=spec.MAX_EFFECTIVE_BALANCE + 1, ) validator = state.validators[validator_index] @@ -620,7 +622,15 @@ def test_success_no_max_effective_balance(spec, state): def test_success_no_excess_balance(spec, state): validator_index = len(state.validators) // 2 # To be partially withdrawable, the validator needs an excess balance - set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, balance=spec.MAX_EFFECTIVE_BALANCE) + set_eth1_withdrawal_credential_with_balance( + spec, + state, + validator_index, + # Ensure validator has the required effective balance, so this isn't the reason it fails + effective_balance=spec.MAX_EFFECTIVE_BALANCE, + # Remove validator's excess balance to make it ineligible for withdrawals + balance=spec.MAX_EFFECTIVE_BALANCE, + ) validator = state.validators[validator_index] assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE @@ -879,7 +889,8 @@ def test_partially_withdrawable_validator_legacy_max_minus_one(spec, state): set_eth1_withdrawal_credential_with_balance( spec, state, validator_index, - effective_balance=spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT, + # Assume effective balance updates haven't happened yet + effective_balance=spec.MAX_EFFECTIVE_BALANCE, balance=spec.MAX_EFFECTIVE_BALANCE - 1 ) assert not spec.is_partially_withdrawable_validator( From 137d0239295d8a372d0d2b57b8bcbd403162f9c2 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 31 Mar 2025 11:17:30 -0500 Subject: [PATCH 7/8] Remove new test unrelated to PR fix --- .../epoch_processing/test_process_registry_updates.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py index 9da161620e..14b4b20a00 100644 --- a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py @@ -70,12 +70,3 @@ def test_activation_queue_eligibility__greater_than_min_activation_balance(spec, balance = spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT set_compounding_withdrawal_credential_with_balance(spec, state, index) yield from run_test_activation_queue_eligibility(spec, state, index, balance) - - -@with_electra_and_later -@spec_state_test -def test_activation_queue_eligibility__fractional_greater_than_min_activation_balance(spec, state): - index = 15 - balance = spec.MIN_ACTIVATION_BALANCE + (spec.EFFECTIVE_BALANCE_INCREMENT * 0.6) - set_compounding_withdrawal_credential_with_balance(spec, state, index) - yield from run_test_activation_queue_eligibility(spec, state, index, balance) From ea19632ec212cd61cdc286949a56e42f600bcdfa Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 31 Mar 2025 11:43:44 -0500 Subject: [PATCH 8/8] Do the same thing for compounding validators --- .../pyspec/eth2spec/test/helpers/withdrawals.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index 7ba39cd182..7909b1abdf 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -36,7 +36,10 @@ def set_eth1_withdrawal_credential_with_balance(spec, state, index, effective_ba elif balance is None: balance = effective_balance elif effective_balance is None: - effective_balance = min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE) + effective_balance = min( + balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, + spec.MAX_EFFECTIVE_BALANCE + ) if address is None: address = b'\x11' * 20 @@ -111,12 +114,18 @@ def set_compounding_withdrawal_credential_with_balance(spec, state, index, effective_balance=None, balance=None, address=None): set_compounding_withdrawal_credential(spec, state, index, address) - if effective_balance is None: + if balance is None and effective_balance is None: + balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA effective_balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA - if balance is None: + elif balance is None: balance = effective_balance + elif effective_balance is None: + effective_balance = min( + balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, + spec.MAX_EFFECTIVE_BALANCE_ELECTRA + ) - state.validators[index].effective_balance = effective_balance - effective_balance % spec.EFFECTIVE_BALANCE_INCREMENT + state.validators[index].effective_balance = effective_balance state.balances[index] = balance