2021-08-18 23:11:38 +00:00
# Altair -- Fork Logic
2020-12-15 05:18:20 +00:00
## Table of contents
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE - RUN doctoc TO UPDATE -->
- [Introduction ](#introduction )
- [Configuration ](#configuration )
2021-03-15 16:05:13 +00:00
- [Fork to Altair ](#fork-to-altair )
2020-12-15 05:18:20 +00:00
- [Fork trigger ](#fork-trigger )
- [Upgrading the state ](#upgrading-the-state )
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Introduction
2021-08-19 13:59:05 +00:00
This document describes the process of the first upgrade of the beacon chain: the Altair hard fork, introducing light client support and other improvements.
2020-12-15 05:18:20 +00:00
## Configuration
Warning: this configuration is not definitive.
| Name | Value |
| - | - |
2021-03-11 13:22:38 +00:00
| `ALTAIR_FORK_VERSION` | `Version('0x01000000')` |
2021-09-24 18:29:34 +00:00
| `ALTAIR_FORK_EPOCH` | `Epoch(74240)` (Oct 27, 2021, 10:56:23am UTC) |
2020-12-15 05:18:20 +00:00
2021-03-15 16:05:13 +00:00
## Fork to Altair
2020-12-15 05:18:20 +00:00
### Fork trigger
2021-09-24 18:14:39 +00:00
The fork is triggered at epoch `ALTAIR_FORK_EPOCH` .
2020-12-15 05:18:20 +00:00
2021-04-21 08:42:54 +00:00
Note that for the pure Altair networks, we don't apply `upgrade_to_altair` since it starts with Altair version logic.
2021-04-20 15:37:53 +00:00
2020-12-15 05:18:20 +00:00
### Upgrading the state
2021-05-11 17:58:45 +00:00
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == ALTAIR_FORK_EPOCH` , an irregular state change is made to upgrade to Altair.
2021-05-11 20:13:22 +00:00
The upgrade occurs after the completion of the inner loop of `process_slots` that sets `state.slot` equal to `ALTAIR_FORK_EPOCH * SLOTS_PER_EPOCH` .
2021-05-18 20:50:46 +00:00
Care must be taken when transitioning through the fork boundary as implementations will need a modified [state transition function ](../phase0/beacon-chain.md#beacon-chain-state-transition-function ) that deviates from the Phase 0 document.
In particular, the outer `state_transition` function defined in the Phase 0 document will not expose the precise fork slot to execute the upgrade in the presence of skipped slots at the fork boundary. Instead the logic must be within `process_slots` .
2020-12-15 05:18:20 +00:00
```python
2021-05-13 19:21:20 +00:00
def translate_participation(state: BeaconState, pending_attestations: Sequence[phase0.PendingAttestation]) -> None:
2021-05-06 00:55:10 +00:00
for attestation in pending_attestations:
data = attestation.data
inclusion_delay = attestation.inclusion_delay
# Translate attestation inclusion info to flag indices
participation_flag_indices = get_attestation_participation_flag_indices(state, data, inclusion_delay)
# Apply flags to all attesting validators
epoch_participation = state.previous_epoch_participation
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
2021-05-13 19:21:20 +00:00
for flag_index in participation_flag_indices:
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
2021-05-06 00:55:10 +00:00
2021-03-11 13:22:38 +00:00
def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
2021-04-23 15:21:29 +00:00
epoch = phase0.get_current_epoch(pre)
2020-12-15 05:18:20 +00:00
post = BeaconState(
2021-03-09 22:16:26 +00:00
# Versioning
2020-12-15 05:18:20 +00:00
genesis_time=pre.genesis_time,
2021-01-05 16:42:01 +00:00
genesis_validators_root=pre.genesis_validators_root,
2020-12-15 05:18:20 +00:00
slot=pre.slot,
fork=Fork(
previous_version=pre.fork.current_version,
2021-03-11 13:22:38 +00:00
current_version=ALTAIR_FORK_VERSION,
2020-12-15 05:18:20 +00:00
epoch=epoch,
),
# History
latest_block_header=pre.latest_block_header,
block_roots=pre.block_roots,
state_roots=pre.state_roots,
historical_roots=pre.historical_roots,
# Eth1
eth1_data=pre.eth1_data,
eth1_data_votes=pre.eth1_data_votes,
eth1_deposit_index=pre.eth1_deposit_index,
# Registry
validators=pre.validators,
balances=pre.balances,
# Randomness
randao_mixes=pre.randao_mixes,
# Slashings
slashings=pre.slashings,
2021-03-02 01:19:12 +00:00
# Participation
2021-03-09 22:16:26 +00:00
previous_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
current_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
2020-12-15 05:18:20 +00:00
# Finality
justification_bits=pre.justification_bits,
previous_justified_checkpoint=pre.previous_justified_checkpoint,
current_justified_checkpoint=pre.current_justified_checkpoint,
finalized_checkpoint=pre.finalized_checkpoint,
2021-03-15 11:08:41 +00:00
# Inactivity
Typing problems fixes (#2271)
* Typing problem fixed: `process_block_header` passes `Bytes32()` to `state_root` of `BeaconBlockHeader`, which type is `Root`
* Typing problem fixed in `initialize_beacon_state_from_eth1`: `len` returns an `int` value, while `deposit_count=uint64` of `Eth1Data` has type `uint64`
* Typing problem fixed in `process_rewards_and_penalties`: `numerator` of type `int` passed to `weight` parameter of `get_flag_index_deltas`, which has type `uint64`
* Typing problem fixed in `process_attestation`; `False` passes as `crosslink_success` parameter of `PendingAttestation`, which has type `boolean`. `False` is an instance of `(python.)bool` and is not an instance of `(ssz.)boolean`
* Typing problem fixed: `shard_data_roots` of `ShardTransition` has type `List[Bytes32]`, but its elements are used as if they were `Root` values, e.g. in `process_chunk_challenge` method: passed to `data_root` of `CustodyChunkChallengeRecord` which has type `Root`
* Typing problem fixed in `process_custody_final_updates`: `index` has type `int`, while `validator_indices_in_records` has type `Set[ValidatorIndex]`, so tesing whether `index in validator_indices_in_records` can be risky, depending on implementation details. `ValidatorIndex(index) in validator_indices_in_records` is a safer variant.
* Typing problem fixed: `slashed` parameter of `pack_compact_validator` has type `(python.)bool`, however in `committee_to_compact_committee` a value of `(ssz.)boolean` is passed as a value of the parameter
* Typing problem fixed: `inactivity_scores` is a `List[uint64,...]`, while it is intialized/appended with values of `(python.)int` type
* fixed according to @protolambda suggestions
* changed types of _WEIGHT constants and appropriate variables/parameters, according to @protolambda suggestions
* revert code formatting back
* Introduced ZERO_ROOT according to @protolambda 's suggestion
* Reverted back to , according to @protolambda comments
2021-03-25 21:03:21 +00:00
inactivity_scores=[uint64(0) for _ in range(len(pre.validators))],
2020-12-15 05:18:20 +00:00
)
2021-05-06 00:55:10 +00:00
# Fill in previous epoch participation from the pre state's pending attestations
translate_participation(post, pre.previous_epoch_attestations)
2021-05-11 21:18:18 +00:00
2020-12-17 00:12:51 +00:00
# Fill in sync committees
2021-05-12 15:44:13 +00:00
# Note: A duplicate committee is assigned for the current and next committee at the fork boundary
post.current_sync_committee = get_next_sync_committee(post)
post.next_sync_committee = get_next_sync_committee(post)
2020-12-15 05:18:20 +00:00
return post
```