Add more deposit tests
This commit is contained in:
parent
97e6166bf1
commit
990de16c0f
|
@ -2,307 +2,383 @@ from eth2spec.test.context import spec_state_test, always_bls, with_electra_and_
|
||||||
from eth2spec.test.helpers.deposits import (
|
from eth2spec.test.helpers.deposits import (
|
||||||
prepare_deposit_request,
|
prepare_deposit_request,
|
||||||
run_deposit_request_processing,
|
run_deposit_request_processing,
|
||||||
run_deposit_request_processing_with_specific_fork_version
|
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.state import next_epoch_via_block
|
|
||||||
from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable
|
|
||||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
|
||||||
|
|
||||||
|
|
||||||
def run_process_pending_deposits(spec, state):
|
def _run_deposit_request_switching_to_compounding(
|
||||||
yield from run_epoch_processing_with(
|
spec,
|
||||||
spec, state, 'process_pending_deposits')
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_creds,
|
||||||
|
request_creds,
|
||||||
|
signed=True,
|
||||||
|
effective=True
|
||||||
|
):
|
||||||
|
deposit_request = prepare_deposit_request(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
# Minimal deposit amount
|
||||||
|
amount=(spec.EFFECTIVE_BALANCE_INCREMENT * 1),
|
||||||
|
withdrawal_credentials=request_creds,
|
||||||
|
signed=signed
|
||||||
|
)
|
||||||
|
state.validators[validator_index].withdrawal_credentials = initial_creds
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
deposit_request,
|
||||||
|
validator_index,
|
||||||
|
switches_to_compounding=effective
|
||||||
|
)
|
||||||
|
|
||||||
|
if effective:
|
||||||
|
# Withdrawal address must never be changed, the change applies to the type only
|
||||||
|
expected_credentials = spec.COMPOUNDING_WITHDRAWAL_PREFIX + initial_creds[1:]
|
||||||
|
assert state.validators[validator_index].withdrawal_credentials == expected_credentials
|
||||||
|
else:
|
||||||
|
assert state.validators[validator_index].withdrawal_credentials == initial_creds
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_new_deposit_under_max(spec, state):
|
def test_process_deposit_request_min_activation(spec, state):
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
# effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement.
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE - 1
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_new_deposit_max(spec, state):
|
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
validator_index = len(state.validators)
|
validator_index = len(state.validators)
|
||||||
# effective balance will be exactly the same as balance.
|
# effective balance will be exactly the same as balance.
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_new_deposit_over_max(spec, state):
|
def test_process_deposit_request_max_effective_balance_compounding(spec, state):
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
# just 1 over the limit, effective balance should be set MAX_EFFECTIVE_BALANCE during processing
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE + 1
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_new_deposit_eth1_withdrawal_credentials(spec, state):
|
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
validator_index = len(state.validators)
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
|
||||||
withdrawal_credentials = (
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
deposit_request = prepare_deposit_request(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
signed=True,
|
||||||
|
withdrawal_credentials=withdrawal_credentials
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_top_up_min_activation(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
state.validators[validator_index].effective_balance = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_top_up_max_effective_balance_compounding(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
state.validators[validator_index].withdrawal_credentials = withdrawal_credentials
|
||||||
|
|
||||||
|
deposit_request = prepare_deposit_request(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
signed=True,
|
||||||
|
withdrawal_credentials=withdrawal_credentials
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_process_deposit_request_invalid_sig(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
deposit_request = prepare_deposit_request(spec, validator_index, amount)
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_process_deposit_request_top_up_invalid_sig(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
deposit_request = prepare_deposit_request(spec, validator_index, amount)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
state.validators[validator_index].effective_balance = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_set_start_index(spec, state):
|
||||||
|
assert state.deposit_requests_start_index == spec.UNSET_DEPOSIT_REQUESTS_START_INDEX
|
||||||
|
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
assert state.deposit_requests_start_index == deposit_request.index
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_set_start_index_only_once(spec, state):
|
||||||
|
initial_start_index = 1
|
||||||
|
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
state.deposit_requests_start_index = initial_start_index
|
||||||
|
|
||||||
|
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
||||||
|
|
||||||
|
assert state.deposit_requests_start_index == initial_start_index
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_switch_to_compounding_normal(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
+ b'\x00' * 11 # specified 0s
|
+ b'\x00' * 11 # specified 0s
|
||||||
+ b'\x59' * 20 # a 20-byte eth1 address
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
)
|
)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
compounding_credentials = (
|
||||||
deposit_request = prepare_deposit_request(
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
spec,
|
spec,
|
||||||
|
state,
|
||||||
validator_index,
|
validator_index,
|
||||||
amount,
|
initial_withdrawal_credentials,
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
compounding_credentials,
|
||||||
signed=True,
|
effective=True
|
||||||
)
|
)
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_new_deposit_non_versioned_withdrawal_credentials(spec, state):
|
def test_process_deposit_request_switch_to_compounding_with_excess(spec, state):
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
withdrawal_credentials = (
|
|
||||||
b'\xFF' # Non specified withdrawal credentials version
|
|
||||||
+ b'\x02' * 31 # Garabage bytes
|
|
||||||
)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
deposit_request = prepare_deposit_request(
|
|
||||||
spec,
|
|
||||||
validator_index,
|
|
||||||
amount,
|
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
|
||||||
signed=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
@always_bls
|
|
||||||
def test_correct_sig_but_forked_state(spec, state):
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
# deposits will always be valid, regardless of the current fork
|
|
||||||
state.fork.current_version = spec.Version('0x1234abcd')
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
@always_bls
|
|
||||||
def test_incorrect_sig_new_deposit(spec, state):
|
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount)
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index, effective=False)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_top_up__max_effective_balance(spec, state):
|
|
||||||
validator_index = 0
|
validator_index = 0
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
# there is excess balace that will be enqueued to pending deposits
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
initial_balance = initial_effective_balance = (
|
||||||
|
spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT // 2)
|
||||||
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE
|
initial_withdrawal_credentials = (
|
||||||
state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
deposits_len = len(state.pending_deposits)
|
compounding_credentials = (
|
||||||
assert state.pending_deposits[deposits_len - 1].amount == amount
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_top_up__less_effective_balance(spec, state):
|
|
||||||
validator_index = 0
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
|
||||||
|
|
||||||
initial_balance = spec.MAX_EFFECTIVE_BALANCE - 1000
|
|
||||||
initial_effective_balance = spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT
|
|
||||||
state.balances[validator_index] = initial_balance
|
state.balances[validator_index] = initial_balance
|
||||||
state.validators[validator_index].effective_balance = initial_effective_balance
|
state.validators[validator_index].effective_balance = initial_effective_balance
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
|
|
||||||
deposits_len = len(state.pending_deposits)
|
|
||||||
assert state.pending_deposits[deposits_len - 1].amount == amount
|
|
||||||
# unchanged effective balance
|
|
||||||
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_top_up__zero_balance(spec, state):
|
|
||||||
validator_index = 0
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, signed=True)
|
|
||||||
|
|
||||||
initial_balance = 0
|
|
||||||
initial_effective_balance = 0
|
|
||||||
state.balances[validator_index] = initial_balance
|
|
||||||
state.validators[validator_index].effective_balance = initial_effective_balance
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
|
|
||||||
deposits_len = len(state.pending_deposits)
|
|
||||||
assert state.pending_deposits[deposits_len - 1].amount == amount
|
|
||||||
# unchanged effective balance
|
|
||||||
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
@always_bls
|
|
||||||
def test_incorrect_sig_top_up(spec, state):
|
|
||||||
validator_index = 0
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount)
|
|
||||||
|
|
||||||
# invalid signatures, in top-ups, are allowed!
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_incorrect_withdrawal_credentials_top_up(spec, state):
|
|
||||||
validator_index = 0
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
|
||||||
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:]
|
|
||||||
deposit_request = prepare_deposit_request(
|
|
||||||
spec,
|
spec,
|
||||||
|
state,
|
||||||
validator_index,
|
validator_index,
|
||||||
amount,
|
initial_withdrawal_credentials,
|
||||||
withdrawal_credentials=withdrawal_credentials
|
compounding_credentials,
|
||||||
)
|
effective=True
|
||||||
|
|
||||||
# inconsistent withdrawal credentials, in top-ups, are allowed!
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_key_validate_invalid_subgroup(spec, state):
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
|
|
||||||
# All-zero pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception.
|
|
||||||
pubkey = b'\x00' * 48
|
|
||||||
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, pubkey=pubkey, signed=True)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_key_validate_invalid_decompression(spec, state):
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
|
|
||||||
# `deserialization_fails_infinity_with_true_b_flag` BLS G1 deserialization test case.
|
|
||||||
# This pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception.
|
|
||||||
pubkey_hex = 'c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
|
||||||
pubkey = bytes.fromhex(pubkey_hex)
|
|
||||||
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, pubkey=pubkey, signed=True)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
@always_bls
|
|
||||||
def test_ineffective_deposit_with_previous_fork_version(spec, state):
|
|
||||||
# Since deposits are valid across forks, the domain is always set with `GENESIS_FORK_VERSION`.
|
|
||||||
# It's an ineffective deposit because it fails at BLS sig verification.
|
|
||||||
# NOTE: it was effective in Altair.
|
|
||||||
assert state.fork.previous_version != state.fork.current_version
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing_with_specific_fork_version(
|
|
||||||
spec,
|
|
||||||
state,
|
|
||||||
fork_version=state.fork.previous_version,
|
|
||||||
effective=False,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
@always_bls
|
def test_process_deposit_request_switch_to_compounding_incorrect_credentials(spec, state):
|
||||||
def test_effective_deposit_with_genesis_fork_version(spec, state):
|
|
||||||
assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing_with_specific_fork_version(
|
|
||||||
spec,
|
|
||||||
state,
|
|
||||||
fork_version=spec.config.GENESIS_FORK_VERSION,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_success_top_up_to_withdrawn_validator(spec, state):
|
|
||||||
validator_index = 0
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
compounding_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:]
|
||||||
|
)
|
||||||
|
|
||||||
# Fully withdraw validator
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
set_validator_fully_withdrawable(spec, state, validator_index)
|
spec,
|
||||||
assert state.balances[validator_index] > 0
|
state,
|
||||||
next_epoch_via_block(spec, state)
|
validator_index,
|
||||||
assert state.balances[validator_index] == 0
|
initial_withdrawal_credentials,
|
||||||
assert state.validators[validator_index].effective_balance > 0
|
compounding_credentials,
|
||||||
next_epoch_via_block(spec, state)
|
effective=True
|
||||||
assert state.validators[validator_index].effective_balance == 0
|
)
|
||||||
|
|
||||||
# Make a top-up balance to validator
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
|
||||||
deposit_request = prepare_deposit_request(spec, validator_index, amount, len(state.validators), signed=True)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(spec, state, deposit_request, validator_index)
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_switch_to_compounding_no_compounding(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
# credentials with ETH1 prefix
|
||||||
|
incorrect_compounding_credentials = (
|
||||||
|
b'\xFF'
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
deposits_len = len(state.pending_deposits)
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
assert state.pending_deposits[deposits_len - 1].amount == amount
|
spec,
|
||||||
assert state.validators[validator_index].effective_balance == 0
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_withdrawal_credentials,
|
||||||
|
incorrect_compounding_credentials,
|
||||||
|
effective=False
|
||||||
|
)
|
||||||
|
|
||||||
validator = state.validators[validator_index]
|
|
||||||
|
|
||||||
pending_deposits_len = len(state.pending_deposits)
|
@with_electra_and_later
|
||||||
pending_deposit = state.pending_deposits[pending_deposits_len - 1]
|
@spec_state_test
|
||||||
current_epoch = spec.get_current_epoch(state)
|
def test_process_deposit_request_switch_to_compounding_has_bls(spec, state):
|
||||||
has_execution_withdrawal = spec.has_execution_withdrawal_credential(validator)
|
validator_index = 0
|
||||||
is_withdrawable = validator.withdrawable_epoch <= current_epoch
|
initial_withdrawal_credentials = state.validators[validator_index].withdrawal_credentials.copy()
|
||||||
has_non_zero_balance = pending_deposit.amount > 0
|
compounding_credentials = (
|
||||||
# NOTE: directly compute `is_fully_withdrawable_validator` conditions here
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
# to work around how the epoch processing changed balance updates
|
+ b'\x00' * 11 # specified 0s
|
||||||
assert has_execution_withdrawal and is_withdrawable and has_non_zero_balance
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_withdrawal_credentials,
|
||||||
|
compounding_credentials,
|
||||||
|
effective=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_process_deposit_request_switch_to_compounding_invalid_sig(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
compounding_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_withdrawal_credentials,
|
||||||
|
compounding_credentials,
|
||||||
|
signed=False,
|
||||||
|
effective=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_switch_to_compounding_inactive(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
compounding_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set exit_epoch to the current epoch to make validator inactive
|
||||||
|
spec.initiate_validator_exit(state, validator_index)
|
||||||
|
state.validators[validator_index].exit_epoch = spec.get_current_epoch(state)
|
||||||
|
|
||||||
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_withdrawal_credentials,
|
||||||
|
compounding_credentials,
|
||||||
|
effective=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_process_deposit_request_switch_to_compounding_exited_and_active(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
initial_withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
compounding_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initiate exit
|
||||||
|
spec.initiate_validator_exit(state, validator_index)
|
||||||
|
|
||||||
|
yield from _run_deposit_request_switching_to_compounding(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
validator_index,
|
||||||
|
initial_withdrawal_credentials,
|
||||||
|
compounding_credentials,
|
||||||
|
effective=True
|
||||||
|
)
|
||||||
|
|
|
@ -1,264 +1,467 @@
|
||||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
spec_state_test,
|
spec_state_test,
|
||||||
with_electra_and_later,
|
with_electra_and_later,
|
||||||
|
always_bls,
|
||||||
|
)
|
||||||
|
from tests.core.pyspec.eth2spec.test.helpers.deposits import (
|
||||||
|
prepare_pending_deposit,
|
||||||
|
run_pending_deposit_applying,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
|
||||||
from tests.core.pyspec.eth2spec.test.helpers.deposits import build_deposit_data
|
|
||||||
from eth2spec.test.helpers.state import next_epoch_via_block
|
from eth2spec.test.helpers.state import next_epoch_via_block
|
||||||
|
from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable
|
||||||
|
|
||||||
def run_process_pending_deposits(spec, state):
|
|
||||||
yield from run_epoch_processing_with(
|
|
||||||
spec, state, 'process_pending_deposits')
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_apply_pending_deposit_add_validator_to_registry(spec, state):
|
def test_apply_pending_deposit_under_min_activation(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement.
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE - 1
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_min_activation(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_over_min_activation(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
# just 1 over the limit, effective balance should be set MIN_ACTIVATION_BALANCE during processing
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE + 1
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_eth1_withdrawal_credentials(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_compounding_withdrawal_credentials_under_max(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
# effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement.
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA - 1
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_compounding_withdrawal_credentials_max(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
# effective balance will be exactly the same as balance.
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_compounding_withdrawal_credentials_over_max(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
# just 1 over the limit, effective balance should be set MAX_EFFECTIVE_BALANCE_ELECTRA during processing
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA + 1
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_non_versioned_withdrawal_credentials(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
b'\xFF' # Non specified withdrawal credentials version
|
||||||
|
+ b'\x02' * 31 # Garabage bytes
|
||||||
|
)
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_non_versioned_withdrawal_credentials_over_min_activation(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
withdrawal_credentials = (
|
||||||
|
b'\xFF' # Non specified withdrawal credentials version
|
||||||
|
+ b'\x02' * 31 # Garabage bytes
|
||||||
|
)
|
||||||
|
# just 1 over the limit, effective balance should be set MIN_ACTIVATION_BALANCE during processing
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE + 1
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
signed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_apply_pending_deposit_correct_sig_but_forked_state(spec, state):
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
# deposits will always be valid, regardless of the current fork
|
||||||
|
state.fork.current_version = spec.Version('0x1234abcd')
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_apply_pending_deposit_incorrect_sig_new_deposit(spec, state):
|
||||||
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount)
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_top_up__min_activation_balance(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
state.validators[validator_index].effective_balance = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
assert state.balances[validator_index] == spec.MIN_ACTIVATION_BALANCE + amount
|
||||||
|
assert state.validators[validator_index].effective_balance == spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_top_up__min_activation_balance_compounding(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
state.validators[validator_index].withdrawal_credentials = withdrawal_credentials
|
||||||
|
state.validators[validator_index].effective_balance = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
assert state.balances[validator_index] == spec.MIN_ACTIVATION_BALANCE + amount
|
||||||
|
assert state.validators[validator_index].effective_balance == spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_top_up__max_effective_balance_compounding(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
withdrawal_credentials = (
|
||||||
|
spec.COMPOUNDING_WITHDRAWAL_PREFIX
|
||||||
|
+ b'\x00' * 11 # specified 0s
|
||||||
|
+ b'\x59' * 20 # a 20-byte eth1 address
|
||||||
|
)
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE_ELECTRA // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
|
||||||
|
state.validators[validator_index].withdrawal_credentials = withdrawal_credentials
|
||||||
|
state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
assert state.balances[validator_index] == spec.MAX_EFFECTIVE_BALANCE_ELECTRA + amount
|
||||||
|
assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE_ELECTRA
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_top_up__less_effective_balance(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
initial_balance = spec.MIN_ACTIVATION_BALANCE - 1000
|
||||||
|
initial_effective_balance = spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT
|
||||||
|
state.balances[validator_index] = initial_balance
|
||||||
|
state.validators[validator_index].effective_balance = initial_effective_balance
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
assert state.balances[validator_index] == initial_balance + amount
|
||||||
|
# unchanged effective balance
|
||||||
|
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_top_up__zero_balance(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
initial_balance = 0
|
||||||
|
initial_effective_balance = 0
|
||||||
|
state.balances[validator_index] = initial_balance
|
||||||
|
state.validators[validator_index].effective_balance = initial_effective_balance
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
assert state.balances[validator_index] == initial_balance + amount
|
||||||
|
# unchanged effective balance
|
||||||
|
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_apply_pending_deposit_incorrect_sig_top_up(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
# invalid signatures, in top-ups, are allowed!
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_incorrect_withdrawal_credentials_top_up(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:]
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index,
|
||||||
|
amount,
|
||||||
|
signed=True,
|
||||||
|
withdrawal_credentials=withdrawal_credentials
|
||||||
|
)
|
||||||
|
|
||||||
|
# inconsistent withdrawal credentials, in top-ups, are allowed!
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_key_validate_invalid_subgroup(spec, state):
|
||||||
|
validator_index = len(state.validators)
|
||||||
amount = spec.MIN_ACTIVATION_BALANCE
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
|
||||||
# select validator set outside of the mainnet preset of 256
|
# All-zero pubkey would not pass `bls.KeyValidate`, but `apply_pending_deposit` would not throw exception.
|
||||||
index = len(state.validators)
|
pubkey = b'\x00' * 48
|
||||||
withdrawal_credentials = (
|
|
||||||
spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:]
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, pubkey=pubkey, signed=True)
|
||||||
)
|
|
||||||
deposit_data = build_deposit_data(spec,
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
withdrawal_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
old_validator_count = len(state.validators)
|
|
||||||
state.pending_deposits.append(deposit)
|
|
||||||
yield from run_process_pending_deposits(spec, state)
|
|
||||||
# validator count should increase by 1
|
|
||||||
assert len(state.validators) == old_validator_count + 1
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_apply_pending_deposit_increases_balance(spec, state):
|
def test_apply_pending_deposit_key_validate_invalid_decompression(spec, state):
|
||||||
amount = 100
|
validator_index = len(state.validators)
|
||||||
# signature doesn't matter here as it's interpreted as a top-up
|
amount = spec.MIN_ACTIVATION_BALANCE
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=state.validators[0].pubkey,
|
# `deserialization_fails_infinity_with_true_b_flag` BLS G1 deserialization test case.
|
||||||
withdrawal_credentials=state.validators[0].withdrawal_credentials,
|
# This pubkey would not pass `bls.KeyValidate`, but `apply_pending_deposit` would not throw exception.
|
||||||
amount=amount,
|
pubkey_hex = 'c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
slot=spec.GENESIS_SLOT
|
pubkey = bytes.fromhex(pubkey_hex)
|
||||||
)
|
|
||||||
# run test
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, pubkey=pubkey, signed=True)
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
assert state.balances[0] == amount
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
@with_electra_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_apply_pending_deposit_switch_to_compounding(spec, state):
|
@always_bls
|
||||||
amount = 100
|
def test_apply_pending_deposit_ineffective_deposit_with_bad_fork_version(spec, state):
|
||||||
|
validator_index=len(state.validators)
|
||||||
|
fork_version=spec.Version('0xAaBbCcDd')
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index=validator_index,
|
||||||
|
amount=spec.MIN_ACTIVATION_BALANCE,
|
||||||
|
fork_version=fork_version,
|
||||||
|
signed=True
|
||||||
|
)
|
||||||
|
|
||||||
# choose a value public key that's in the validator set
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
index = 0
|
|
||||||
withdrawal_credentials = (
|
|
||||||
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX +
|
@with_electra_and_later
|
||||||
spec.hash(pubkeys[index])[1:]
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_apply_pending_deposit_with_previous_fork_version(spec, state):
|
||||||
|
# Since deposits are valid across forks, the domain is always set with `GENESIS_FORK_VERSION`.
|
||||||
|
# It's an ineffective deposit because it fails at BLS sig verification.
|
||||||
|
# NOTE: it was effective in Altair.
|
||||||
|
assert state.fork.previous_version != state.fork.current_version
|
||||||
|
|
||||||
|
validator_index=len(state.validators)
|
||||||
|
fork_version=state.fork.previous_version
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index=validator_index,
|
||||||
|
amount=spec.MIN_ACTIVATION_BALANCE,
|
||||||
|
fork_version=fork_version,
|
||||||
|
signed=True
|
||||||
)
|
)
|
||||||
compounding_credentials = (
|
|
||||||
spec.COMPOUNDING_WITHDRAWAL_PREFIX +
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
spec.hash(pubkeys[index])[1:]
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_ineffective_deposit_with_current_fork_version(spec, state):
|
||||||
|
validator_index=len(state.validators)
|
||||||
|
fork_version=state.fork.current_version
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index=validator_index,
|
||||||
|
amount=spec.MIN_ACTIVATION_BALANCE,
|
||||||
|
fork_version=fork_version,
|
||||||
|
signed=True
|
||||||
)
|
)
|
||||||
# advance the state
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=False)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_apply_pending_deposit_effective_deposit_with_genesis_fork_version(spec, state):
|
||||||
|
assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version)
|
||||||
|
|
||||||
|
validator_index=len(state.validators)
|
||||||
|
fork_version=state.fork.previous_version
|
||||||
|
pending_deposit = prepare_pending_deposit(
|
||||||
|
spec,
|
||||||
|
validator_index=validator_index,
|
||||||
|
amount=spec.MIN_ACTIVATION_BALANCE,
|
||||||
|
fork_version=spec.config.GENESIS_FORK_VERSION,
|
||||||
|
signed=True
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
@with_electra_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_apply_pending_deposit_success_top_up_to_withdrawn_validator(spec, state):
|
||||||
|
validator_index = 0
|
||||||
|
|
||||||
|
# Fully withdraw validator
|
||||||
|
set_validator_fully_withdrawable(spec, state, validator_index)
|
||||||
|
assert state.balances[validator_index] > 0
|
||||||
next_epoch_via_block(spec, state)
|
next_epoch_via_block(spec, state)
|
||||||
state.validators[index].withdrawal_credentials = withdrawal_credentials
|
assert state.balances[validator_index] == 0
|
||||||
# set validator to be exited by current epoch
|
assert state.validators[validator_index].effective_balance > 0
|
||||||
state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1
|
|
||||||
deposit_data = build_deposit_data(spec,
|
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
compounding_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=compounding_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
state.balances[index] = 0
|
|
||||||
# run test
|
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
# validator balance should increase
|
|
||||||
assert state.balances[index] == amount
|
|
||||||
current_credentials = state.validators[0].withdrawal_credentials
|
|
||||||
assert current_credentials == compounding_credentials
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_apply_pending_deposit_switch_to_compounding_no_compounding(spec, state):
|
|
||||||
amount = 100
|
|
||||||
|
|
||||||
# choose a value public key that's in the validator set
|
|
||||||
index = 0
|
|
||||||
withdrawal_credentials = (
|
|
||||||
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX +
|
|
||||||
spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
# wrong compounding
|
|
||||||
compounding_credentials = (
|
|
||||||
spec.hash(b"wrong compounding address")[:]
|
|
||||||
)
|
|
||||||
# advance the state
|
|
||||||
next_epoch_via_block(spec, state)
|
next_epoch_via_block(spec, state)
|
||||||
state.validators[index].withdrawal_credentials = withdrawal_credentials
|
assert state.validators[validator_index].effective_balance == 0
|
||||||
# set validator to be exited by current epoch
|
|
||||||
state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1
|
|
||||||
deposit_data = build_deposit_data(spec,
|
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
compounding_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=compounding_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
state.balances[index] = 0
|
|
||||||
# run test
|
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
# validator balance should increase
|
|
||||||
assert state.balances[index] == amount
|
|
||||||
current_credentials = state.validators[0].withdrawal_credentials
|
|
||||||
assert current_credentials == withdrawal_credentials
|
|
||||||
|
|
||||||
|
# Make a top-up balance to validator
|
||||||
|
amount = spec.MIN_ACTIVATION_BALANCE // 4
|
||||||
|
pending_deposit = prepare_pending_deposit(spec, validator_index, amount, signed=True)
|
||||||
|
|
||||||
@with_electra_and_later
|
yield from run_pending_deposit_applying(spec, state, pending_deposit, validator_index)
|
||||||
@spec_state_test
|
|
||||||
def test_apply_pending_deposit_switch_to_compounding_has_bls(spec, state):
|
|
||||||
amount = 100
|
|
||||||
|
|
||||||
# choose a value public key that's in the validator set
|
assert state.balances[validator_index] == amount
|
||||||
index = 0
|
assert state.validators[validator_index].effective_balance == 0
|
||||||
compounding_credentials = (
|
|
||||||
spec.COMPOUNDING_WITHDRAWAL_PREFIX +
|
|
||||||
spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
# advance the state
|
|
||||||
next_epoch_via_block(spec, state)
|
|
||||||
bls_credentials = state.validators[index].withdrawal_credentials
|
|
||||||
# set validator to be exited by current epoch
|
|
||||||
state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1
|
|
||||||
deposit_data = build_deposit_data(spec,
|
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
compounding_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=compounding_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
state.balances[index] = 0
|
|
||||||
# run test
|
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
# validator balance should increase
|
|
||||||
assert state.balances[index] == amount
|
|
||||||
current_credentials = state.validators[index].withdrawal_credentials
|
|
||||||
# does not switch to compounding
|
|
||||||
assert current_credentials == bls_credentials
|
|
||||||
|
|
||||||
|
validator = state.validators[validator_index]
|
||||||
|
balance = state.balances[validator_index]
|
||||||
|
current_epoch = spec.get_current_epoch(state)
|
||||||
|
|
||||||
@with_electra_and_later
|
assert spec.is_fully_withdrawable_validator(validator, balance, current_epoch)
|
||||||
@spec_state_test
|
|
||||||
def test_apply_pending_deposit_switch_to_compounding_invalid_sig(spec, state):
|
|
||||||
amount = 100
|
|
||||||
|
|
||||||
# choose a value public key that's in the validator set
|
|
||||||
index = 0
|
|
||||||
withdrawal_credentials = (
|
|
||||||
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX +
|
|
||||||
spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
compounding_credentials = (
|
|
||||||
spec.COMPOUNDING_WITHDRAWAL_PREFIX +
|
|
||||||
spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
# advance the state
|
|
||||||
next_epoch_via_block(spec, state)
|
|
||||||
state.validators[index].withdrawal_credentials = withdrawal_credentials
|
|
||||||
# set validator to be exited by current epoch
|
|
||||||
state.validators[index].exit_epoch = spec.get_current_epoch(state) - 1
|
|
||||||
# creates wrong signature
|
|
||||||
deposit_data = build_deposit_data(spec,
|
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
withdrawal_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=compounding_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
state.balances[index] = 0
|
|
||||||
# run test
|
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
# validator balance should increase
|
|
||||||
assert state.balances[index] == amount
|
|
||||||
current_credentials = state.validators[0].withdrawal_credentials
|
|
||||||
assert current_credentials == withdrawal_credentials
|
|
||||||
|
|
||||||
|
|
||||||
@with_electra_and_later
|
|
||||||
@spec_state_test
|
|
||||||
def test_apply_pending_deposit_switch_to_compounding_not_exited(spec, state):
|
|
||||||
amount = 100
|
|
||||||
|
|
||||||
# choose a value public key that's in the validator set
|
|
||||||
index = 0
|
|
||||||
withdrawal_credentials = (
|
|
||||||
spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
compounding_credentials = (
|
|
||||||
spec.COMPOUNDING_WITHDRAWAL_PREFIX + spec.hash(pubkeys[index])[1:]
|
|
||||||
)
|
|
||||||
state.validators[index].withdrawal_credentials = withdrawal_credentials
|
|
||||||
deposit_data = build_deposit_data(spec,
|
|
||||||
pubkeys[index],
|
|
||||||
privkeys[index],
|
|
||||||
amount,
|
|
||||||
compounding_credentials,
|
|
||||||
signed=True)
|
|
||||||
deposit = spec.PendingDeposit(
|
|
||||||
pubkey=pubkeys[index],
|
|
||||||
withdrawal_credentials=compounding_credentials,
|
|
||||||
amount=amount,
|
|
||||||
slot=spec.GENESIS_SLOT,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
)
|
|
||||||
state.balances[index] = 0
|
|
||||||
# run test
|
|
||||||
spec.apply_pending_deposit(state, deposit)
|
|
||||||
# validator balance should increase
|
|
||||||
assert state.balances[index] == amount
|
|
||||||
# make sure validator did not switch to compounding if not exited
|
|
||||||
current_credentials = state.validators[0].withdrawal_credentials
|
|
||||||
assert current_credentials == withdrawal_credentials
|
|
||||||
# postpone pending_deposit
|
|
||||||
assert len(state.pending_deposits) == 0
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from eth2spec.test.context import expect_assertion_error
|
||||||
from eth2spec.test.helpers.forks import is_post_altair, is_post_electra
|
from eth2spec.test.helpers.forks import is_post_altair, is_post_electra
|
||||||
from eth2spec.test.helpers.keys import pubkeys, privkeys
|
from eth2spec.test.helpers.keys import pubkeys, privkeys
|
||||||
from eth2spec.test.helpers.state import get_balance
|
from eth2spec.test.helpers.state import get_balance
|
||||||
|
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_to
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
|
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
|
||||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||||
|
@ -23,7 +24,7 @@ def mock_deposit(spec, state, index):
|
||||||
assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
|
assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
|
||||||
|
|
||||||
|
|
||||||
def build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, fork_version, signed=False):
|
def build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, fork_version=None, signed=False):
|
||||||
deposit_data = spec.DepositData(
|
deposit_data = spec.DepositData(
|
||||||
pubkey=pubkey,
|
pubkey=pubkey,
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
@ -276,6 +277,47 @@ def build_pending_deposit(spec, validator_index, amount,
|
||||||
pending_deposit.signature = deposit_data.signature
|
pending_deposit.signature = deposit_data.signature
|
||||||
return pending_deposit
|
return pending_deposit
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_pending_deposit(spec, validator_index, amount,
|
||||||
|
pubkey=None,
|
||||||
|
privkey=None,
|
||||||
|
withdrawal_credentials=None,
|
||||||
|
fork_version=None,
|
||||||
|
signed=False,
|
||||||
|
slot=None):
|
||||||
|
"""
|
||||||
|
Create a pending deposit for the given validator, depositing the given amount.
|
||||||
|
"""
|
||||||
|
if pubkey is None:
|
||||||
|
pubkey = pubkeys[validator_index]
|
||||||
|
|
||||||
|
if privkey is None:
|
||||||
|
privkey = privkeys[validator_index]
|
||||||
|
|
||||||
|
# insecurely use pubkey as withdrawal key if no credentials provided
|
||||||
|
if withdrawal_credentials is None:
|
||||||
|
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:]
|
||||||
|
|
||||||
|
# use GENESIS_SLOT which is always finalized if no slot provided
|
||||||
|
if slot is None:
|
||||||
|
slot = spec.GENESIS_SLOT
|
||||||
|
|
||||||
|
deposit_data = build_deposit_data(spec,
|
||||||
|
pubkey,
|
||||||
|
privkey,
|
||||||
|
amount,
|
||||||
|
withdrawal_credentials,
|
||||||
|
fork_version,
|
||||||
|
signed)
|
||||||
|
|
||||||
|
return spec.PendingDeposit(
|
||||||
|
pubkey=deposit_data.pubkey,
|
||||||
|
amount=deposit_data.amount,
|
||||||
|
withdrawal_credentials=deposit_data.withdrawal_credentials,
|
||||||
|
signature=deposit_data.signature,
|
||||||
|
slot=slot,
|
||||||
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Run processing
|
# Run processing
|
||||||
#
|
#
|
||||||
|
@ -381,14 +423,24 @@ def run_deposit_processing_with_specific_fork_version(
|
||||||
yield from run_deposit_processing(spec, state, deposit, validator_index, valid=valid, effective=effective)
|
yield from run_deposit_processing(spec, state, deposit, validator_index, valid=valid, effective=effective)
|
||||||
|
|
||||||
|
|
||||||
def run_deposit_request_processing(spec, state, deposit_request, validator_index, valid=True, effective=True):
|
def run_deposit_request_processing(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
deposit_request,
|
||||||
|
validator_index,
|
||||||
|
effective=True,
|
||||||
|
switches_to_compounding=False):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Run ``process_deposit_request``, yielding:
|
Run ``process_deposit_request``, yielding:
|
||||||
- pre-state ('pre')
|
- pre-state ('pre')
|
||||||
- deposit_request ('deposit_request')
|
- deposit_request ('deposit_request')
|
||||||
- post-state ('post').
|
- post-state ('post').
|
||||||
If ``valid == False``, run expecting ``AssertionError``
|
|
||||||
"""
|
"""
|
||||||
|
assert is_post_electra(spec)
|
||||||
|
if switches_to_compounding:
|
||||||
|
assert effective
|
||||||
|
|
||||||
pre_validator_count = len(state.validators)
|
pre_validator_count = len(state.validators)
|
||||||
pre_balance = 0
|
pre_balance = 0
|
||||||
is_top_up = False
|
is_top_up = False
|
||||||
|
@ -403,71 +455,103 @@ def run_deposit_request_processing(spec, state, deposit_request, validator_index
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
yield 'deposit_request', deposit_request
|
yield 'deposit_request', deposit_request
|
||||||
|
|
||||||
if not valid:
|
|
||||||
expect_assertion_error(lambda: spec.process_deposit_request(state, deposit_request))
|
|
||||||
yield 'post', None
|
|
||||||
return
|
|
||||||
|
|
||||||
spec.process_deposit_request(state, deposit_request)
|
spec.process_deposit_request(state, deposit_request)
|
||||||
|
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
if not effective or not bls.KeyValidate(deposit_request.pubkey):
|
# New validator is only created after the pending_deposits processing
|
||||||
|
assert len(state.validators) == pre_validator_count
|
||||||
|
assert len(state.balances) == pre_validator_count
|
||||||
|
|
||||||
|
if is_top_up:
|
||||||
|
assert state.validators[validator_index].effective_balance == pre_effective_balance
|
||||||
|
if switches_to_compounding and pre_balance > spec.MIN_ACTIVATION_BALANCE:
|
||||||
|
assert state.balances[validator_index] == spec.MIN_ACTIVATION_BALANCE
|
||||||
|
else:
|
||||||
|
assert state.balances[validator_index] == pre_balance
|
||||||
|
|
||||||
|
pending_deposit = spec.PendingDeposit(
|
||||||
|
pubkey=deposit_request.pubkey,
|
||||||
|
withdrawal_credentials=deposit_request.withdrawal_credentials,
|
||||||
|
amount=deposit_request.amount,
|
||||||
|
signature=deposit_request.signature,
|
||||||
|
slot=state.slot,
|
||||||
|
)
|
||||||
|
|
||||||
|
if switches_to_compounding and pre_balance > spec.MIN_ACTIVATION_BALANCE:
|
||||||
|
validator = state.validators[validator_index]
|
||||||
|
excess_amount = pre_balance - spec.MIN_ACTIVATION_BALANCE
|
||||||
|
pending_excess = spec.PendingDeposit(
|
||||||
|
pubkey=validator.pubkey,
|
||||||
|
withdrawal_credentials=validator.withdrawal_credentials,
|
||||||
|
amount=excess_amount,
|
||||||
|
signature=spec.bls.G2_POINT_AT_INFINITY,
|
||||||
|
slot=spec.GENESIS_SLOT,
|
||||||
|
)
|
||||||
|
assert state.pending_deposits == [pending_deposit, pending_excess]
|
||||||
|
else:
|
||||||
|
assert state.pending_deposits == [pending_deposit]
|
||||||
|
|
||||||
|
|
||||||
|
def run_pending_deposit_applying(spec, state, pending_deposit, validator_index, effective=True):
|
||||||
|
"""
|
||||||
|
Enqueue ``pending_deposit`` and run epoch processing with ``process_pending_deposits``, yielding:
|
||||||
|
- pre-state ('pre')
|
||||||
|
- post-state ('post').
|
||||||
|
"""
|
||||||
|
assert is_post_electra(spec)
|
||||||
|
|
||||||
|
# ensure the transition from eth1 bridge is complete
|
||||||
|
state.deposit_requests_start_index = state.eth1_deposit_index
|
||||||
|
|
||||||
|
# ensure there is enough churn to apply the deposit
|
||||||
|
if pending_deposit.amount > spec.get_activation_exit_churn_limit(state):
|
||||||
|
state.deposit_balance_to_consume = pending_deposit.amount - spec.get_activation_exit_churn_limit(state)
|
||||||
|
|
||||||
|
# append pending deposit
|
||||||
|
state.pending_deposits.append(pending_deposit)
|
||||||
|
|
||||||
|
# run to the very beginning of the epoch processing to avoid
|
||||||
|
# any updates to the validator registry (e.g. ejections)
|
||||||
|
run_epoch_processing_to(spec, state, "process_justification_and_finalization")
|
||||||
|
|
||||||
|
pre_validator_count = len(state.validators)
|
||||||
|
pre_balance = 0
|
||||||
|
pre_effective_balance = 0
|
||||||
|
is_top_up = False
|
||||||
|
# is a top-up
|
||||||
|
if validator_index < pre_validator_count:
|
||||||
|
is_top_up = True
|
||||||
|
pre_balance = get_balance(state, validator_index)
|
||||||
|
pre_effective_balance = state.validators[validator_index].effective_balance
|
||||||
|
|
||||||
|
yield 'pre', state
|
||||||
|
|
||||||
|
spec.process_pending_deposits(state)
|
||||||
|
|
||||||
|
yield 'post', state
|
||||||
|
|
||||||
|
if effective:
|
||||||
|
if is_top_up:
|
||||||
|
# Top-ups don't add validators
|
||||||
|
assert len(state.validators) == pre_validator_count
|
||||||
|
assert len(state.balances) == pre_validator_count
|
||||||
|
# Top-ups do not change effective balance
|
||||||
|
assert state.validators[validator_index].effective_balance == pre_effective_balance
|
||||||
|
else:
|
||||||
|
# new validator is added
|
||||||
|
assert len(state.validators) == pre_validator_count + 1
|
||||||
|
assert len(state.balances) == pre_validator_count + 1
|
||||||
|
# effective balance is set correctly
|
||||||
|
max_effective_balace = spec.get_validator_max_effective_balance(state.validators[validator_index])
|
||||||
|
effective_balance = min(max_effective_balace, pending_deposit.amount)
|
||||||
|
effective_balance -= effective_balance % spec.EFFECTIVE_BALANCE_INCREMENT
|
||||||
|
assert state.validators[validator_index].effective_balance == effective_balance
|
||||||
|
assert get_balance(state, validator_index) == pre_balance + pending_deposit.amount
|
||||||
|
else:
|
||||||
assert len(state.validators) == pre_validator_count
|
assert len(state.validators) == pre_validator_count
|
||||||
assert len(state.balances) == pre_validator_count
|
assert len(state.balances) == pre_validator_count
|
||||||
if is_top_up:
|
if is_top_up:
|
||||||
assert get_balance(state, validator_index) == pre_balance
|
assert get_balance(state, validator_index) == pre_balance
|
||||||
else:
|
|
||||||
if is_top_up:
|
|
||||||
# Top-ups do not change effective balance
|
|
||||||
assert state.validators[validator_index].effective_balance == pre_effective_balance
|
|
||||||
assert len(state.validators) == pre_validator_count
|
|
||||||
assert len(state.balances) == pre_validator_count
|
|
||||||
else:
|
|
||||||
# new validator is only created after the pending_deposits processing
|
|
||||||
assert len(state.validators) == pre_validator_count
|
|
||||||
assert len(state.balances) == pre_validator_count
|
|
||||||
|
|
||||||
assert len(state.pending_deposits) == pre_pending_deposits + 1
|
assert len(state.pending_deposits) == 0
|
||||||
assert state.pending_deposits[pre_pending_deposits].pubkey == deposit_request.pubkey
|
|
||||||
assert state.pending_deposits[
|
|
||||||
pre_pending_deposits].withdrawal_credentials == deposit_request.withdrawal_credentials
|
|
||||||
assert state.pending_deposits[pre_pending_deposits].amount == deposit_request.amount
|
|
||||||
assert state.pending_deposits[pre_pending_deposits].signature == deposit_request.signature
|
|
||||||
assert state.pending_deposits[pre_pending_deposits].slot == state.slot
|
|
||||||
|
|
||||||
|
|
||||||
def run_deposit_request_processing_with_specific_fork_version(
|
|
||||||
spec,
|
|
||||||
state,
|
|
||||||
fork_version,
|
|
||||||
valid=True,
|
|
||||||
effective=True):
|
|
||||||
validator_index = len(state.validators)
|
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
|
||||||
|
|
||||||
pubkey = pubkeys[validator_index]
|
|
||||||
privkey = privkeys[validator_index]
|
|
||||||
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:]
|
|
||||||
|
|
||||||
deposit_message = spec.DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount)
|
|
||||||
domain = spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=fork_version)
|
|
||||||
deposit_data = spec.DepositData(
|
|
||||||
pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount,
|
|
||||||
signature=bls.Sign(privkey, spec.compute_signing_root(deposit_message, domain))
|
|
||||||
)
|
|
||||||
deposit_request = spec.DepositRequest(
|
|
||||||
pubkey=deposit_data.pubkey,
|
|
||||||
withdrawal_credentials=deposit_data.withdrawal_credentials,
|
|
||||||
amount=deposit_data.amount,
|
|
||||||
signature=deposit_data.signature,
|
|
||||||
index=validator_index)
|
|
||||||
|
|
||||||
yield from run_deposit_request_processing(
|
|
||||||
spec,
|
|
||||||
state,
|
|
||||||
deposit_request,
|
|
||||||
validator_index,
|
|
||||||
valid=valid,
|
|
||||||
effective=effective
|
|
||||||
)
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ def get_process_calls(spec):
|
||||||
'charge_confirmed_header_fees', # sharding
|
'charge_confirmed_header_fees', # sharding
|
||||||
'reset_pending_headers', # sharding
|
'reset_pending_headers', # sharding
|
||||||
'process_eth1_data_reset',
|
'process_eth1_data_reset',
|
||||||
'process_pending_balance_deposits', # electra
|
'process_pending_deposits', # electra
|
||||||
'process_pending_consolidations', # electra
|
'process_pending_consolidations', # electra
|
||||||
'process_effective_balance_updates',
|
'process_effective_balance_updates',
|
||||||
'process_slashings_reset',
|
'process_slashings_reset',
|
||||||
|
@ -38,8 +38,6 @@ def get_process_calls(spec):
|
||||||
'process_sync_committee_updates', # altair
|
'process_sync_committee_updates', # altair
|
||||||
'process_full_withdrawals', # capella
|
'process_full_withdrawals', # capella
|
||||||
'process_partial_withdrawals', # capella
|
'process_partial_withdrawals', # capella
|
||||||
'process_pending_deposits', # electra
|
|
||||||
'process_pending_consolidations', # electra
|
|
||||||
# TODO: add sharding processing functions when spec stabilizes.
|
# TODO: add sharding processing functions when spec stabilizes.
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,20 @@ def run_test_effective_balance_hysteresis(spec, state, with_compounding_credenti
|
||||||
(min, min + (hys_inc * div * 2), min + (2 * inc), "exact two step balance increment"),
|
(min, min + (hys_inc * div * 2), min + (2 * inc), "exact two step balance increment"),
|
||||||
(min, min + (hys_inc * div * 2) + 1, min + (2 * inc), "over two steps, round down"),
|
(min, min + (hys_inc * div * 2) + 1, min + (2 * inc), "over two steps, round down"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if with_compounding_credentials:
|
||||||
|
min = spec.MIN_ACTIVATION_BALANCE
|
||||||
|
cases = cases + [
|
||||||
|
(min, min + (hys_inc * up), min, "bigger balance, but not high enough"),
|
||||||
|
(min, min + (hys_inc * up) + 1, min + inc, "bigger balance, high enough, but small step"),
|
||||||
|
(min, min + (hys_inc * div * 2) - 1, min + inc, "bigger balance, high enough, close to double step"),
|
||||||
|
(min, min + (hys_inc * div * 2), min + (2 * inc), "exact two step balance increment"),
|
||||||
|
(min, min + (hys_inc * div * 2) + 1, min + (2 * inc), "over two steps, round down"),
|
||||||
|
(min, min * 2 + 1, min * 2, "top up or consolidation doubling the balance"),
|
||||||
|
(min, min * 2 - 1, min * 2 - spec.EFFECTIVE_BALANCE_INCREMENT,
|
||||||
|
"top up or consolidation almost doubling the balance"),
|
||||||
|
]
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
for i, (pre_eff, bal, _, _) in enumerate(cases):
|
for i, (pre_eff, bal, _, _) in enumerate(cases):
|
||||||
assert spec.is_active_validator(state.validators[i], current_epoch)
|
assert spec.is_active_validator(state.validators[i], current_epoch)
|
||||||
|
|
Loading…
Reference in New Issue