From fdb5c7dcf3ac3e051a0abeb7a2d71f99e4c767e7 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 22 Sep 2022 15:19:22 -0500 Subject: [PATCH] Add partial withdrawal balance tests --- .../test_process_bls_to_execution_change.py | 2 +- .../test_process_withdrawals.py | 2 +- .../test_process_partial_withdrawals.py | 58 +++++++++++++++++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py index 4b69e04a6..4ad1bca86 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py @@ -185,7 +185,7 @@ def test_fail_incorrect_from_bls_pubkey(spec, state): @always_bls def test_fail_bad_signature(spec, state): signed_address_change = get_signed_address_change(spec, state) - # Mutate sigature + # Mutate signature signed_address_change.signature = spec.BLSSignature(b'\x42' * 96) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False) 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 26ace24b3..4932bc60d 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 @@ -235,7 +235,7 @@ def test_fail_many_dequeued_incorrectly(spec, state): if i % 3 == 0: withdrawal.index += 1 elif i % 3 == 1: - withdrawal.address = (i).to_bytes(20, 'big') + withdrawal.address = i.to_bytes(20, 'big') else: withdrawal.amount += 1 diff --git a/tests/core/pyspec/eth2spec/test/capella/epoch_processing/test_process_partial_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/epoch_processing/test_process_partial_withdrawals.py index bf2e73fa1..431c2f2d3 100644 --- a/tests/core/pyspec/eth2spec/test/capella/epoch_processing/test_process_partial_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/epoch_processing/test_process_partial_withdrawals.py @@ -10,13 +10,18 @@ from eth2spec.test.helpers.state import next_epoch from eth2spec.test.helpers.random import randomize_state -def set_validator_partially_withdrawable(spec, state, index, rng=random.Random(666)): +def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance): validator = state.validators[index] validator.withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] - validator.effective_balance = spec.MAX_EFFECTIVE_BALANCE - state.balances[index] = spec.MAX_EFFECTIVE_BALANCE + rng.randint(1, 100000000) + validator.effective_balance = min(balance, spec.MAX_EFFECTIVE_BALANCE) + state.balances[index] = balance - assert spec.is_partially_withdrawable_validator(validator, state.balances[index]) + +def set_validator_partially_withdrawable(spec, state, index, rng=random.Random(666)): + balance = spec.MAX_EFFECTIVE_BALANCE + rng.randint(1, 100000000) + set_eth1_withdrawal_credential_with_balance(spec, state, index, balance) + + assert spec.is_partially_withdrawable_validator(state.validators[index], state.balances[index]) def run_process_partial_withdrawals(spec, state, num_expected_withdrawals=None): @@ -62,6 +67,49 @@ def test_success_no_withdrawable(spec, state): assert pre_validators == state.validators +@with_capella_and_later +@spec_state_test +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) + validator = state.validators[validator_index] + + assert validator.effective_balance < spec.MAX_EFFECTIVE_BALANCE + assert not spec.is_partially_withdrawable_validator(validator, state.balances[validator_index]) + + yield from run_process_partial_withdrawals(spec, state, 0) + + +@with_capella_and_later +@spec_state_test +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) + validator = state.validators[validator_index] + + assert validator.effective_balance == spec.MAX_EFFECTIVE_BALANCE + assert not spec.is_partially_withdrawable_validator(validator, state.balances[validator_index]) + + yield from run_process_partial_withdrawals(spec, state, 0) + + +@with_capella_and_later +@spec_state_test +def test_success_excess_balance_but_no_max_effective_balance(spec, state): + validator_index = len(state.validators) // 2 + set_validator_partially_withdrawable(spec, state, validator_index) + validator = state.validators[validator_index] + + # To be partially withdrawable, the validator needs both a maxed out effective balance and an excess balance + validator.effective_balance = spec.MAX_EFFECTIVE_BALANCE - 1 + + assert not spec.is_partially_withdrawable_validator(validator, state.balances[validator_index]) + + yield from run_process_partial_withdrawals(spec, state, 0) + + @with_capella_and_later @spec_state_test def test_success_one_partial_withdrawable(spec, state): @@ -155,7 +203,7 @@ def test_success_max_partial_withdrawable(spec, state): @with_capella_and_later -@with_presets([MINIMAL], reason="not no enough validators with mainnet config") +@with_presets([MINIMAL], reason="not enough validators with mainnet config") @spec_state_test def test_success_max_plus_one_withdrawable(spec, state): # Sanity check that this test works for this state