Merge branch 'master' into hwwhww-patch-2

This commit is contained in:
Danny Ryan 2018-12-18 12:45:50 -06:00
commit 20006c674b
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
1 changed files with 67 additions and 67 deletions

View File

@ -147,7 +147,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
* **Crosslink** - a set of signatures from a committee attesting to a block in a shard chain, which can be included into the beacon chain. Crosslinks are the main means by which the beacon chain "learns about" the updated state of shard chains. * **Crosslink** - a set of signatures from a committee attesting to a block in a shard chain, which can be included into the beacon chain. Crosslinks are the main means by which the beacon chain "learns about" the updated state of shard chains.
* **Slot** - a period of `SLOT_DURATION` seconds, during which one proposer has the ability to create a beacon chain block and some attesters have the ability to make attestations * **Slot** - a period of `SLOT_DURATION` seconds, during which one proposer has the ability to create a beacon chain block and some attesters have the ability to make attestations
* **Epoch** - an aligned span of slots during which all [validators](#dfn-validator) get exactly one chance to make an attestation * **Epoch** - an aligned span of slots during which all [validators](#dfn-validator) get exactly one chance to make an attestation
* **Finalized**, **justified** - see Casper FFG finalization here: https://arxiv.org/abs/1710.09437 * **Finalized**, **justified** - see Casper FFG finalization [[casper-ffg]](#ref-casper-ffg)
* **Withdrawal period** - the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable * **Withdrawal period** - the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable
* **Genesis time** - the Unix time of the genesis beacon chain block at slot 0 * **Genesis time** - the Unix time of the genesis beacon chain block at slot 0
@ -454,6 +454,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
# Validator registry # Validator registry
'validator_registry': [ValidatorRecord], 'validator_registry': [ValidatorRecord],
'validator_balances': ['uint64'],
'validator_registry_latest_change_slot': 'uint64', 'validator_registry_latest_change_slot': 'uint64',
'validator_registry_exit_count': 'uint64', 'validator_registry_exit_count': 'uint64',
'validator_registry_delta_chain_tip': 'hash32', # For light clients to track deltas 'validator_registry_delta_chain_tip': 'hash32', # For light clients to track deltas
@ -496,8 +497,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
'randao_commitment': 'hash32', 'randao_commitment': 'hash32',
# Slots the proposer has skipped (i.e. layers of RANDAO expected) # Slots the proposer has skipped (i.e. layers of RANDAO expected)
'randao_layers': 'uint64', 'randao_layers': 'uint64',
# Balance in Gwei
'balance': 'uint64',
# Status code # Status code
'status': 'uint64', 'status': 'uint64',
# Slot when validator last changed status (or 0) # Slot when validator last changed status (or 0)
@ -963,11 +962,11 @@ def get_attestation_participants(state: BeaconState,
#### `get_effective_balance` #### `get_effective_balance`
```python ```python
def get_effective_balance(validator: ValidatorRecord) -> int: def get_effective_balance(state: State, index: int) -> int:
""" """
Returns the effective balance (also known as "balance at stake") for the ``validator``. Returns the effective balance (also known as "balance at stake") for a ``validator`` with the given ``index``.
""" """
return min(validator.balance, MAX_DEPOSIT * GWEI_PER_ETH) return min(state.validator_balances[index], MAX_DEPOSIT * GWEI_PER_ETH)
``` ```
#### `get_new_validator_registry_delta_chain_tip` #### `get_new_validator_registry_delta_chain_tip`
@ -1140,6 +1139,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
# Validator registry # Validator registry
validator_registry=[], validator_registry=[],
validator_balances=[],
validator_registry_latest_change_slot=INITIAL_SLOT_NUMBER, validator_registry_latest_change_slot=INITIAL_SLOT_NUMBER,
validator_registry_exit_count=0, validator_registry_exit_count=0,
validator_registry_delta_chain_tip=ZERO_HASH, validator_registry_delta_chain_tip=ZERO_HASH,
@ -1179,7 +1179,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials, withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials,
randao_commitment=deposit.deposit_data.deposit_input.randao_commitment randao_commitment=deposit.deposit_data.deposit_input.randao_commitment
) )
if state.validator_registry[validator_index].balance >= MAX_DEPOSIT * GWEI_PER_ETH: if get_effective_balance(state, validator_index) == MAX_DEPOSIT * GWEI_PER_ETH:
update_validator_status(state, validator_index, ACTIVE) update_validator_status(state, validator_index, ACTIVE)
# set initial committee shuffling # set initial committee shuffling
@ -1198,9 +1198,11 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
First, two helper functions: First, two helper functions:
```python ```python
def min_empty_validator_index(validators: List[ValidatorRecord], current_slot: int) -> int: def min_empty_validator_index(validators: List[ValidatorRecord],
for i, v in enumerate(validators): validator_balances: List[int],
if v.balance == 0 and v.latest_status_change_slot + ZERO_BALANCE_VALIDATOR_TTL <= current_slot: current_slot: int) -> int:
for i, (v, vbal) in enumerate(zip(validators, validator_balances)):
if vbal == 0 and v.latest_status_change_slot + ZERO_BALANCE_VALIDATOR_TTL <= current_slot:
return i return i
return None return None
``` ```
@ -1261,25 +1263,25 @@ def process_deposit(state: BeaconState,
withdrawal_credentials=withdrawal_credentials, withdrawal_credentials=withdrawal_credentials,
randao_commitment=randao_commitment, randao_commitment=randao_commitment,
randao_layers=0, randao_layers=0,
balance=deposit,
status=PENDING_ACTIVATION, status=PENDING_ACTIVATION,
latest_status_change_slot=state.slot, latest_status_change_slot=state.slot,
exit_count=0 exit_count=0
) )
index = min_empty_validator_index(state.validator_registry, state.slot) index = min_empty_validator_index(state.validator_registry, state.validator_balances, state.slot)
if index is None: if index is None:
state.validator_registry.append(validator) state.validator_registry.append(validator)
state.validator_balances.append(deposit)
index = len(state.validator_registry) - 1 index = len(state.validator_registry) - 1
else: else:
state.validator_registry[index] = validator state.validator_registry[index] = validator
state.validator_balances[index] = deposit
else: else:
# Increase balance by deposit # Increase balance by deposit
index = validator_pubkeys.index(pubkey) index = validator_pubkeys.index(pubkey)
validator = state.validator_registry[index] assert state.validator_registry[index].withdrawal_credentials == withdrawal_credentials
assert validator.withdrawal_credentials == withdrawal_credentials
validator.balance += deposit state.validator_balances[index] += deposit
return index return index
``` ```
@ -1361,12 +1363,12 @@ def exit_validator(state: BeaconState,
validator.latest_status_change_slot = state.slot validator.latest_status_change_slot = state.slot
if new_status == EXITED_WITH_PENALTY: if new_status == EXITED_WITH_PENALTY:
state.latest_penalized_exit_balances[state.slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD] += get_effective_balance(validator) state.latest_penalized_exit_balances[state.slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD] += get_effective_balance(state, index)
whistleblower = state.validator_registry[get_beacon_proposer_index(state, state.slot)] whistleblower_index = get_beacon_proposer_index(state, state.slot)
whistleblower_reward = validator.balance // WHISTLEBLOWER_REWARD_QUOTIENT whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT
whistleblower.balance += whistleblower_reward state.validator_balances[whistleblower_index] += whistleblower_reward
validator.balance -= whistleblower_reward state.validator_balances[index] -= whistleblower_reward
if prev_status == EXITED_WITHOUT_PENALTY: if prev_status == EXITED_WITHOUT_PENALTY:
return return
@ -1400,8 +1402,8 @@ Below are the processing steps that happen at every slot.
### Block roots ### Block roots
* Let `previous_block_root` be the `hash_tree_root` of the previous beacon block processed in the chain. * Let `previous_block_root` be the `tree_hash_root` of the previous beacon block processed in the chain.
* Set `state.latest_block_roots = state.latest_block_roots[1:] + [previous_block_root]`. * Set `state.latest_block_roots[(state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root`.
* If `state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0` append `merkle_root(state.latest_block_roots)` to `state.batched_block_roots`. * If `state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0` append `merkle_root(state.latest_block_roots)` to `state.batched_block_roots`.
## Per-block processing ## Per-block processing
@ -1541,51 +1543,46 @@ The steps below happen when `state.slot % EPOCH_LENGTH == 0`.
All [validators](#dfn-validator): All [validators](#dfn-validator):
* Let `active_validators = [state.validator_registry[i] for i in get_active_validator_indices(state.validator_registry)]`. * Let `active_validator_indices = get_active_validator_indices(state.validator_registry)`.
* Let `total_balance = sum([get_effective_balance(v) for v in active_validators])`. * Let `total_balance = sum([get_effective_balance(state, i) for i in active_validator_indices])`.
[Validators](#dfn-Validator) attesting during the current epoch: [Validators](#dfn-Validator) attesting during the current epoch:
* Let `this_epoch_attestations = [a for a in state.latest_attestations if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]`. (Note: this is the set of attestations of slots in the epoch `state.slot-EPOCH_LENGTH...state.slot-1`, _not_ attestations that got included in the chain during the epoch `state.slot-EPOCH_LENGTH...state.slot-1`.) * Let `this_epoch_attestations = [a for a in state.latest_attestations if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]`. (Note: this is the set of attestations of slots in the epoch `state.slot-EPOCH_LENGTH...state.slot-1`, _not_ attestations that got included in the chain during the epoch `state.slot-EPOCH_LENGTH...state.slot-1`.)
* Validators justifying the epoch boundary block at the start of the current epoch: * Validators justifying the epoch boundary block at the start of the current epoch:
* Let `this_epoch_boundary_attestations = [a for a in this_epoch_attestations if a.data.epoch_boundary_root == get_block_root(state, state.slot-EPOCH_LENGTH) and a.justified_slot == state.justified_slot]`. * Let `this_epoch_boundary_attestations = [a for a in this_epoch_attestations if a.data.epoch_boundary_root == get_block_root(state, state.slot-EPOCH_LENGTH) and a.justified_slot == state.justified_slot]`.
* Let `this_epoch_boundary_attester_indices` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`. * Let `this_epoch_boundary_attester_indices` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`.
* Let `this_epoch_boundary_attesters = [state.validator_registry[i] for indices in this_epoch_boundary_attester_indices for i in indices]`. * Let `this_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in this_epoch_boundary_attester_indices])`.
* Let `this_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in this_epoch_boundary_attesters])`.
[Validators](#dfn-Validator) attesting during the previous epoch: [Validators](#dfn-Validator) attesting during the previous epoch:
* Validators that made an attestation during the previous epoch: * Validators that made an attestation during the previous epoch:
* Let `previous_epoch_attestations = [a for a in state.latest_attestations if state.slot - 2 * EPOCH_LENGTH <= a.slot < state.slot - EPOCH_LENGTH]`. * Let `previous_epoch_attestations = [a for a in state.latest_attestations if state.slot - 2 * EPOCH_LENGTH <= a.slot < state.slot - EPOCH_LENGTH]`.
* Let `previous_epoch_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_attestations]`. * Let `previous_epoch_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_attestations]`.
* Let `previous_epoch_attesters = [state.validator_registry[i] for indices in previous_epoch_attester_indices for i in indices]`.
* Validators targeting the previous justified hash: * Validators targeting the previous justified hash:
* Let `previous_epoch_justified_attestations = [a for a in this_epoch_attestations + previous_epoch_attestations if a.justified_slot == state.previous_justified_slot]`. * Let `previous_epoch_justified_attestations = [a for a in this_epoch_attestations + previous_epoch_attestations if a.justified_slot == state.previous_justified_slot]`.
* Let `previous_epoch_justified_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_justified_attestations]`. * Let `previous_epoch_justified_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_justified_attestations]`.
* Let `previous_epoch_justified_attesters = [state.validator_registry[i] for indices in previous_epoch_justified_attester_indices for i in indices]`. * Let `previous_epoch_justified_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_justified_attester_indices])`.
* Let `previous_epoch_justified_attesting_balance = sum([get_effective_balance(v) for v in previous_epoch_justified_attesters])`.
* Validators justifying the epoch boundary block at the start of the previous epoch: * Validators justifying the epoch boundary block at the start of the previous epoch:
* Let `previous_epoch_boundary_attestations = [a for a in previous_epoch_justified_attestations if a.epoch_boundary_root == get_block_root(state, state.slot - 2 * EPOCH_LENGTH)]`. * Let `previous_epoch_boundary_attestations = [a for a in previous_epoch_justified_attestations if a.epoch_boundary_root == get_block_root(state, state.slot - 2 * EPOCH_LENGTH)]`.
* Let `previous_epoch_boundary_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`. * Let `previous_epoch_boundary_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`.
* Let `previous_epoch_boundary_attesters = [state.validator_registry[i] for indices in previous_epoch_boundary_attester_indices for i in indices]`. * Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_boundary_attester_indices])`.
* Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in previous_epoch_boundary_attesters])`.
* Validators attesting to the expected beacon chain head during the previous epoch: * Validators attesting to the expected beacon chain head during the previous epoch:
* Let `previous_epoch_head_attestations = [a for a in previous_epoch_attestations if a.beacon_block_root == get_block_root(state, a.slot)]`. * Let `previous_epoch_head_attestations = [a for a in previous_epoch_attestations if a.beacon_block_root == get_block_root(state, a.slot)]`.
* Let `previous_epoch_head_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_head_attestations]`. * Let `previous_epoch_head_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_head_attestations]`.
* Let `previous_epoch_head_attesters = [state.validator_registry[i] for indices in previous_epoch_head_attester_indices for i in indices]`. * Let `previous_epoch_head_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_head_attester_indices])`.
* Let `previous_epoch_head_attesting_balance = sum([get_effective_balance(v) for v in previous_epoch_head_attesters])`.
**Note**: `previous_epoch_boundary_attesting_balance` balance might be marginally different than `this_epoch_boundary_attesting_balance` during the previous epoch transition. Due to the tight bound on validator churn each epoch and small per-epoch rewards/penalties, the potential balance difference is very low and only marginally affects consensus safety.
For every `shard_committee` in `state.shard_committees_at_slots`: For every `shard_committee` in `state.shard_committees_at_slots`:
* Let `attesting_validators(shard_committee, shard_block_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_attestations + previous_epoch_attestations if a.shard == shard_committee.shard and a.shard_block_root == shard_block_root]`. * Let `attesting_validator_indices(shard_committee, shard_block_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_attestations + previous_epoch_attestations if a.shard == shard_committee.shard and a.shard_block_root == shard_block_root]`.
* Let `winning_root(shard_committee)` be equal to the value of `shard_block_root` such that `sum([get_effective_balance(v) for v in attesting_validators(shard_committee, shard_block_root)])` is maximized (ties broken by favoring lower `shard_block_root` values). * Let `winning_root(shard_committee)` be equal to the value of `shard_block_root` such that `sum([get_effective_balance(state, i) for i in attesting_validator_indices(shard_committee, shard_block_root)])` is maximized (ties broken by favoring lower `shard_block_root` values).
* Let `attesting_validators(shard_committee)` be equal to `attesting_validators(shard_committee, winning_root(shard_committee))` for convenience. * Let `attesting_validators(shard_committee)` be equal to `attesting_validators(shard_committee, winning_root(shard_committee))` for convenience.
* Let `total_attesting_balance(shard_committee)` be the sum of the balances-at-stake of `attesting_validators(shard_committee)`. * Let `total_attesting_balance(shard_committee)` be the sum of the balances-at-stake of `attesting_validators(shard_committee)`.
* Let `total_balance(shard_committee) = sum([get_effective_balance(v) for v in shard_committee.committee])`. * Let `total_balance(shard_committee) = sum([get_effective_balance(state, i) for i in shard_committee.committee])`.
* Let `inclusion_slot(v) = a.slot_included` for the attestation `a` where `v` is in `get_attestation_participants(state, a.data, a.participation_bitfield)`. * Let `inclusion_slot(state, index) = a.slot_included` for the attestation `a` where `index` is in `get_attestation_participants(state, a.data, a.participation_bitfield)`.
* Let `inclusion_distance(v) = a.slot_included - a.data.slot` where `a` is the above attestation. * Let `inclusion_distance(state, index) = a.slot_included - a.data.slot` where `a` is the above attestation.
* Let `adjust_for_inclusion_distance(magnitude, distance)` be the function below. * Let `adjust_for_inclusion_distance(magnitude, distance)` be the function below.
```python ```python
@ -1630,8 +1627,8 @@ For every `shard_committee` in `state.shard_committees_at_slots`:
First, we define some additional helpers: First, we define some additional helpers:
* Let `base_reward_quotient = BASE_REWARD_QUOTIENT * integer_squareroot(total_balance // GWEI_PER_ETH)`. * Let `base_reward_quotient = BASE_REWARD_QUOTIENT * integer_squareroot(total_balance // GWEI_PER_ETH)`.
* Let `base_reward(v) = get_effective_balance(v) // base_reward_quotient // 4` for any validator `v`. * Let `base_reward(state, index) = get_effective_balance(state, index) // base_reward_quotient // 4` for any validator with the given `index`.
* Let `inactivity_penalty(v, slots_since_finality) = base_reward(v) + get_effective_balance(v) * slots_since_finality // INACTIVITY_PENALTY_QUOTIENT` for any validator `v`. * Let `inactivity_penalty(state, index, slots_since_finality) = base_reward(state, index) + get_effective_balance(state, index) * slots_since_finality // INACTIVITY_PENALTY_QUOTIENT` for any validator with the given `index`.
#### Justification and finalization #### Justification and finalization
@ -1642,32 +1639,32 @@ Note: When applying penalties in the following balance recalculations implemente
Case 1: `slots_since_finality <= 4 * EPOCH_LENGTH`: Case 1: `slots_since_finality <= 4 * EPOCH_LENGTH`:
* Expected FFG source: * Expected FFG source:
* Any [validator](#dfn-validator) `v` in `previous_epoch_justified_attesters` gains `adjust_for_inclusion_distance(base_reward(v) * previous_epoch_justified_attesting_balance // total_balance, inclusion_distance(v))`. * Any [validator](#dfn-validator) `index` in `previous_epoch_justified_attester_indices` gains `adjust_for_inclusion_distance(base_reward(state, index) * previous_epoch_justified_attesting_balance // total_balance, inclusion_distance(state, index))`.
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_justified_attesters` loses `base_reward(v)`. * Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_justified_attester_indices` loses `base_reward(state, index)`.
* Expected FFG target: * Expected FFG target:
* Any [validator](#dfn-validator) `v` in `previous_epoch_boundary_attesters` gains `adjust_for_inclusion_distance(base_reward(v) * previous_epoch_boundary_attesting_balance // total_balance, inclusion_distance(v))`. * Any [validator](#dfn-validator) `index` in `previous_epoch_boundary_attester_indices` gains `adjust_for_inclusion_distance(base_reward(state, index) * previous_epoch_boundary_attesting_balance // total_balance, inclusion_distance(state, index))`.
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_boundary_attesters` loses `base_reward(v)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_boundary_attester_indices` loses `base_reward(state, index)`.
* Expected beacon chain head: * Expected beacon chain head:
* Any [validator](#dfn-validator) `v` in `previous_epoch_head_attesters` gains `adjust_for_inclusion_distance(base_reward(v) * previous_epoch_head_attesting_balance // total_balance, inclusion_distance(v))`. * Any [validator](#dfn-validator) `index` in `previous_epoch_head_attester_indices` gains `adjust_for_inclusion_distance(base_reward(state, index) * previous_epoch_head_attesting_balance // total_balance, inclusion_distance(state, index))`.
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_head_attesters` loses `base_reward(v)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_head_attester_indices` loses `base_reward(state, index)`.
Case 2: `slots_since_finality > 4 * EPOCH_LENGTH`: Case 2: `slots_since_finality > 4 * EPOCH_LENGTH`:
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_justified_attesters`, loses `inactivity_penalty(v, slots_since_finality)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_justified_attester_indices`, loses `inactivity_penalty(state, index, slots_since_finality)`.
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_boundary_attesters`, loses `inactivity_penalty(v, slots_since_finality)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_boundary_attester_indices`, loses `inactivity_penalty(state, index, slots_since_finality)`.
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_head_attesters`, loses `inactivity_penalty(v, slots_since_finality)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_head_attester_indices`, loses `inactivity_penalty(state, index, slots_since_finality)`.
* Any [validator](#dfn-validator) with `status == EXITED_WITH_PENALTY`, loses `3 * inactivity_penalty(v, slots_since_finality)`. * Any [validator](#dfn-validator) `index` with `status == EXITED_WITH_PENALTY`, loses `3 * inactivity_penalty(state, index, slots_since_finality)`.
#### Attestation inclusion #### Attestation inclusion
For each `v` in `previous_epoch_attesters`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(v))` and set `state.validator_registry[proposer_index].balance += base_reward(v) // INCLUDER_REWARD_QUOTIENT`. For each `index` in `previous_epoch_attester_indices`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(state, index))` and set `state.validator_balances[proposer_index] += base_reward(state, index) // INCLUDER_REWARD_QUOTIENT`.
#### Crosslinks #### Crosslinks
For every `shard_committee` in `state.shard_committees_at_slots[:EPOCH_LENGTH]` (i.e. the objects corresponding to the epoch before the current one), for each `v` in `[state.validator_registry[index] for index in shard_committee.committee]`, adjust balances as follows: For every `shard_committee` in `state.shard_committees_at_slots[:EPOCH_LENGTH]` (i.e. the objects corresponding to the epoch before the current one), for each `index` in `shard_committee.committee`, adjust balances as follows:
* If `v in attesting_validators(shard_committee)`, `v.balance += adjust_for_inclusion_distance(base_reward(v) * total_attesting_balance(shard_committee) // total_balance(shard_committee)), inclusion_distance(v))`. * If `index in attesting_validators(shard_committee)`, `state.validator_balances[index] += adjust_for_inclusion_distance(base_reward(state, index) * total_attesting_balance(shard_committee) // total_balance(shard_committee)), inclusion_distance(state, index))`.
* If `v not in attesting_validators(shard_committee)`, `v.balance -= base_reward(v)`. * If `index not in attesting_validators(shard_committee)`, `state.validator_balances[index] -= base_reward(state, index)`.
### Ejections ### Ejections
@ -1680,7 +1677,7 @@ def process_ejections(state: BeaconState) -> None:
and eject active validators with balance below ``EJECTION_BALANCE``. and eject active validators with balance below ``EJECTION_BALANCE``.
""" """
for index in active_validator_indices(state.validator_registry): for index in active_validator_indices(state.validator_registry):
if state.validator_registry[index].balance < EJECTION_BALANCE: if state.validator_balances[index] < EJECTION_BALANCE:
update_validator_status(state, index, new_status=EXITED_WITHOUT_PENALTY) update_validator_status(state, index, new_status=EXITED_WITHOUT_PENALTY)
``` ```
@ -1702,7 +1699,7 @@ def update_validator_registry(state: BeaconState) -> None:
# The active validators # The active validators
active_validator_indices = get_active_validator_indices(state.validator_registry) active_validator_indices = get_active_validator_indices(state.validator_registry)
# The total effective balance of active validators # The total effective balance of active validators
total_balance = sum([get_effective_balance(v) for i, v in enumerate(validator_registry) if i in active_validator_indices]) total_balance = sum([get_effective_balance(state, i) for i in active_validator_indices])
# The maximum balance churn in Gwei (for deposits and exits separately) # The maximum balance churn in Gwei (for deposits and exits separately)
max_balance_churn = max( max_balance_churn = max(
@ -1713,9 +1710,9 @@ def update_validator_registry(state: BeaconState) -> None:
# Activate validators within the allowable balance churn # Activate validators within the allowable balance churn
balance_churn = 0 balance_churn = 0
for index, validator in enumerate(state.validator_registry): for index, validator in enumerate(state.validator_registry):
if validator.status == PENDING_ACTIVATION and validator.balance >= MAX_DEPOSIT * GWEI_PER_ETH: if validator.status == PENDING_ACTIVATION and state.validator_balances[index] >= MAX_DEPOSIT * GWEI_PER_ETH:
# Check the balance churn would be within the allowance # Check the balance churn would be within the allowance
balance_churn += get_effective_balance(validator) balance_churn += get_effective_balance(state, index)
if balance_churn > max_balance_churn: if balance_churn > max_balance_churn:
break break
@ -1727,7 +1724,7 @@ def update_validator_registry(state: BeaconState) -> None:
for index, validator in enumerate(state.validator_registry): for index, validator in enumerate(state.validator_registry):
if validator.status == ACTIVE_PENDING_EXIT: if validator.status == ACTIVE_PENDING_EXIT:
# Check the balance churn would be within the allowance # Check the balance churn would be within the allowance
balance_churn += get_effective_balance(validator) balance_churn += get_effective_balance(state, index)
if balance_churn > max_balance_churn: if balance_churn > max_balance_churn:
break break
@ -1744,11 +1741,11 @@ def update_validator_registry(state: BeaconState) -> None:
) )
# Calculate penalties for slashed validators # Calculate penalties for slashed validators
def to_penalize(v): def to_penalize(index):
return v.status == EXITED_WITH_PENALTY return state.validator_registry[index].status == EXITED_WITH_PENALTY
validators_to_penalize = filter(to_penalize, validator_registry) validators_to_penalize = filter(to_penalize, range(len(validator_registry)))
for v in validators_to_penalize: for index in validators_to_penalize:
v.balance -= get_effective_balance(v) * min(total_penalties * 3, total_balance) // total_balance state.validator_balances[index] -= get_effective_balance(state, index) * min(total_penalties * 3, total_balance) // total_balance
return validator_registry, latest_penalized_exit_balances, validator_registry_delta_chain_tip return validator_registry, latest_penalized_exit_balances, validator_registry_delta_chain_tip
``` ```
@ -1809,6 +1806,9 @@ This section is divided into Normative and Informative references. Normative re
## Normative ## Normative
## Informative ## Informative
<a id="ref-casper-ffg"></a> _**casper-ffg**_
&nbsp; _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437
<a id="ref-python-poc"></a> _**python-poc**_ <a id="ref-python-poc"></a> _**python-poc**_
&nbsp; _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain &nbsp; _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain