From 99f82e76b426b4973196de0706d6559359e1d75f Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Wed, 27 Nov 2024 13:03:06 +0600 Subject: [PATCH 1/2] Add pending deposit and consolidation tests --- .../test/electra/sanity/test_slots.py | 125 ++++++++++++++++++ tests/generators/sanity/main.py | 1 + 2 files changed, 126 insertions(+) create mode 100644 tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py b/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py new file mode 100644 index 0000000000..89f88ee4b3 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py @@ -0,0 +1,125 @@ +from eth2spec.test.context import ( + spec_state_test, + with_electra_and_later, +) +from eth2spec.test.helpers.deposits import prepare_pending_deposit +from eth2spec.test.helpers.state import transition_to + + +def run_epoch_processing(spec, state, pending_deposits=[], pending_consolidations=[]): + # Transition to the last slot of the epoch + slot = state.slot + spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - 1 + transition_to(spec, state, slot) + state.pending_deposits = pending_deposits + state.pending_consolidations = pending_consolidations + yield 'pre', state + yield 'slots', 1 + spec.process_slots(state, state.slot + 1) + yield 'post', state + + assert state.pending_deposits == [] + assert state.pending_consolidations == [] + + +@with_electra_and_later +@spec_state_test +def test_multiple_pending_deposits_same_pubkey(spec, state): + # Create multiple deposits with the same pubkey + index = len(state.validators) + deposit = prepare_pending_deposit(spec, validator_index=index, amount=spec.MIN_ACTIVATION_BALANCE, signed=True) + pending_deposits = [deposit, deposit] + + yield from run_epoch_processing(spec, state, pending_deposits) + + # Check deposit balance is applied correctly + assert state.balances[index] == sum(d.amount for d in pending_deposits) + assert state.validators[index].effective_balance == spec.MIN_ACTIVATION_BALANCE + + +@with_electra_and_later +@spec_state_test +def test_multiple_pending_deposits_same_pubkey_compounding(spec, state): + # Create multiple deposits with the same pubkey and compounding creds + index = len(state.validators) + deposit = prepare_pending_deposit( + spec, validator_index=index, amount=spec.MIN_ACTIVATION_BALANCE, signed=True, + withdrawal_credentials=(spec.COMPOUNDING_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x11' * 20) + ) + pending_deposits = [deposit, deposit] + + yield from run_epoch_processing(spec, state, pending_deposits) + + # Check deposit balance is applied correctly + assert state.balances[index] == sum(d.amount for d in pending_deposits) + assert state.validators[index].effective_balance == state.balances[index] + + +@with_electra_and_later +@spec_state_test +def test_multiple_pending_deposits_same_pubkey_below_upward_threshold(spec, state): + # Create multiple deposits with top up lower than the upward threshold + index = len(state.validators) + deposit_0 = prepare_pending_deposit( + spec, validator_index=index, + amount=(spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT), signed=True + ) + deposit_1 = prepare_pending_deposit( + spec, validator_index=index, + amount=spec.EFFECTIVE_BALANCE_INCREMENT, signed=True + ) + pending_deposits = [deposit_0, deposit_1] + + yield from run_epoch_processing(spec, state, pending_deposits) + + # Check deposit balance is applied correctly + assert state.balances[index] == sum(d.amount for d in pending_deposits) + assert state.validators[index].effective_balance == deposit_0.amount + + +@with_electra_and_later +@spec_state_test +def test_multiple_pending_deposits_same_pubkey_above_upward_threshold(spec, state): + # Create multiple deposits with top up greater than the upward threshold + index = len(state.validators) + deposit_0 = prepare_pending_deposit( + spec, validator_index=index, + amount=(spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT), signed=True + ) + amount = spec.EFFECTIVE_BALANCE_INCREMENT // spec.HYSTERESIS_QUOTIENT * spec.HYSTERESIS_UPWARD_MULTIPLIER + 1 + deposit_1 = prepare_pending_deposit(spec, validator_index=index, amount=amount, signed=True) + pending_deposits = [deposit_0, deposit_1] + + yield from run_epoch_processing(spec, state, pending_deposits) + + # Check deposit balance is applied correctly + balance = state.balances[index] + assert balance == sum(d.amount for d in pending_deposits) + assert state.validators[index].effective_balance == balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT + + +@with_electra_and_later +@spec_state_test +def test_pending_consolidation(spec, state): + # Create pending consolidation + 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 withdrawable epoch to current epoch to allow processing + state.validators[source_index].withdrawable_epoch = current_epoch + # Set the source withdrawal credential to eth1 + state.validators[target_index].withdrawal_credentials = ( + spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b"\x00" * 11 + b"\x11" * 20 + ) + # Set the target withdrawal credential to compounding + state.validators[target_index].withdrawal_credentials = ( + spec.COMPOUNDING_WITHDRAWAL_PREFIX + b"\x00" * 11 + b"\x11" * 20 + ) + pending_consolidations = [spec.PendingConsolidation(source_index=source_index, target_index=target_index)] + + yield from run_epoch_processing(spec, state, pending_consolidations=pending_consolidations) + + # Check the consolidation is processed correctly + assert state.balances[source_index] == 0 + assert state.validators[source_index].effective_balance == 0 + assert state.balances[target_index] == spec.MIN_ACTIVATION_BALANCE * 2 + assert state.validators[target_index].effective_balance == spec.MIN_ACTIVATION_BALANCE * 2 diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 8039b82a44..2145146856 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -33,6 +33,7 @@ # do not forget to update sanity/block/__init__.py accordingly. _new_electra_mods = {key: 'eth2spec.test.electra.sanity.' + key for key in [ 'blocks', + 'slots', ]} electra_mods = combine_mods(_new_electra_mods, deneb_mods) From d2072df41df48fc4b010e5275f3c2191946f814d Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 28 Nov 2024 23:54:28 +0800 Subject: [PATCH 2/2] minor suggestions --- .../eth2spec/test/electra/sanity/test_slots.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py b/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py index 89f88ee4b3..9ea506392b 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/test_slots.py @@ -6,7 +6,11 @@ from eth2spec.test.helpers.state import transition_to -def run_epoch_processing(spec, state, pending_deposits=[], pending_consolidations=[]): +def run_epoch_processing(spec, state, pending_deposits=None, pending_consolidations=None): + if pending_deposits is None: + pending_deposits = [] + if pending_consolidations is None: + pending_consolidations = [] # Transition to the last slot of the epoch slot = state.slot + spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - 1 transition_to(spec, state, slot) @@ -29,7 +33,7 @@ def test_multiple_pending_deposits_same_pubkey(spec, state): deposit = prepare_pending_deposit(spec, validator_index=index, amount=spec.MIN_ACTIVATION_BALANCE, signed=True) pending_deposits = [deposit, deposit] - yield from run_epoch_processing(spec, state, pending_deposits) + yield from run_epoch_processing(spec, state, pending_deposits=pending_deposits) # Check deposit balance is applied correctly assert state.balances[index] == sum(d.amount for d in pending_deposits) @@ -47,7 +51,7 @@ def test_multiple_pending_deposits_same_pubkey_compounding(spec, state): ) pending_deposits = [deposit, deposit] - yield from run_epoch_processing(spec, state, pending_deposits) + yield from run_epoch_processing(spec, state, pending_deposits=pending_deposits) # Check deposit balance is applied correctly assert state.balances[index] == sum(d.amount for d in pending_deposits) @@ -69,7 +73,7 @@ def test_multiple_pending_deposits_same_pubkey_below_upward_threshold(spec, stat ) pending_deposits = [deposit_0, deposit_1] - yield from run_epoch_processing(spec, state, pending_deposits) + yield from run_epoch_processing(spec, state, pending_deposits=pending_deposits) # Check deposit balance is applied correctly assert state.balances[index] == sum(d.amount for d in pending_deposits) @@ -116,6 +120,11 @@ def test_pending_consolidation(spec, state): ) pending_consolidations = [spec.PendingConsolidation(source_index=source_index, target_index=target_index)] + assert state.balances[source_index] == spec.MIN_ACTIVATION_BALANCE + assert state.validators[source_index].effective_balance == spec.MIN_ACTIVATION_BALANCE + assert state.balances[target_index] == spec.MIN_ACTIVATION_BALANCE + assert state.validators[target_index].effective_balance == spec.MIN_ACTIVATION_BALANCE + yield from run_epoch_processing(spec, state, pending_consolidations=pending_consolidations) # Check the consolidation is processed correctly