eth2.0-specs/specs/altair/beacon-chain.md

700 lines
29 KiB
Markdown
Raw Normal View History

2021-03-11 13:22:38 +00:00
# Ethereum 2.0 Altair
2020-11-12 09:28:05 +00:00
## Table of contents
<!-- TOC -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
2020-11-12 09:28:05 +00:00
- [Introduction](#introduction)
2021-02-01 20:48:55 +00:00
- [Custom types](#custom-types)
- [Constants](#constants)
- [Participation flag indices](#participation-flag-indices)
- [Participation flag fractions](#participation-flag-fractions)
2021-01-05 13:56:32 +00:00
- [Misc](#misc)
2020-11-12 09:28:05 +00:00
- [Configuration](#configuration)
2021-02-11 21:53:29 +00:00
- [Updated penalty values](#updated-penalty-values)
2021-01-05 13:56:32 +00:00
- [Misc](#misc-1)
- [Time parameters](#time-parameters)
- [Domain types](#domain-types)
- [Containers](#containers)
2021-03-09 22:16:26 +00:00
- [Modified containers](#modified-containers)
- [`BeaconBlockBody`](#beaconblockbody)
- [`BeaconState`](#beaconstate)
- [New containers](#new-containers)
- [`SyncCommittee`](#synccommittee)
2020-11-12 09:28:05 +00:00
- [Helper functions](#helper-functions)
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
- [`Predicates`](#predicates)
- [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify)
2021-01-05 21:17:34 +00:00
- [Misc](#misc-2)
- [`get_flag_indices_and_numerators`](#get_flag_indices_and_numerators)
- [`add_flag`](#add_flag)
- [`has_flag`](#has_flag)
2020-11-12 09:28:05 +00:00
- [Beacon state accessors](#beacon-state-accessors)
- [`get_sync_committee_indices`](#get_sync_committee_indices)
- [`get_sync_committee`](#get_sync_committee)
2021-01-05 21:17:34 +00:00
- [`get_base_reward`](#get_base_reward)
2021-01-05 13:56:32 +00:00
- [`get_unslashed_participating_indices`](#get_unslashed_participating_indices)
- [`get_flag_deltas`](#get_flag_deltas)
2021-01-11 10:06:37 +00:00
- [New `get_inactivity_penalty_deltas`](#new-get_inactivity_penalty_deltas)
2021-02-11 21:53:29 +00:00
- [Beacon state mutators](#beacon-state-mutators)
- [New `slash_validator`](#new-slash_validator)
2020-11-12 09:28:05 +00:00
- [Block processing](#block-processing)
- [Modified `process_attestation`](#modified-process_attestation)
2021-03-09 20:21:16 +00:00
- [Modified `process_deposit`](#modified-process_deposit)
- [Sync committee processing](#sync-committee-processing)
- [Epoch processing](#epoch-processing)
- [Justification and finalization](#justification-and-finalization)
2021-03-09 20:21:16 +00:00
- [Leak scores](#leak-scores)
- [Rewards and penalties](#rewards-and-penalties)
- [Slashings](#slashings)
- [Participation flags updates](#participation-flags-updates)
- [Sync committee updates](#sync-committee-updates)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
2020-11-12 09:28:05 +00:00
## Introduction
2021-03-11 13:22:38 +00:00
Altair is a patch implementing the first hard fork to the beacon chain.
2021-02-15 18:22:11 +00:00
It has four main features:
2020-12-18 23:22:11 +00:00
* Light client support via sync committees
* Incentive accounting reforms, reducing spec complexity
and [TODO] reducing the cost of processing chains that have very little or zero participation for a long span of epochs
2021-02-15 18:22:11 +00:00
* Update penalty configuration values, moving them toward their planned maximally punitive configuration
2020-12-18 23:22:11 +00:00
* Fork choice rule changes to address weaknesses recently discovered in the existing fork choice
## Custom types
| Name | SSZ equivalent | Description |
| - | - | - |
| `ParticipationFlags` | `uint8` | A succinct representation of 8 boolean participation flags |
## Constants
### Participation flag indices
2020-12-18 23:22:11 +00:00
| Name | Value |
2020-12-18 23:22:11 +00:00
| - | - |
| `TIMELY_HEAD_FLAG_INDEX` | `0` |
| `TIMELY_SOURCE_FLAG_INDEX` | `1` |
| `TIMELY_TARGET_FLAG_INDEX` | `2` |
2020-12-18 23:22:11 +00:00
### Participation flag fractions
2020-12-18 23:22:11 +00:00
| Name | Value |
| - | - |
| `TIMELY_HEAD_FLAG_NUMERATOR` | `12` |
| `TIMELY_SOURCE_FLAG_NUMERATOR` | `12` |
| `TIMELY_TARGET_FLAG_NUMERATOR` | `32` |
| `FLAG_DENOMINATOR` | `64` |
2020-12-18 23:22:11 +00:00
**Note**: The participatition flag fractions add up to 7/8.
The remaining 1/8 is for proposer incentives and other future micro-incentives.
2020-12-18 23:22:11 +00:00
### Misc
| Name | Value |
| - | - |
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
2021-01-05 17:11:46 +00:00
## Configuration
2021-02-11 21:53:29 +00:00
### Updated penalty values
This patch updates a few configuration values to move penalty constants toward their final, maxmium security values.
*Note*: The spec does *not* override previous configuration values but instead creates new values and replaces usage throughout.
| Name | Value |
| - | - |
2021-03-11 13:22:38 +00:00
| `ALTAIR_INACTIVITY_PENALTY_QUOTIENT` | `uint64(3 * 2**24)` (= 50,331,648) |
| `ALTAIR_MIN_SLASHING_PENALTY_QUOTIENT` | `uint64(2**6)` (=64) |
| `ALTAIR_PROPORTIONAL_SLASHING_MULTIPLIER` | `uint64(2)` |
2021-02-11 21:53:29 +00:00
2020-11-12 09:28:05 +00:00
### Misc
| Name | Value |
| - | - |
| `SYNC_COMMITTEE_SIZE` | `uint64(2**10)` (= 1,024) |
| `SYNC_SUBCOMMITTEE_SIZE` | `uint64(2**6)` (= 64) |
| `LEAK_SCORE_BIAS` | 4 |
### Time parameters
| Name | Value | Unit | Duration |
| - | - | :-: | :-: |
| `EPOCHS_PER_SYNC_COMMITTEE_PERIOD` | `Epoch(2**8)` (= 256) | epochs | ~27 hours |
2020-11-12 09:28:05 +00:00
### Domain types
| Name | Value |
| - | - |
| `DOMAIN_SYNC_COMMITTEE` | `DomainType('0x07000000')` |
## Containers
2020-11-12 09:28:05 +00:00
2021-03-09 22:16:26 +00:00
### Modified containers
2020-12-07 15:10:39 +00:00
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
#### `BeaconBlockBody`
2020-11-12 09:28:05 +00:00
```python
class BeaconBlockBody(Container):
randao_reveal: BLSSignature
eth1_data: Eth1Data # Eth1 data vote
graffiti: Bytes32 # Arbitrary data
# Operations
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]
attestations: List[Attestation, MAX_ATTESTATIONS]
deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
2020-11-25 11:59:01 +00:00
# Sync committee aggregate signature
2021-03-11 13:22:38 +00:00
sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE] # [New in Altair]
sync_committee_signature: BLSSignature # [New in Altair]
2020-11-12 09:28:05 +00:00
```
#### `BeaconState`
2020-11-12 09:28:05 +00:00
```python
2020-12-18 23:22:11 +00:00
class BeaconState(Container):
# Versioning
genesis_time: uint64
genesis_validators_root: Root
slot: Slot
fork: Fork
# History
latest_block_header: BeaconBlockHeader
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
# Eth1
eth1_data: Eth1Data
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
eth1_deposit_index: uint64
# Registry
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
# Slashings
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
# Participation
2021-03-11 16:28:58 +00:00
previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] # [New in Altair]
current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] # [New in Altair]
2020-12-18 23:22:11 +00:00
# Finality
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch
previous_justified_checkpoint: Checkpoint
current_justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
# Light client sync committees
2021-03-11 16:28:58 +00:00
current_sync_committee: SyncCommittee # [New in Altair]
next_sync_committee: SyncCommittee # [New in Altair]
2021-03-09 20:21:16 +00:00
# Leak
2021-03-11 16:28:58 +00:00
leak_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] # [New in Altair]
2020-11-12 09:28:05 +00:00
```
### New containers
2020-11-12 09:28:05 +00:00
#### `SyncCommittee`
2020-11-12 09:28:05 +00:00
```python
class SyncCommittee(Container):
pubkeys: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE]
pubkey_aggregates: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE // SYNC_SUBCOMMITTEE_SIZE]
2020-11-12 09:28:05 +00:00
```
## Helper functions
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
### `Predicates`
#### `eth2_fast_aggregate_verify`
```python
def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
"""
Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
"""
if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
return True
return bls.FastAggregateVerify(pubkeys, message, signature)
```
### Misc
#### `get_flag_indices_and_numerators`
```python
def get_flag_indices_and_numerators() -> Sequence[Tuple[int, int]]:
return (
(TIMELY_HEAD_FLAG_INDEX, TIMELY_HEAD_FLAG_NUMERATOR),
(TIMELY_SOURCE_FLAG_INDEX, TIMELY_SOURCE_FLAG_NUMERATOR),
(TIMELY_TARGET_FLAG_INDEX, TIMELY_TARGET_FLAG_NUMERATOR),
)
```
#### `add_flag`
```python
def add_flag(flags: ParticipationFlags, flag_index: int) -> ParticipationFlags:
flag = ParticipationFlags(2**flag_index)
return flags | flag
```
#### `has_flag`
```python
def has_flag(flags: ParticipationFlags, flag_index: int) -> bool:
flag = ParticipationFlags(2**flag_index)
return flags & flag == flag
```
### Beacon state accessors
#### `get_sync_committee_indices`
2020-11-12 09:28:05 +00:00
```python
def get_sync_committee_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
2020-11-12 09:28:05 +00:00
"""
2021-01-19 12:52:40 +00:00
Return the sequence of sync committee indices (which may include duplicate indices) for a given state and epoch.
"""
2020-12-07 15:10:39 +00:00
MAX_RANDOM_BYTE = 2**8 - 1
2020-11-15 17:23:44 +00:00
base_epoch = Epoch((max(epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD, 1) - 1) * EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
active_validator_indices = get_active_validator_indices(state, base_epoch)
active_validator_count = uint64(len(active_validator_indices))
seed = get_seed(state, base_epoch, DOMAIN_SYNC_COMMITTEE)
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
i = 0
sync_committee_indices: List[ValidatorIndex] = []
while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
candidate_index = active_validator_indices[shuffled_index]
random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
effective_balance = state.validators[candidate_index].effective_balance
2021-01-19 12:52:40 +00:00
if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: # Sample with replacement
sync_committee_indices.append(candidate_index)
i += 1
return sync_committee_indices
2020-11-12 09:28:05 +00:00
```
2020-11-15 17:23:44 +00:00
#### `get_sync_committee`
2020-11-12 09:28:05 +00:00
```python
def get_sync_committee(state: BeaconState, epoch: Epoch) -> SyncCommittee:
2020-11-12 09:28:05 +00:00
"""
Return the sync committee for a given state and epoch.
2020-11-12 09:28:05 +00:00
"""
indices = get_sync_committee_indices(state, epoch)
2021-03-09 20:21:16 +00:00
pubkeys = [state.validators[index].pubkey for index in indices]
subcommitees = [pubkeys[i:i + SYNC_SUBCOMMITTEE_SIZE] for i in range(0, len(pubkeys), SYNC_SUBCOMMITTEE_SIZE)]
pubkey_aggregates = [bls.AggregatePKs(subcommitee) for subcommitee in subcommitees]
return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=pubkey_aggregates)
2020-11-12 09:28:05 +00:00
```
#### `get_base_reward`
*Note*: The function `get_base_reward` is modified with the removal of `BASE_REWARDS_PER_EPOCH`.
```python
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
total_balance = get_total_active_balance(state)
effective_balance = state.validators[index].effective_balance
return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance))
```
2020-12-18 23:22:11 +00:00
#### `get_unslashed_participating_indices`
```python
def get_unslashed_participating_indices(state: BeaconState, flag_index: int, epoch: Epoch) -> Set[ValidatorIndex]:
"""
Retrieve the active and unslashed validator indices for the given epoch and flag index.
"""
2020-12-18 23:22:11 +00:00
assert epoch in (get_previous_epoch(state), get_current_epoch(state))
if epoch == get_current_epoch(state):
epoch_participation = state.current_epoch_participation
else:
epoch_participation = state.previous_epoch_participation
active_validator_indices = get_active_validator_indices(state, epoch)
participating_indices = [i for i in active_validator_indices if has_flag(epoch_participation[i], flag_index)]
2020-12-18 23:22:11 +00:00
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
```
#### `get_flag_deltas`
```python
def get_flag_deltas(state: BeaconState,
flag_index: int,
numerator: uint64) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
2020-12-18 23:22:11 +00:00
"""
2021-02-02 19:35:00 +00:00
Compute the rewards and penalties associated with a particular duty, by scanning through the participation
2020-12-18 23:22:11 +00:00
flags to determine who participated and who did not and assigning them the appropriate rewards and penalties.
"""
rewards = [Gwei(0)] * len(state.validators)
penalties = [Gwei(0)] * len(state.validators)
unslashed_participating_indices = get_unslashed_participating_indices(state, flag_index, get_previous_epoch(state))
2020-12-18 23:22:11 +00:00
increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from balances to avoid uint64 overflow
unslashed_participating_increments = get_total_balance(state, unslashed_participating_indices) // increment
active_increments = get_total_active_balance(state) // increment
for index in get_eligible_validator_indices(state):
base_reward = get_base_reward(state, index)
if index in unslashed_participating_indices:
if is_in_inactivity_leak(state):
# Optimal participation is fully rewarded to cancel the inactivity penalty
rewards[index] = base_reward * numerator // FLAG_DENOMINATOR
2020-12-18 23:22:11 +00:00
else:
rewards[index] = (
(base_reward * numerator * unslashed_participating_increments)
// (active_increments * FLAG_DENOMINATOR)
2020-12-18 23:22:11 +00:00
)
else:
penalties[index] = base_reward * numerator // FLAG_DENOMINATOR
return rewards, penalties
2020-12-18 23:22:11 +00:00
```
2021-01-11 10:06:37 +00:00
#### New `get_inactivity_penalty_deltas`
2020-12-18 23:22:11 +00:00
2021-02-11 21:53:29 +00:00
*Note*: The function `get_inactivity_penalty_deltas` is modified in the selection of matching target indices
and the removal of `BASE_REWARDS_PER_EPOCH`.
2020-12-18 23:22:11 +00:00
```python
def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
"""
Compute the penalties associated with the inactivity leak, by scanning through the participation
flags to determine who participated and who did not, applying the leak penalty globally and applying
compensatory rewards to participants.
"""
rewards = [Gwei(0) for _ in range(len(state.validators))]
penalties = [Gwei(0) for _ in range(len(state.validators))]
if not is_in_inactivity_leak(state):
return rewards, penalties
reward_numerator_sum = sum(numerator for (_, numerator) in get_flag_indices_and_numerators())
matching_target_attesting_indices = get_unslashed_participating_indices(
state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)
)
for index in get_eligible_validator_indices(state):
# If validator is performing optimally this cancels all attestation rewards for a neutral balance
penalties[index] += Gwei(get_base_reward(state, index) * reward_numerator_sum // FLAG_DENOMINATOR)
2021-03-09 20:21:16 +00:00
if index not in matching_target_attesting_indices and state.leak_scores[index] >= LEAK_SCORE_BIAS:
effective_balance = state.validators[index].effective_balance
leak_penalty = Gwei(
2021-03-11 16:28:58 +00:00
effective_balance * state.leak_scores[index] // LEAK_SCORE_BIAS // ALTAIR_INACTIVITY_PENALTY_QUOTIENT
)
penalties[index] += leak_penalty
return rewards, penalties
2020-12-18 23:22:11 +00:00
```
2021-02-11 21:53:29 +00:00
### Beacon state mutators
#### New `slash_validator`
*Note*: The function `slash_validator` is modified
2021-03-11 13:22:38 +00:00
with the substitution of `MIN_SLASHING_PENALTY_QUOTIENT` with `ALTAIR_MIN_SLASHING_PENALTY_QUOTIENT`.
2021-02-11 21:53:29 +00:00
```python
def slash_validator(state: BeaconState,
slashed_index: ValidatorIndex,
whistleblower_index: ValidatorIndex=None) -> None:
"""
Slash the validator with index ``slashed_index``.
"""
epoch = get_current_epoch(state)
initiate_validator_exit(state, slashed_index)
validator = state.validators[slashed_index]
validator.slashed = True
validator.withdrawable_epoch = max(validator.withdrawable_epoch, Epoch(epoch + EPOCHS_PER_SLASHINGS_VECTOR))
state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
2021-03-11 13:22:38 +00:00
decrease_balance(state, slashed_index, validator.effective_balance // ALTAIR_MIN_SLASHING_PENALTY_QUOTIENT)
2021-02-11 21:53:29 +00:00
# Apply proposer and whistleblower rewards
proposer_index = get_beacon_proposer_index(state)
if whistleblower_index is None:
whistleblower_index = proposer_index
whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT)
increase_balance(state, proposer_index, proposer_reward)
increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
```
2020-11-12 09:28:05 +00:00
### Block processing
```python
def process_block(state: BeaconState, block: BeaconBlock) -> None:
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
process_block_header(state, block)
process_randao(state, block.body)
process_eth1_data(state, block.body)
2021-03-11 13:22:38 +00:00
process_operations(state, block.body) # [Modified in Altair]
process_sync_committee(state, block.body) # [New in Altair]
2020-11-12 09:28:05 +00:00
```
#### Modified `process_attestation`
2020-12-18 23:22:11 +00:00
*Note*: The function `process_attestation` is modified to do incentive accounting with epoch participation flags.
```python
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
data = attestation.data
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
assert data.target.epoch == compute_epoch_at_slot(data.slot)
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
2020-12-18 23:22:11 +00:00
committee = get_beacon_committee(state, data.slot, data.index)
assert len(attestation.aggregation_bits) == len(committee)
2020-12-18 23:22:11 +00:00
if data.target.epoch == get_current_epoch(state):
epoch_participation = state.current_epoch_participation
justified_checkpoint = state.current_justified_checkpoint
else:
epoch_participation = state.previous_epoch_participation
justified_checkpoint = state.previous_justified_checkpoint
2020-12-18 23:22:11 +00:00
# Matching roots
is_matching_head = data.beacon_block_root == get_block_root_at_slot(state, data.slot)
is_matching_source = data.source == justified_checkpoint
is_matching_target = data.target.root == get_block_root(state, data.target.epoch)
assert is_matching_source
# Verify signature
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
# Participation flag indices
participation_flag_indices = []
if is_matching_head and is_matching_target and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
2020-12-18 23:22:11 +00:00
if is_matching_source and state.slot <= data.slot + integer_squareroot(SLOTS_PER_EPOCH):
participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
2020-12-18 23:22:11 +00:00
if is_matching_target and state.slot <= data.slot + SLOTS_PER_EPOCH:
participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)
2020-12-18 23:22:11 +00:00
# Update epoch participation flags
proposer_reward_numerator = 0
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
for flag_index, flag_numerator in get_flag_indices_and_numerators():
if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
proposer_reward_numerator += get_base_reward(state, index) * flag_numerator
2020-12-18 23:22:11 +00:00
# Reward proposer
proposer_reward = Gwei(proposer_reward_numerator // (FLAG_DENOMINATOR * PROPOSER_REWARD_QUOTIENT))
2020-12-18 23:22:11 +00:00
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
```
2021-03-09 20:21:16 +00:00
#### Modified `process_deposit`
2021-03-09 20:21:16 +00:00
*Note*: The function `process_deposit` is modified to initialize `leak_scores`, `previous_epoch_participation`, `current_epoch_participation`.
```python
def process_deposit(state: BeaconState, deposit: Deposit) -> None:
# Verify the Merkle branch
assert is_valid_merkle_branch(
leaf=hash_tree_root(deposit.data),
branch=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the List length mix-in
index=state.eth1_deposit_index,
root=state.eth1_data.deposit_root,
)
# Deposits must be processed in order
state.eth1_deposit_index += 1
pubkey = deposit.data.pubkey
amount = deposit.data.amount
validator_pubkeys = [v.pubkey for v in state.validators]
if pubkey not in validator_pubkeys:
# Verify the deposit signature (proof of possession) which is not checked by the deposit contract
deposit_message = DepositMessage(
pubkey=deposit.data.pubkey,
withdrawal_credentials=deposit.data.withdrawal_credentials,
amount=deposit.data.amount,
)
domain = compute_domain(DOMAIN_DEPOSIT) # Fork-agnostic domain since deposits are valid across forks
signing_root = compute_signing_root(deposit_message, domain)
if not bls.Verify(pubkey, signing_root, deposit.data.signature):
return
# Add validator and balance entries
state.validators.append(get_validator_from_deposit(state, deposit))
state.balances.append(amount)
2021-03-11 15:55:55 +00:00
state.previous_epoch_participation.append(ParticipationFlags(0b0000_0000)) # [New in Altair]
state.current_epoch_participation.append(ParticipationFlags(0b0000_0000)) # [New in Altair]
2021-03-11 16:28:58 +00:00
state.leak_scores.append(0) # [New in Altair]
else:
# Increase balance by deposit amount
index = ValidatorIndex(validator_pubkeys.index(pubkey))
increase_balance(state, index, amount)
```
#### Sync committee processing
2020-11-12 09:28:05 +00:00
```python
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
def process_sync_committee(state: BeaconState, body: BeaconBlockBody) -> None:
# Verify sync committee aggregate signature signing over the previous slot block root
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
previous_slot = Slot(max(int(state.slot), 1) - 1)
committee_indices = get_sync_committee_indices(state, get_current_epoch(state))
2020-12-07 15:10:39 +00:00
participant_indices = [index for index, bit in zip(committee_indices, body.sync_committee_bits) if bit]
committee_pubkeys = state.current_sync_committee.pubkeys
participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, body.sync_committee_bits) if bit]
domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, body.sync_committee_signature)
# Reward sync committee participants
proposer_rewards = Gwei(0)
active_validator_count = uint64(len(get_active_validator_indices(state, get_current_epoch(state))))
for participant_index in participant_indices:
proposer_reward = get_proposer_reward(state, participant_index)
proposer_rewards += proposer_reward
base_reward = get_base_reward(state, participant_index)
max_participant_reward = base_reward - proposer_reward
reward = Gwei(max_participant_reward * active_validator_count // (len(committee_indices) * SLOTS_PER_EPOCH))
increase_balance(state, participant_index, reward)
# Reward beacon proposer
increase_balance(state, get_beacon_proposer_index(state), proposer_rewards)
2020-11-12 09:28:05 +00:00
```
### Epoch processing
```python
def process_epoch(state: BeaconState) -> None:
2021-03-11 13:22:38 +00:00
process_justification_and_finalization(state) # [Modified in Altair]
2021-03-11 16:28:58 +00:00
process_leak_updates(state) # [New in Altair]
2021-03-11 13:22:38 +00:00
process_rewards_and_penalties(state) # [Modified in Altair]
process_registry_updates(state)
2021-03-11 13:22:38 +00:00
process_slashings(state) # [Modified in Altair]
2021-01-27 06:42:50 +00:00
process_eth1_data_reset(state)
process_effective_balance_updates(state)
process_slashings_reset(state)
process_randao_mixes_reset(state)
process_historical_roots_update(state)
2021-03-11 13:22:38 +00:00
process_participation_flag_updates(state) # [New in Altair]
process_sync_committee_updates(state) # [New in Altair]
```
#### Justification and finalization
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
2020-12-18 23:22:11 +00:00
*Note*: The function `process_justification_and_finalization` is modified with `matching_target_attestations` replaced by `matching_target_indices`.
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
```python
2020-12-18 23:22:11 +00:00
def process_justification_and_finalization(state: BeaconState) -> None:
# Initial FFG checkpoint values have a `0x00` stub for `root`.
# Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return
previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state)
old_previous_justified_checkpoint = state.previous_justified_checkpoint
old_current_justified_checkpoint = state.current_justified_checkpoint
2020-12-18 23:22:11 +00:00
# Process justifications
state.previous_justified_checkpoint = state.current_justified_checkpoint
state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
state.justification_bits[0] = 0b0
matching_target_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, previous_epoch)
2020-12-18 23:22:11 +00:00
if get_total_balance(state, matching_target_indices) * 3 >= get_total_active_balance(state) * 2:
state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
root=get_block_root(state, previous_epoch))
state.justification_bits[1] = 0b1
matching_target_indices = get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, current_epoch)
2020-12-18 23:22:11 +00:00
if get_total_balance(state, matching_target_indices) * 3 >= get_total_active_balance(state) * 2:
state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
root=get_block_root(state, current_epoch))
state.justification_bits[0] = 0b1
2020-12-18 23:22:11 +00:00
# Process finalizations
bits = state.justification_bits
# The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
state.finalized_checkpoint = old_previous_justified_checkpoint
# The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_checkpoint = old_previous_justified_checkpoint
# The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_checkpoint = old_current_justified_checkpoint
# The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
state.finalized_checkpoint = old_current_justified_checkpoint
```
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
#### Leak scores
2021-03-09 20:21:16 +00:00
*Note*: The function `process_leak_updates` is new.
```python
2021-03-09 20:21:16 +00:00
def process_leak_updates(state: BeaconState) -> None:
matching_target_attesting_indices = get_unslashed_participating_indices(
state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)
)
for index in get_eligible_validator_indices(state):
if index in matching_target_attesting_indices:
2021-03-09 20:21:16 +00:00
if state.leak_scores[index] > 0:
state.leak_scores[index] -= 1
elif is_in_inactivity_leak(state):
2021-03-09 20:21:16 +00:00
state.leak_scores[index] += LEAK_SCORE_BIAS
```
#### Rewards and penalties
2020-12-18 23:22:11 +00:00
*Note*: The function `process_rewards_and_penalties` is modified to support the incentive reforms.
2020-12-18 23:22:11 +00:00
```python
def process_rewards_and_penalties(state: BeaconState) -> None:
# No rewards are applied at the end of `GENESIS_EPOCH` because rewards are for work done in the previous epoch
if get_current_epoch(state) == GENESIS_EPOCH:
return
flag_deltas = [
get_flag_deltas(state, flag_index, flag_numerator)
for (flag_index, flag_numerator) in get_flag_indices_and_numerators()
]
2020-12-18 23:22:11 +00:00
deltas = flag_deltas + [get_inactivity_penalty_deltas(state)]
for (rewards, penalties) in deltas:
2020-12-18 23:22:11 +00:00
for index in range(len(state.validators)):
increase_balance(state, ValidatorIndex(index), rewards[index])
decrease_balance(state, ValidatorIndex(index), penalties[index])
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
```
#### Slashings
2021-02-11 21:53:29 +00:00
2021-03-11 13:22:38 +00:00
*Note*: The function `process_slashings` is modified to use `ALTAIR_PROPORTIONAL_SLASHING_MULTIPLIER`.
2021-02-11 21:53:29 +00:00
```python
def process_slashings(state: BeaconState) -> None:
epoch = get_current_epoch(state)
total_balance = get_total_active_balance(state)
2021-03-11 13:22:38 +00:00
adjusted_total_slashing_balance = min(sum(state.slashings) * ALTAIR_PROPORTIONAL_SLASHING_MULTIPLIER, total_balance)
2021-02-11 21:53:29 +00:00
for index, validator in enumerate(state.validators):
if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
penalty = penalty_numerator // total_balance * increment
decrease_balance(state, ValidatorIndex(index), penalty)
```
#### Participation flags updates
*Note*: The function `process_participation_flag_updates` is new.
```python
def process_participation_flag_updates(state: BeaconState) -> None:
state.previous_epoch_participation = state.current_epoch_participation
state.current_epoch_participation = [ParticipationFlags(0b0000_0000) for _ in range(len(state.validators))]
```
#### Sync committee updates
executable light client patch: beacon-chain.md (#2141) * Bump remerkleable to 0.1.18 * Disable `sync-protocol.md` for now. Make linter pass * Enable lightclient tests * Use *new* `optional_fast_aggregate_verify` * Fix ToC and codespell * Do not run phase1 tests with Lightclient patch * Fix the Eth1Data casting bug. Add a workaround. * Fix `run_on_attestation` testing helper * Revert * Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify` * Apply Proto's suggestion * Apply Danny's suggestion * Fixing tests * Fix after rebasing * Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH` * New doctoc * Add lightclient patch configs * fix gitignore light client patch generator output * Upgrade state for light client patch * Add `lightclient-fork.md` to deal the fork boundary and fix `process_block_header` * Misc cleanups 1) Add a summary note for every function that is changed. 2) Avoid changing `process_block` (instead only change `process_block_header`). 3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction. 4) Misc cleanups * Update block.py * Update beacon-chain.md * Fix typo "minimal" -> "mainnet" Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com> * Use the new `BeaconBlockHeader` instead of phase 0 version * Update config files * Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody` Co-authored-by: protolambda <proto@protolambda.com> Co-authored-by: Justin <drakefjustin@gmail.com> Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
2020-12-15 05:18:20 +00:00
*Note*: The function `process_sync_committee_updates` is new.
2020-11-12 09:28:05 +00:00
```python
def process_sync_committee_updates(state: BeaconState) -> None:
next_epoch = get_current_epoch(state) + Epoch(1)
if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
state.current_sync_committee = state.next_sync_committee
state.next_sync_committee = get_sync_committee(state, next_epoch + EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
2020-11-12 09:28:05 +00:00
```