A few more cleanups

This commit is contained in:
Justin Drake 2019-06-30 14:11:46 +01:00
parent 58c864ddf4
commit 94404a5856
3 changed files with 52 additions and 54 deletions

View File

@ -81,9 +81,9 @@
- [`get_block_root_at_slot`](#get_block_root_at_slot) - [`get_block_root_at_slot`](#get_block_root_at_slot)
- [`get_randao_mix`](#get_randao_mix) - [`get_randao_mix`](#get_randao_mix)
- [`get_active_validator_indices`](#get_active_validator_indices) - [`get_active_validator_indices`](#get_active_validator_indices)
- [`get_churn_limit`](#get_churn_limit) - [`get_validator_churn_limit`](#get_validator_churn_limit)
- [`get_committee_count`](#get_committee_count)
- [`get_seed`](#get_seed) - [`get_seed`](#get_seed)
- [`get_committee_count`](#get_committee_count)
- [`get_crosslink_committee`](#get_crosslink_committee) - [`get_crosslink_committee`](#get_crosslink_committee)
- [`get_start_shard`](#get_start_shard) - [`get_start_shard`](#get_start_shard)
- [`get_shard_delta`](#get_shard_delta) - [`get_shard_delta`](#get_shard_delta)
@ -713,9 +713,11 @@ def shuffle_index(index: ValidatorIndex, index_count: int, seed: Hash) -> Valida
```python ```python
def compute_committee(indices: Sequence[ValidatorIndex], def compute_committee(indices: Sequence[ValidatorIndex],
seed: Hash, index: int, count: int) -> Sequence[ValidatorIndex]: seed: Hash,
index: int,
count: int) -> Sequence[ValidatorIndex]:
""" """
Return the committee corresponding to ``indices``, ``seed``, ``index`` and committee ``count``. Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``.
""" """
start = (len(indices) * index) // count start = (len(indices) * index) // count
end = (len(indices) * (index + 1)) // count end = (len(indices) * (index + 1)) // count
@ -780,7 +782,7 @@ def epoch_first_slot(epoch: Epoch) -> Slot:
```python ```python
def delayed_activation_exit_epoch(epoch: Epoch) -> Epoch: def delayed_activation_exit_epoch(epoch: Epoch) -> Epoch:
""" """
Return the epoch at which an activation or exit triggered in ``epoch`` takes effect. Return the epoch where validator activations and exits initiated in ``epoch`` take effect.
""" """
return Epoch(epoch + 1 + ACTIVATION_EXIT_DELAY) return Epoch(epoch + 1 + ACTIVATION_EXIT_DELAY)
``` ```
@ -812,7 +814,7 @@ def get_current_epoch(state: BeaconState) -> Epoch:
```python ```python
def get_previous_epoch(state: BeaconState) -> Epoch: def get_previous_epoch(state: BeaconState) -> Epoch:
"""` """`
Return the previous epoch (current epoch if at ``GENESIS_EPOCH``). Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
""" """
current_epoch = get_current_epoch(state) current_epoch = get_current_epoch(state)
return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1) return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
@ -859,10 +861,10 @@ def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[V
return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)] return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
``` ```
#### `get_churn_limit` #### `get_validator_churn_limit`
```python ```python
def get_churn_limit(state: BeaconState) -> int: def get_validator_churn_limit(state: BeaconState) -> int:
""" """
Return the validator churn limit for the current epoch. Return the validator churn limit for the current epoch.
""" """
@ -870,24 +872,6 @@ def get_churn_limit(state: BeaconState) -> int:
return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT) return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT)
``` ```
#### `get_committee_count`
```python
def get_committee_count(state: BeaconState, epoch: Epoch) -> int:
"""
Return the number of committees at ``epoch``.
"""
active_validator_indices = get_active_validator_indices(state, epoch)
return max(
1,
min(
SHARD_COUNT // SLOTS_PER_EPOCH,
len(active_validator_indices) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
)
) * SLOTS_PER_EPOCH
```
#### `get_seed` #### `get_seed`
```python ```python
@ -895,11 +879,25 @@ def get_seed(state: BeaconState, epoch: Epoch) -> Hash:
""" """
Return the seed at ``epoch``. Return the seed at ``epoch``.
""" """
return hash( randao_mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) # Avoid underflow
get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) + # Avoid underflow active_indices_root = hash_tree_root(List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, epoch)))
hash_tree_root(List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, epoch))) + return hash(randao_mix + active_indices_root + int_to_bytes(epoch, length=32))
int_to_bytes(epoch, length=32) ```
)
#### `get_committee_count`
```python
def get_committee_count(state: BeaconState, epoch: Epoch) -> int:
"""
Return the number of committees at ``epoch``.
"""
return max(
1,
min(
SHARD_COUNT // SLOTS_PER_EPOCH,
len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
)
) * SLOTS_PER_EPOCH
``` ```
#### `get_crosslink_committee` #### `get_crosslink_committee`
@ -1010,6 +1008,16 @@ def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
return Gwei(max(sum([state.validators[index].effective_balance for index in indices]), 1)) return Gwei(max(sum([state.validators[index].effective_balance for index in indices]), 1))
``` ```
#### `get_total_active_balance`
```python
def get_total_active_balance(state: BeaconState) -> Gwei:
"""
Return the combined effective balance of the active validators.
"""
return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
```
#### `get_domain` #### `get_domain`
```python ```python
@ -1093,7 +1101,7 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH] exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH]
exit_queue_epoch = max(exit_epochs + [delayed_activation_exit_epoch(get_current_epoch(state))]) exit_queue_epoch = max(exit_epochs + [delayed_activation_exit_epoch(get_current_epoch(state))])
exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch]) exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch])
if exit_queue_churn >= get_churn_limit(state): if exit_queue_churn >= get_validator_churn_limit(state):
exit_queue_epoch += Epoch(1) exit_queue_epoch += Epoch(1)
# Set validator exit epoch and withdrawable epoch # Set validator exit epoch and withdrawable epoch
@ -1219,11 +1227,9 @@ def process_slot(state: BeaconState) -> None:
# Cache state root # Cache state root
previous_state_root = hash_tree_root(state) previous_state_root = hash_tree_root(state)
state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
# Cache latest block header state root # Cache latest block header state root
if state.latest_block_header.state_root == ZERO_HASH: if state.latest_block_header.state_root == ZERO_HASH:
state.latest_block_header.state_root = previous_state_root state.latest_block_header.state_root = previous_state_root
# Cache block root # Cache block root
previous_block_root = signing_root(state.latest_block_header) previous_block_root = signing_root(state.latest_block_header)
state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
@ -1248,11 +1254,6 @@ def process_epoch(state: BeaconState) -> None:
#### Helper functions #### Helper functions
```python
def get_total_active_balance(state: BeaconState) -> Gwei:
return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
```
```python ```python
def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]: def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
assert epoch in (get_previous_epoch(state), get_current_epoch(state)) assert epoch in (get_previous_epoch(state), get_current_epoch(state))
@ -1278,7 +1279,7 @@ def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> Sequence
```python ```python
def get_unslashed_attesting_indices(state: BeaconState, def get_unslashed_attesting_indices(state: BeaconState,
attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]: attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]:
output = set() # Type: Set[ValidatorIndex] output = set() # type: Set[ValidatorIndex]
for a in attestations: for a in attestations:
output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits)) output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits))
return set(filter(lambda index: not state.validators[index].slashed, list(output))) return set(filter(lambda index: not state.validators[index].slashed, list(output)))
@ -1477,7 +1478,7 @@ def process_registry_updates(state: BeaconState) -> None:
validator.activation_epoch >= delayed_activation_exit_epoch(state.finalized_checkpoint.epoch) validator.activation_epoch >= delayed_activation_exit_epoch(state.finalized_checkpoint.epoch)
], key=lambda index: state.validators[index].activation_eligibility_epoch) ], key=lambda index: state.validators[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_validator_churn_limit(state)]:
validator = state.validators[index] validator = state.validators[index]
if validator.activation_epoch == FAR_FUTURE_EPOCH: if validator.activation_epoch == FAR_FUTURE_EPOCH:
validator.activation_epoch = delayed_activation_exit_epoch(get_current_epoch(state)) validator.activation_epoch = delayed_activation_exit_epoch(get_current_epoch(state))
@ -1703,13 +1704,10 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
amount = deposit.data.amount amount = deposit.data.amount
validator_pubkeys = [v.pubkey for v in state.validators] validator_pubkeys = [v.pubkey for v in state.validators]
if pubkey not in validator_pubkeys: if pubkey not in validator_pubkeys:
# Verify the deposit signature (proof of possession). # Verify the deposit signature (proof of possession) for new validators.
# Invalid signatures are allowed by the deposit contract, # Note: The deposit contract does not check signatures.
# and hence included on-chain, but must not be processed.
# Note: Deposits are valid across forks, hence the deposit domain is retrieved directly from `bls_domain` # Note: Deposits are valid across forks, hence the deposit domain is retrieved directly from `bls_domain`
if not bls_verify( if not bls_verify(pubkey, signing_root(deposit.data), deposit.data.signature, bls_domain(DOMAIN_DEPOSIT)):
pubkey, signing_root(deposit.data), deposit.data.signature, bls_domain(DOMAIN_DEPOSIT)
):
return return
# Add validator and balance entries # Add validator and balance entries
@ -1757,14 +1755,14 @@ def process_transfer(state: BeaconState, transfer: Transfer) -> None:
assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee) assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee)
# A transfer is valid in only one slot # A transfer is valid in only one slot
assert state.slot == transfer.slot assert state.slot == transfer.slot
# Sender must satisfy at least one of the following conditions in the parenthesis: # Sender must satisfy at least one of the following:
assert ( assert (
# * Has not been activated # 1) Never have been eligible for activation
state.validators[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or state.validators[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or
# * Is withdrawable # 2) Be withdrawable
get_current_epoch(state) >= state.validators[transfer.sender].withdrawable_epoch or get_current_epoch(state) >= state.validators[transfer.sender].withdrawable_epoch or
# * Balance after transfer is more than the effective balance threshold # 3) Have a balance of at least MAX_EFFECTIVE_BALANCE after the transfer
transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <= state.balances[transfer.sender] state.balances[transfer.sender] >= transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE
) )
# Verify that the pubkey is valid # Verify that the pubkey is valid
assert ( assert (

View File

@ -71,7 +71,7 @@ def test_success_exit_queue(spec, state):
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
# exit `MAX_EXITS_PER_EPOCH` # exit `MAX_EXITS_PER_EPOCH`
initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_churn_limit(state)] initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_validator_churn_limit(state)]
# Prepare a bunch of exits, based on the current state # Prepare a bunch of exits, based on the current state
exit_queue = [] exit_queue = []

View File

@ -45,7 +45,7 @@ def test_activation_queue_sorting(spec, state):
state.validators[mock_activations - 1].activation_eligibility_epoch = epoch state.validators[mock_activations - 1].activation_eligibility_epoch = epoch
# make sure we are hitting the churn # make sure we are hitting the churn
churn_limit = spec.get_churn_limit(state) churn_limit = spec.get_validator_churn_limit(state)
assert mock_activations > churn_limit assert mock_activations > churn_limit
yield from run_process_registry_updates(spec, state) yield from run_process_registry_updates(spec, state)