mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-09 09:14:32 +00:00
Merge pull request #3979 from mkalinin/more-withdrawal-tests
eip7251: Bugfix and more withdrawal tests
This commit is contained in:
commit
c060147812
@ -1059,7 +1059,7 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],
|
||||
withdrawal_index = state.next_withdrawal_index
|
||||
validator_index = state.next_withdrawal_validator_index
|
||||
withdrawals: List[Withdrawal] = []
|
||||
partial_withdrawals_count = 0
|
||||
processed_partial_withdrawals_count = 0
|
||||
|
||||
# [New in Electra:EIP7251] Consume pending partial withdrawals
|
||||
for withdrawal in state.pending_partial_withdrawals:
|
||||
@ -1079,13 +1079,16 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],
|
||||
))
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
|
||||
partial_withdrawals_count += 1
|
||||
processed_partial_withdrawals_count += 1
|
||||
|
||||
# Sweep for remaining.
|
||||
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
for _ in range(bound):
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
# [Modified in Electra:EIP7251]
|
||||
partially_withdrawn_balance = sum(
|
||||
withdrawal.amount for withdrawal in withdrawals if withdrawal.validator_index == validator_index)
|
||||
balance = state.balances[validator_index] - partially_withdrawn_balance
|
||||
if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
withdrawals.append(Withdrawal(
|
||||
index=withdrawal_index,
|
||||
@ -1105,7 +1108,7 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],
|
||||
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
break
|
||||
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
return withdrawals, partial_withdrawals_count
|
||||
return withdrawals, processed_partial_withdrawals_count
|
||||
```
|
||||
|
||||
##### Modified `process_withdrawals`
|
||||
@ -1114,7 +1117,8 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],
|
||||
|
||||
```python
|
||||
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
expected_withdrawals, partial_withdrawals_count = get_expected_withdrawals(state) # [Modified in Electra:EIP7251]
|
||||
# [Modified in Electra:EIP7251]
|
||||
expected_withdrawals, processed_partial_withdrawals_count = get_expected_withdrawals(state)
|
||||
|
||||
assert payload.withdrawals == expected_withdrawals
|
||||
|
||||
@ -1122,7 +1126,7 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
||||
|
||||
# Update pending partial withdrawals [New in Electra:EIP7251]
|
||||
state.pending_partial_withdrawals = state.pending_partial_withdrawals[partial_withdrawals_count:]
|
||||
state.pending_partial_withdrawals = state.pending_partial_withdrawals[processed_partial_withdrawals_count:]
|
||||
|
||||
# Update the next withdrawal index if this block contained withdrawals
|
||||
if len(expected_withdrawals) != 0:
|
||||
|
@ -11,7 +11,7 @@ from eth2spec.test.helpers.state import (
|
||||
next_slot,
|
||||
)
|
||||
from eth2spec.test.helpers.withdrawals import (
|
||||
prepare_expected_withdrawals_compounding,
|
||||
prepare_expected_withdrawals,
|
||||
run_withdrawals_processing,
|
||||
set_compounding_withdrawal_credential_with_balance,
|
||||
prepare_pending_withdrawal,
|
||||
@ -23,11 +23,11 @@ from eth2spec.test.helpers.withdrawals import (
|
||||
def test_success_mixed_fully_and_partial_withdrawable_compounding(spec, state):
|
||||
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2
|
||||
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD - num_full_withdrawals
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals_compounding(
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
spec, state,
|
||||
rng=random.Random(42),
|
||||
num_full_withdrawals=num_full_withdrawals,
|
||||
num_partial_withdrawals_sweep=num_partial_withdrawals,
|
||||
num_full_withdrawals_comp=num_full_withdrawals,
|
||||
num_partial_withdrawals_comp=num_partial_withdrawals,
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
@ -94,14 +94,351 @@ def test_pending_withdrawals_one_skipped_one_effective(spec, state):
|
||||
index_0 = 3
|
||||
index_1 = 5
|
||||
|
||||
withdrawal_0 = prepare_pending_withdrawal(spec, state, index_0)
|
||||
withdrawal_1 = prepare_pending_withdrawal(spec, state, index_1)
|
||||
pending_withdrawal_0 = prepare_pending_withdrawal(spec, state, index_0)
|
||||
pending_withdrawal_1 = prepare_pending_withdrawal(spec, state, index_1)
|
||||
|
||||
# If validator doesn't have an excess balance pending withdrawal is skipped
|
||||
state.balances[index_0] = spec.MIN_ACTIVATION_BALANCE
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
assert state.pending_partial_withdrawals == [withdrawal_0, withdrawal_1]
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
assert state.pending_partial_withdrawals == [pending_withdrawal_0, pending_withdrawal_1]
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=1,
|
||||
pending_withdrawal_requests=[pending_withdrawal_1]
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_next_epoch(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
next_epoch = spec.get_current_epoch(state) + 1
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, validator_index, withdrawable_epoch=next_epoch)
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
assert state.pending_partial_withdrawals == [pending_withdrawal]
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_at_max(spec, state):
|
||||
pending_withdrawal_requests = []
|
||||
# Create spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP + 1 partial withdrawals
|
||||
for i in range(0, spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP + 1):
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, i)
|
||||
pending_withdrawal_requests.append(pending_withdrawal)
|
||||
|
||||
assert len(state.pending_partial_withdrawals) == spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP + 1
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP,
|
||||
pending_withdrawal_requests=pending_withdrawal_requests[:spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP]
|
||||
)
|
||||
|
||||
withdrawals_exceeding_max = pending_withdrawal_requests[spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP:]
|
||||
assert state.pending_partial_withdrawals == withdrawals_exceeding_max
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_exiting_validator(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, validator_index)
|
||||
spec.initiate_validator_exit(state, pending_withdrawal.index)
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_low_effective_balance(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, validator_index)
|
||||
state.validators[pending_withdrawal.index].effective_balance = (
|
||||
spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_no_excess_balance(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, validator_index)
|
||||
state.balances[pending_withdrawal.index] = spec.MIN_ACTIVATION_BALANCE
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_with_ineffective_sweep_on_top(spec, state):
|
||||
# Ensure validator will be processed by the sweep
|
||||
validator_index = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) // 2
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
)
|
||||
|
||||
# Check that validator is partially withdrawable before pending withdrawal is processed
|
||||
assert spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index]
|
||||
)
|
||||
# And is not partially withdrawable thereafter
|
||||
assert not spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index] - pending_withdrawal.amount
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=1,
|
||||
fully_withdrawable_indices=[],
|
||||
partial_withdrawals_indices=[],
|
||||
pending_withdrawal_requests=[pending_withdrawal]
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_with_ineffective_sweep_on_top_2(spec, state):
|
||||
# Ensure validator will be processed by the sweep
|
||||
validator_index = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) // 2
|
||||
|
||||
pending_withdrawal_0 = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
amount=spec.EFFECTIVE_BALANCE_INCREMENT // 2
|
||||
)
|
||||
|
||||
pending_withdrawal_1 = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
amount=spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
|
||||
# Set excess balance in a way that validator
|
||||
# becomes not partially withdrawable only after the second pending withdrawal is processed
|
||||
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE_ELECTRA + spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
assert spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index] - pending_withdrawal_0.amount
|
||||
)
|
||||
assert not spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index] - pending_withdrawal_0.amount - pending_withdrawal_1.amount
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=2,
|
||||
fully_withdrawable_indices=[],
|
||||
partial_withdrawals_indices=[],
|
||||
pending_withdrawal_requests=[pending_withdrawal_0, pending_withdrawal_1]
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_with_effective_sweep_on_top(spec, state):
|
||||
# Ensure validator will be processed by the sweep
|
||||
validator_index = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) // 2
|
||||
|
||||
pending_withdrawal_0 = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
amount=spec.EFFECTIVE_BALANCE_INCREMENT // 2
|
||||
)
|
||||
|
||||
pending_withdrawal_1 = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
amount=spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
|
||||
# Set excess balance to requested amount times three,
|
||||
# so the validator is partially withdrawable after pending withdrawal is processed
|
||||
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE_ELECTRA + spec.EFFECTIVE_BALANCE_INCREMENT * 2
|
||||
assert spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index] - pending_withdrawal_0.amount - pending_withdrawal_1.amount
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=3,
|
||||
fully_withdrawable_indices=[],
|
||||
partial_withdrawals_indices=[validator_index],
|
||||
pending_withdrawal_requests=[pending_withdrawal_0, pending_withdrawal_1]
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_with_sweep_different_validator(spec, state):
|
||||
# Ensure validator will be processed by the sweep
|
||||
validator_index_0 = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) // 2 - 1
|
||||
validator_index_1 = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) // 2
|
||||
|
||||
# Initiate pending withdrawal for the first validator
|
||||
pending_withdrawal_0 = prepare_pending_withdrawal(
|
||||
spec, state,
|
||||
validator_index_0,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
amount=spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
|
||||
# Make the second validator partially withdrawable by the sweep
|
||||
set_compounding_withdrawal_credential_with_balance(
|
||||
spec, state, validator_index_1,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE_ELECTRA,
|
||||
balance=(spec.MAX_EFFECTIVE_BALANCE_ELECTRA + spec.EFFECTIVE_BALANCE_INCREMENT)
|
||||
)
|
||||
|
||||
assert spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index_1],
|
||||
state.balances[validator_index_1]
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=2,
|
||||
fully_withdrawable_indices=[],
|
||||
partial_withdrawals_indices=[validator_index_1],
|
||||
pending_withdrawal_requests=[pending_withdrawal_0]
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_mixed_with_sweep_and_fully_withdrawable(spec, state):
|
||||
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_full_withdrawals_comp = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_partial_withdrawals_comp = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_pending_withdrawal_requests = spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP // 2
|
||||
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
spec, state,
|
||||
rng=random.Random(42),
|
||||
num_full_withdrawals=num_full_withdrawals,
|
||||
num_partial_withdrawals=num_partial_withdrawals,
|
||||
num_full_withdrawals_comp=num_full_withdrawals_comp,
|
||||
num_partial_withdrawals_comp=num_partial_withdrawals_comp,
|
||||
)
|
||||
|
||||
pending_withdrawal_requests = []
|
||||
for index in range(0, len(state.validators)):
|
||||
if len(pending_withdrawal_requests) >= num_pending_withdrawal_requests:
|
||||
break
|
||||
if index in (fully_withdrawable_indices + partial_withdrawals_indices):
|
||||
continue
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, index)
|
||||
pending_withdrawal_requests.append(pending_withdrawal)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD,
|
||||
fully_withdrawable_indices=fully_withdrawable_indices,
|
||||
partial_withdrawals_indices=partial_withdrawals_indices,
|
||||
pending_withdrawal_requests=pending_withdrawal_requests
|
||||
)
|
||||
|
||||
assert state.pending_partial_withdrawals == []
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_withdrawals_at_max_mixed_with_sweep_and_fully_withdrawable(spec, state):
|
||||
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_full_withdrawals_comp = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_partial_withdrawals_comp = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 4
|
||||
num_pending_withdrawal_requests = spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP + 1
|
||||
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
spec, state,
|
||||
rng=random.Random(42),
|
||||
num_full_withdrawals=num_full_withdrawals,
|
||||
num_partial_withdrawals=num_partial_withdrawals,
|
||||
num_full_withdrawals_comp=num_full_withdrawals_comp,
|
||||
num_partial_withdrawals_comp=num_partial_withdrawals_comp,
|
||||
)
|
||||
|
||||
pending_withdrawal_requests = []
|
||||
for index in range(0, len(state.validators)):
|
||||
if len(pending_withdrawal_requests) >= num_pending_withdrawal_requests:
|
||||
break
|
||||
if index in (fully_withdrawable_indices + partial_withdrawals_indices):
|
||||
continue
|
||||
|
||||
pending_withdrawal = prepare_pending_withdrawal(spec, state, index)
|
||||
pending_withdrawal_requests.append(pending_withdrawal)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
yield from run_withdrawals_processing(
|
||||
spec, state,
|
||||
execution_payload,
|
||||
num_expected_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD,
|
||||
fully_withdrawable_indices=fully_withdrawable_indices,
|
||||
partial_withdrawals_indices=partial_withdrawals_indices,
|
||||
pending_withdrawal_requests=pending_withdrawal_requests[:spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP]
|
||||
)
|
||||
|
||||
withdrawals_exceeding_max = pending_withdrawal_requests[spec.MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP:]
|
||||
assert state.pending_partial_withdrawals == withdrawals_exceeding_max
|
||||
|
@ -63,11 +63,21 @@ def sample_withdrawal_indices(spec, state, rng, num_full_withdrawals, num_partia
|
||||
|
||||
|
||||
def prepare_expected_withdrawals(spec, state, rng,
|
||||
num_full_withdrawals=0, num_partial_withdrawals=0):
|
||||
num_full_withdrawals=0, num_partial_withdrawals=0,
|
||||
num_full_withdrawals_comp=0, num_partial_withdrawals_comp=0):
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = sample_withdrawal_indices(
|
||||
spec, state, rng, num_full_withdrawals, num_partial_withdrawals
|
||||
spec, state, rng,
|
||||
num_full_withdrawals + num_full_withdrawals_comp,
|
||||
num_partial_withdrawals + num_partial_withdrawals_comp
|
||||
)
|
||||
|
||||
fully_withdrawable_indices_comp = rng.sample(fully_withdrawable_indices, num_full_withdrawals_comp)
|
||||
partial_withdrawals_indices_comp = rng.sample(partial_withdrawals_indices, num_partial_withdrawals_comp)
|
||||
|
||||
for index in (fully_withdrawable_indices_comp + partial_withdrawals_indices_comp):
|
||||
address = state.validators[index].withdrawal_credentials[12:]
|
||||
set_compounding_withdrawal_credential_with_balance(spec, state, index, address=address)
|
||||
|
||||
for index in fully_withdrawable_indices:
|
||||
set_validator_fully_withdrawable(spec, state, index)
|
||||
for index in partial_withdrawals_indices:
|
||||
@ -97,32 +107,13 @@ def set_compounding_withdrawal_credential_with_balance(spec, state, index,
|
||||
state.balances[index] = balance
|
||||
|
||||
|
||||
def prepare_expected_withdrawals_compounding(spec, state, rng,
|
||||
num_full_withdrawals=0,
|
||||
num_partial_withdrawals_sweep=0,
|
||||
excess_balance=1000000000):
|
||||
assert is_post_electra(spec)
|
||||
|
||||
fully_withdrawable_indices, partial_withdrawals_sweep_indices = sample_withdrawal_indices(
|
||||
spec, state, rng, num_full_withdrawals, num_partial_withdrawals_sweep
|
||||
)
|
||||
|
||||
for index in fully_withdrawable_indices + partial_withdrawals_sweep_indices:
|
||||
address = state.validators[index].withdrawal_credentials[12:]
|
||||
set_compounding_withdrawal_credential_with_balance(spec, state, index, address=address)
|
||||
|
||||
for index in fully_withdrawable_indices:
|
||||
set_validator_fully_withdrawable(spec, state, index)
|
||||
for index in partial_withdrawals_sweep_indices:
|
||||
set_validator_partially_withdrawable(spec, state, index)
|
||||
|
||||
return fully_withdrawable_indices, partial_withdrawals_sweep_indices
|
||||
|
||||
|
||||
def prepare_pending_withdrawal(spec, state, validator_index,
|
||||
effective_balance=32_000_000_000, amount=1_000_000_000):
|
||||
effective_balance=32_000_000_000, amount=1_000_000_000, withdrawable_epoch=None):
|
||||
assert is_post_electra(spec)
|
||||
|
||||
if withdrawable_epoch is None:
|
||||
withdrawable_epoch = spec.get_current_epoch(state)
|
||||
|
||||
balance = effective_balance + amount
|
||||
set_compounding_withdrawal_credential_with_balance(
|
||||
spec, state, validator_index, effective_balance, balance
|
||||
@ -131,7 +122,7 @@ def prepare_pending_withdrawal(spec, state, validator_index,
|
||||
withdrawal = spec.PendingPartialWithdrawal(
|
||||
index=validator_index,
|
||||
amount=amount,
|
||||
withdrawable_epoch=spec.get_current_epoch(state),
|
||||
withdrawable_epoch=withdrawable_epoch,
|
||||
)
|
||||
state.pending_partial_withdrawals.append(withdrawal)
|
||||
|
||||
@ -175,7 +166,8 @@ def verify_post_state(state, spec, expected_withdrawals,
|
||||
|
||||
|
||||
def run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=None,
|
||||
fully_withdrawable_indices=None, partial_withdrawals_indices=None, valid=True):
|
||||
fully_withdrawable_indices=None, partial_withdrawals_indices=None,
|
||||
pending_withdrawal_requests=None, valid=True):
|
||||
"""
|
||||
Run ``process_withdrawals``, yielding:
|
||||
- pre-state ('pre')
|
||||
@ -206,6 +198,11 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with
|
||||
|
||||
yield 'post', state
|
||||
|
||||
# Check withdrawal indices
|
||||
assert state.next_withdrawal_index == pre_state.next_withdrawal_index + len(expected_withdrawals)
|
||||
for index, withdrawal in enumerate(execution_payload.withdrawals):
|
||||
assert withdrawal.index == pre_state.next_withdrawal_index + index
|
||||
|
||||
if len(expected_withdrawals) == 0:
|
||||
next_withdrawal_validator_index = (
|
||||
pre_state.next_withdrawal_validator_index + spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
|
||||
@ -220,4 +217,12 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with
|
||||
if fully_withdrawable_indices is not None or partial_withdrawals_indices is not None:
|
||||
verify_post_state(state, spec, expected_withdrawals, fully_withdrawable_indices, partial_withdrawals_indices)
|
||||
|
||||
# Check withdrawal requests
|
||||
if pending_withdrawal_requests is not None:
|
||||
assert len(pending_withdrawal_requests) <= len(execution_payload.withdrawals)
|
||||
for index, request in enumerate(pending_withdrawal_requests):
|
||||
withdrawal = execution_payload.withdrawals[index]
|
||||
assert withdrawal.validator_index == request.index
|
||||
assert withdrawal.amount == request.amount
|
||||
|
||||
return expected_withdrawals
|
||||
|
Loading…
x
Reference in New Issue
Block a user