mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-01-20 15:38:55 +00:00
fix/add tests for process_execution_layer_withdraw_request
This commit is contained in:
parent
97507b63c0
commit
7a0bf5cea2
@ -10,6 +10,7 @@ from eth2spec.test.helpers.state import (
|
||||
)
|
||||
from eth2spec.test.helpers.withdrawals import (
|
||||
set_eth1_withdrawal_credential_with_balance,
|
||||
set_compounding_withdrawal_credential,
|
||||
)
|
||||
|
||||
|
||||
@ -33,11 +34,38 @@ def test_basic_exit(spec, state):
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=0,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(spec, state, execution_layer_withdraw_request)
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MINIMAL], "need full partial withdrawal queue")
|
||||
def test_basic_exit_with_full_partial_withdrawal_queue(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
# Fill the partial withdrawal queue to the max (with a different validator index)
|
||||
partial_withdrawal = spec.PendingPartialWithdrawal(index=1, amount=1, withdrawable_epoch=current_epoch)
|
||||
state.pending_partial_withdrawals = [partial_withdrawal] * spec.PENDING_PARTIAL_WITHDRAWALS_LIMIT
|
||||
|
||||
# Exit should still be processed
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request,
|
||||
)
|
||||
|
||||
|
||||
# Invalid tests
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
@ -54,7 +82,7 @@ def test_incorrect_source_address(spec, state):
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=incorrect_address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=0,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
@ -81,7 +109,7 @@ def test_incorrect_withdrawal_credential_prefix(spec, state):
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=0,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
@ -105,7 +133,7 @@ def test_on_exit_initiated_validator(spec, state):
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=0,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
@ -124,7 +152,7 @@ def test_activation_epoch_less_than_shard_committee_period(spec, state):
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=0,
|
||||
amount=spec.FULL_EXIT_REQUEST_AMOUNT,
|
||||
)
|
||||
|
||||
assert spec.get_current_epoch(state) < (
|
||||
@ -136,31 +164,163 @@ def test_activation_epoch_less_than_shard_committee_period(spec, state):
|
||||
)
|
||||
|
||||
|
||||
|
||||
# Partial withdrawals tests
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MINIMAL])
|
||||
def test_basic_partial_withdrawal_request(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Ensure that the validator has sufficient excess balance
|
||||
state.balances[validator_index] += 2*amount
|
||||
|
||||
set_compounding_withdrawal_credential(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request,
|
||||
)
|
||||
|
||||
# Check that the assigned exit epoch is correct
|
||||
assert state.earliest_exit_epoch == spec.compute_activation_exit_epoch(current_epoch)
|
||||
|
||||
|
||||
# Invalid partial withdrawal tests
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MINIMAL], "need full partial withdrawal queue")
|
||||
def test_partial_withdrawal_queue_full(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Ensure that the validator has sufficient excess balance
|
||||
state.balances[validator_index] += 2*amount
|
||||
set_compounding_withdrawal_credential(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=10 ** 9,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
partial_withdrawal = spec.PendingPartialWithdrawal(index=0, amount=1, withdrawable_epoch=current_epoch)
|
||||
# Fill the partial withdrawal queue to the max
|
||||
partial_withdrawal = spec.PendingPartialWithdrawal(index=1, amount=1, withdrawable_epoch=current_epoch)
|
||||
state.pending_partial_withdrawals = [partial_withdrawal] * spec.PENDING_PARTIAL_WITHDRAWALS_LIMIT
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request, success=False
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_no_compounding_credentials(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Ensure that the validator has sufficient excess balance
|
||||
state.balances[validator_index] += 2*amount
|
||||
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request, success=False,
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_no_excess_balance(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
|
||||
set_compounding_withdrawal_credential(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request, success=False
|
||||
)
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_pending_withdrawals_consume_all_excess_balance(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Add excess balance
|
||||
state.balances[validator_index] += 10 * amount
|
||||
|
||||
set_compounding_withdrawal_credential(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
# Add pending withdrawals totalling an amount equal to the excess balance
|
||||
partial_withdrawal = spec.PendingPartialWithdrawal(index=validator_index,
|
||||
amount=amount,
|
||||
withdrawable_epoch=current_epoch)
|
||||
state.pending_partial_withdrawals = [partial_withdrawal] * 10
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request, success=False
|
||||
)
|
||||
|
||||
@with_eip7251_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_insufficient_effective_balance(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
validator_pubkey = state.validators[validator_index].pubkey
|
||||
address = b'\x22' * 20
|
||||
amount = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Make effective balance insufficient
|
||||
state.validators[validator_index].effective_balance -= spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
|
||||
set_compounding_withdrawal_credential(spec, state, validator_index, address=address)
|
||||
execution_layer_withdraw_request = spec.ExecutionLayerWithdrawRequest(
|
||||
source_address=address,
|
||||
validator_pubkey=validator_pubkey,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_withdraw_request_processing(
|
||||
spec, state, execution_layer_withdraw_request, success=False,
|
||||
)
|
||||
|
||||
#
|
||||
# Run processing
|
||||
#
|
||||
@ -188,26 +348,41 @@ def run_execution_layer_withdraw_request_processing(
|
||||
return
|
||||
|
||||
pre_exit_epoch = state.validators[validator_index].exit_epoch
|
||||
pre_pending_partial_withdrawals = state.pending_partial_withdrawals
|
||||
pre_pending_partial_withdrawals = state.pending_partial_withdrawals.copy()
|
||||
pre_balance = state.balances[validator_index]
|
||||
|
||||
spec.process_execution_layer_withdraw_request(state, execution_layer_withdraw_request)
|
||||
|
||||
yield 'post', state
|
||||
|
||||
if execution_layer_withdraw_request.amount == 0:
|
||||
# Full exit request
|
||||
if execution_layer_withdraw_request.amount == spec.FULL_EXIT_REQUEST_AMOUNT:
|
||||
if success:
|
||||
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert spec.get_pending_balance_to_withdraw(state, validator_index) == 0
|
||||
else:
|
||||
assert state.validators[validator_index].exit_epoch == pre_exit_epoch
|
||||
assert state.pending_partial_withdrawals == pre_pending_partial_withdrawals
|
||||
# Partial withdrawal request
|
||||
else:
|
||||
if success:
|
||||
assert state.validators[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
assert state.balances[validator_index] == pre_balance
|
||||
post_length = len(state.pending_partial_withdrawals)
|
||||
assert post_length == len(pre_pending_partial_withdrawals) + 1
|
||||
assert post_length < spec.PENDING_PARTIAL_WITHDRAWALS_LIMIT
|
||||
assert state.pending_partial_withdrawals[post_length - 1].validator_index == validator_index
|
||||
expected_amount = compute_amount_to_withdraw(spec, state, validator_index, execution_layer_withdraw_request.amount)
|
||||
expected_withdrawable_epoch = state.earliest_exit_epoch + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||
expected_partial_withdrawal = spec.PendingPartialWithdrawal(index=validator_index,
|
||||
amount=expected_amount,
|
||||
withdrawable_epoch=expected_withdrawable_epoch)
|
||||
assert state.pending_partial_withdrawals == pre_pending_partial_withdrawals + [expected_partial_withdrawal]
|
||||
|
||||
else:
|
||||
assert state.pending_partial_withdrawals == pre_pending_partial_withdrawals
|
||||
|
||||
|
||||
def compute_amount_to_withdraw(spec, state, index, amount):
|
||||
pending_balance_to_withdraw = spec.get_pending_balance_to_withdraw(state, index)
|
||||
return min(
|
||||
state.balances[index] - spec.MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw,
|
||||
amount
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user