Merge branch 'dev' into kzg_multi_verify

This commit is contained in:
Dankrad Feist
2023-02-13 14:38:19 +00:00
9 changed files with 247 additions and 8 deletions

View File

@@ -48,6 +48,7 @@ The head block root associated with a `store` is defined as `get_head(store)`. A
- `on_tick(store, time)` whenever `time > store.time` where `time` is the current Unix time
- `on_block(store, block)` whenever a block `block: SignedBeaconBlock` is received
- `on_attestation(store, attestation)` whenever an attestation `attestation` is received
- `on_attester_slashing(store, attester_slashing)` whenever an attester slashing `attester_slashing` is received
Any of the above handlers that trigger an unhandled exception (e.g. a failed assert or an out-of-range list access) are considered invalid. Invalid calls to handlers must not modify `store`.

View File

@@ -1 +1 @@
1.3.0-rc.1
1.3.0-rc.2

View File

@@ -147,12 +147,14 @@ def test_success_one_partial_withdrawal(spec, state):
@with_capella_and_later
@spec_state_test
def test_success_max_per_slot(spec, state):
def test_success_mixed_fully_and_partial_withdrawable(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(
spec, state,
num_full_withdrawals=num_full_withdrawals, num_partial_withdrawals=num_partial_withdrawals)
num_full_withdrawals=num_full_withdrawals,
num_partial_withdrawals=num_partial_withdrawals,
)
next_slot(spec, state)
execution_payload = build_empty_execution_payload(spec, state)

View File

@@ -1,22 +1,33 @@
from eth2spec.test.helpers.constants import MINIMAL
from eth2spec.test.context import (
with_capella_and_later, spec_state_test
with_capella_and_later,
spec_state_test,
with_presets,
)
from eth2spec.test.helpers.keys import pubkeys
from eth2spec.test.helpers.state import (
next_epoch_via_block,
state_transition_and_sign_block,
transition_to,
next_slot,
)
from eth2spec.test.helpers.block import (
build_empty_block_for_next_slot,
build_empty_block,
)
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
from eth2spec.test.helpers.state import (
next_slot,
from eth2spec.test.helpers.attestations import (
next_epoch_with_attestations,
)
from eth2spec.test.helpers.withdrawals import (
set_eth1_withdrawal_credential_with_balance,
set_validator_fully_withdrawable,
set_validator_partially_withdrawable,
prepare_expected_withdrawals,
)
from eth2spec.test.helpers.deposits import (
prepare_state_and_deposit,
)
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
@@ -255,3 +266,156 @@ def test_invalid_withdrawal_fail_second_block_payload_isnt_compatible(spec, stat
yield 'blocks', [signed_block_2]
yield 'post', None
#
# Mix top-ups and withdrawals
#
@with_capella_and_later
@spec_state_test
def test_top_up_and_partial_withdrawable_validator(spec, state):
next_withdrawal_validator_index = 0
validator_index = next_withdrawal_validator_index + 1
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE)
validator = state.validators[validator_index]
balance = state.balances[validator_index]
assert not spec.is_partially_withdrawable_validator(validator, balance)
# Make a top-up balance to validator
amount = spec.MAX_EFFECTIVE_BALANCE // 4
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.deposits.append(deposit)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
# Since withdrawals happen before deposits, it becomes partially withdrawable after state transition.
validator = state.validators[validator_index]
balance = state.balances[validator_index]
assert spec.is_partially_withdrawable_validator(validator, balance)
@with_capella_and_later
@spec_state_test
def test_top_up_to_fully_withdrawn_validator(spec, state):
"""
Similar to `teste_process_deposit::test_success_top_up_to_withdrawn_validator` test.
"""
next_withdrawal_validator_index = 0
validator_index = next_withdrawal_validator_index + 1
# Fully withdraw validator
set_validator_fully_withdrawable(spec, state, validator_index)
assert state.balances[validator_index] > 0
next_epoch_via_block(spec, state)
assert state.balances[validator_index] == 0
assert state.validators[validator_index].effective_balance > 0
next_epoch_via_block(spec, state)
assert state.validators[validator_index].effective_balance == 0
# Make a top-up deposit to validator
amount = spec.MAX_EFFECTIVE_BALANCE // 4
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.deposits.append(deposit)
signed_block_1 = state_transition_and_sign_block(spec, state, block)
assert spec.is_fully_withdrawable_validator(
state.validators[validator_index],
state.balances[validator_index],
spec.get_current_epoch(state)
)
# Apply an empty block
block = build_empty_block_for_next_slot(spec, state)
signed_block_2 = state_transition_and_sign_block(spec, state, block)
# With mainnet preset, it holds
if len(state.validators) <= spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP:
assert not spec.is_fully_withdrawable_validator(
state.validators[validator_index],
state.balances[validator_index],
spec.get_current_epoch(state)
)
yield 'blocks', [signed_block_1, signed_block_2]
yield 'post', state
def _insert_validator(spec, state, balance):
effective_balance = balance if balance < spec.MAX_EFFECTIVE_BALANCE else spec.MAX_EFFECTIVE_BALANCE
validator_index = len(state.validators)
validator = spec.Validator(
pubkey=pubkeys[validator_index],
withdrawal_credentials=spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x56' * 20,
activation_eligibility_epoch=1,
activation_epoch=2,
exit_epoch=spec.FAR_FUTURE_EPOCH,
withdrawable_epoch=spec.FAR_FUTURE_EPOCH,
effective_balance=effective_balance,
)
state.validators.append(validator)
state.balances.append(balance)
state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
state.inactivity_scores.append(0)
return validator_index
def _run_activate_and_partial_withdrawal(spec, state, initial_balance):
validator_index = _insert_validator(spec, state, balance=initial_balance)
# To make it eligibile activation
transition_to(spec, state, spec.compute_start_slot_at_epoch(2) - 1)
assert not spec.is_active_validator(state.validators[validator_index], spec.get_current_epoch(state))
yield 'pre', state
blocks = []
# To activate
block = build_empty_block_for_next_slot(spec, state)
signed_block = state_transition_and_sign_block(spec, state, block)
blocks.append(signed_block)
assert spec.is_active_validator(state.validators[validator_index], spec.get_current_epoch(state))
if initial_balance > spec.MAX_EFFECTIVE_BALANCE:
assert spec.is_partially_withdrawable_validator(
state.validators[validator_index], state.balances[validator_index])
else:
assert not spec.is_partially_withdrawable_validator(
state.validators[validator_index], state.balances[validator_index])
_, new_blocks, state = next_epoch_with_attestations(spec, state, True, True)
blocks += new_blocks
yield 'blocks', blocks
yield 'post', state
@with_capella_and_later
@with_presets([MINIMAL], reason="too many validators with mainnet config")
@spec_state_test
def test_activate_and_partial_withdrawal_max_effective_balance(spec, state):
yield from _run_activate_and_partial_withdrawal(spec, state, initial_balance=spec.MAX_EFFECTIVE_BALANCE)
@with_capella_and_later
@with_presets([MINIMAL], reason="too many validators with mainnet config")
@spec_state_test
def test_activate_and_partial_withdrawal_overdeposit(spec, state):
yield from _run_activate_and_partial_withdrawal(spec, state, initial_balance=spec.MAX_EFFECTIVE_BALANCE + 10000000)

View File

@@ -0,0 +1,54 @@
from eth2spec.test.context import (
ForkMeta,
always_bls,
with_fork_metas,
)
from eth2spec.test.helpers.constants import (
AFTER_DENEB_PRE_POST_FORKS,
)
from eth2spec.test.helpers.fork_transition import (
OperationType,
run_transition_with_operation,
)
#
# BLSToExecutionChange
#
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
@always_bls
def test_transition_with_btec_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Create a BLS_TO_EXECUTION_CHANGE right *after* the transition
"""
yield from run_transition_with_operation(
state,
fork_epoch,
spec,
post_spec,
pre_tag,
post_tag,
operation_type=OperationType.BLS_TO_EXECUTION_CHANGE,
operation_at_slot=fork_epoch * spec.SLOTS_PER_EPOCH,
)
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
@always_bls
def test_transition_with_btec_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Create a BLS_TO_EXECUTION_CHANGE right *before* the transition
"""
yield from run_transition_with_operation(
state,
fork_epoch,
spec,
post_spec,
pre_tag,
post_tag,
operation_type=OperationType.BLS_TO_EXECUTION_CHANGE,
operation_at_slot=fork_epoch * spec.SLOTS_PER_EPOCH - 1,
)

View File

@@ -37,6 +37,12 @@ ALL_FORK_UPGRADES = {
ALL_PRE_POST_FORKS = ALL_FORK_UPGRADES.items()
AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0}
AFTER_BELLATRIX_PRE_POST_FORKS = AFTER_BELLATRIX_UPGRADES.items()
AFTER_CAPELLA_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items()
if key not in [PHASE0, ALTAIR]}
AFTER_CAPELLA_PRE_POST_FORKS = AFTER_CAPELLA_UPGRADES.items()
AFTER_DENEB_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items()
if key not in [PHASE0, ALTAIR, BELLATRIX]}
AFTER_DENEB_PRE_POST_FORKS = AFTER_DENEB_UPGRADES.items()
#
# Config

View File

@@ -9,6 +9,7 @@ from eth2spec.test.helpers.block import (
build_empty_block,
sign_block,
)
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
from eth2spec.test.helpers.constants import (
ALTAIR,
BELLATRIX,
@@ -36,6 +37,7 @@ class OperationType(Enum):
ATTESTER_SLASHING = auto()
DEPOSIT = auto()
VOLUNTARY_EXIT = auto()
BLS_TO_EXECUTION_CHANGE = auto()
def _set_operations_by_dict(block, operation_dict):
@@ -267,6 +269,10 @@ def run_transition_with_operation(state,
selected_validator_index = 0
signed_exits = prepare_signed_exits(spec, state, [selected_validator_index])
operation_dict = {'voluntary_exits': signed_exits}
elif operation_type == OperationType.BLS_TO_EXECUTION_CHANGE:
selected_validator_index = 0
bls_to_execution_changes = [get_signed_address_change(spec, state, selected_validator_index)]
operation_dict = {'bls_to_execution_changes': bls_to_execution_changes}
def _check_state():
if operation_type == OperationType.PROPOSER_SLASHING:
@@ -288,6 +294,9 @@ def run_transition_with_operation(state,
elif operation_type == OperationType.VOLUNTARY_EXIT:
validator = state.validators[selected_validator_index]
assert validator.exit_epoch < post_spec.FAR_FUTURE_EPOCH
elif operation_type == OperationType.BLS_TO_EXECUTION_CHANGE:
validator = state.validators[selected_validator_index]
assert validator.withdrawal_credentials[:1] == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
yield "pre", state

View File

@@ -16,6 +16,9 @@ from eth2spec.test.altair.transition import (
test_slashing as test_altair_slashing,
test_operations as test_altair_operations,
)
from eth2spec.test.eip4844.transition import (
test_operations as test_eip4844_operations,
)
def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
@@ -37,14 +40,14 @@ def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_n
if __name__ == "__main__":
altair_tests = (
all_tests = (
test_altair_transition,
test_altair_activations_and_exits,
test_altair_leaking,
test_altair_slashing,
test_altair_operations,
test_eip4844_operations,
)
all_tests = altair_tests
for transition_test_module in all_tests:
for pre_fork, post_fork in ALL_PRE_POST_FORKS:
gen_runner.run_generator("transition", [