Merge pull request #1001 from ethereum/registry_test
Fix `process_registry_updates` and add `test_process_registry_updates`
This commit is contained in:
commit
b31c21b3a7
|
@ -1562,6 +1562,7 @@ def process_registry_updates(state: BeaconState) -> None:
|
||||||
], key=lambda index: state.validator_registry[index].activation_eligibility_epoch)
|
], key=lambda index: state.validator_registry[index].activation_eligibility_epoch)
|
||||||
# Dequeued validators for activation up to churn limit (without resetting activation epoch)
|
# Dequeued validators for activation up to churn limit (without resetting activation epoch)
|
||||||
for index in activation_queue[:get_churn_limit(state)]:
|
for index in activation_queue[:get_churn_limit(state)]:
|
||||||
|
validator = state.validator_registry[index]
|
||||||
if validator.activation_epoch == FAR_FUTURE_EPOCH:
|
if validator.activation_epoch == FAR_FUTURE_EPOCH:
|
||||||
validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
|
validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
|
||||||
```
|
```
|
||||||
|
|
|
@ -224,7 +224,7 @@ Up to `MAX_ATTESTATIONS` aggregate attestations can be included in the `block`.
|
||||||
|
|
||||||
##### Deposits
|
##### Deposits
|
||||||
|
|
||||||
If there are any unprocessed deposits for the existing `state.latest_eth1_data` (i.e. `state.latest_eth1_data.deposit_count > state.deposit_index`), then pending deposits _must_ be added to the block. The expected number of deposits is exactly `min(MAX_DEPOSITS, latest_eth1_data.deposit_count - state.deposit_index)`. These [`deposits`](../core/0_beacon-chain.md#deposit) are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](../core/0_deposit-contract.md) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](../core/0_beacon-chain.md#deposits).
|
If there are any unprocessed deposits for the existing `state.latest_eth1_data` (i.e. `state.latest_eth1_data.deposit_count > state.deposit_index`), then pending deposits _must_ be added to the block. The expected number of deposits is exactly `min(MAX_DEPOSITS, latest_eth1_data.deposit_count - state.deposit_index)`. These [`deposits`](../core/0_beacon-chain.md#deposit) are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](../core/0_deposit-contract) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](../core/0_beacon-chain.md#deposits).
|
||||||
|
|
||||||
The `proof` for each deposit must be constructed against the deposit root contained in `state.latest_eth1_data` rather than the deposit root at the time the deposit was initially logged from the 1.0 chain. This entails storing a full deposit merkle tree locally and computing updated proofs against the `latest_eth1_data.deposit_root` as needed. See [`minimal_merkle.py`](https://github.com/ethereum/research/blob/master/spec_pythonizer/utils/merkle_minimal.py) for a sample implementation.
|
The `proof` for each deposit must be constructed against the deposit root contained in `state.latest_eth1_data` rather than the deposit root at the time the deposit was initially logged from the 1.0 chain. This entails storing a full deposit merkle tree locally and computing updated proofs against the `latest_eth1_data.deposit_root` as needed. See [`minimal_merkle.py`](https://github.com/ethereum/research/blob/master/spec_pythonizer/utils/merkle_minimal.py) for a sample implementation.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import eth2spec.phase0.spec as spec
|
||||||
|
|
||||||
|
from eth2spec.phase0.spec import (
|
||||||
|
get_current_epoch,
|
||||||
|
is_active_validator,
|
||||||
|
)
|
||||||
|
from tests.helpers import (
|
||||||
|
next_epoch,
|
||||||
|
)
|
||||||
|
|
||||||
|
# mark entire file as 'state'
|
||||||
|
pytestmark = pytest.mark.state
|
||||||
|
|
||||||
|
|
||||||
|
def test_activation(state):
|
||||||
|
index = 0
|
||||||
|
assert is_active_validator(state.validator_registry[index], get_current_epoch(state))
|
||||||
|
|
||||||
|
# Mock a new deposit
|
||||||
|
state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
assert not is_active_validator(state.validator_registry[index], get_current_epoch(state))
|
||||||
|
|
||||||
|
pre_state = deepcopy(state)
|
||||||
|
|
||||||
|
blocks = []
|
||||||
|
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
||||||
|
block = next_epoch(state)
|
||||||
|
blocks.append(block)
|
||||||
|
|
||||||
|
assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
|
assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
|
assert is_active_validator(
|
||||||
|
state.validator_registry[index],
|
||||||
|
get_current_epoch(state),
|
||||||
|
)
|
||||||
|
|
||||||
|
return pre_state, blocks, state
|
||||||
|
|
||||||
|
|
||||||
|
def test_ejection(state):
|
||||||
|
index = 0
|
||||||
|
assert is_active_validator(state.validator_registry[index], get_current_epoch(state))
|
||||||
|
assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
|
# Mock an ejection
|
||||||
|
state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE
|
||||||
|
|
||||||
|
pre_state = deepcopy(state)
|
||||||
|
|
||||||
|
blocks = []
|
||||||
|
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
||||||
|
block = next_epoch(state)
|
||||||
|
blocks.append(block)
|
||||||
|
|
||||||
|
assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
|
assert not is_active_validator(
|
||||||
|
state.validator_registry[index],
|
||||||
|
get_current_epoch(state),
|
||||||
|
)
|
||||||
|
|
||||||
|
return pre_state, blocks, state
|
|
@ -402,11 +402,21 @@ def add_attestation_to_state(state, attestation, slot):
|
||||||
|
|
||||||
|
|
||||||
def next_slot(state):
|
def next_slot(state):
|
||||||
|
"""
|
||||||
|
Transition to the next slot via an empty block.
|
||||||
|
Return the empty block that triggered the transition.
|
||||||
|
"""
|
||||||
block = build_empty_block_for_next_slot(state)
|
block = build_empty_block_for_next_slot(state)
|
||||||
state_transition(state, block)
|
state_transition(state, block)
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
def next_epoch(state):
|
def next_epoch(state):
|
||||||
|
"""
|
||||||
|
Transition to the start slot of the next epoch via an empty block.
|
||||||
|
Return the empty block that triggered the transition.
|
||||||
|
"""
|
||||||
block = build_empty_block_for_next_slot(state)
|
block = build_empty_block_for_next_slot(state)
|
||||||
block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH)
|
block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH)
|
||||||
state_transition(state, block)
|
state_transition(state, block)
|
||||||
|
return block
|
||||||
|
|
Loading…
Reference in New Issue