Skip to content

Commit 75f7a8a

Browse files
committed
Altair
1 parent 904968f commit 75f7a8a

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

spec/fork.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Fork Logic
2+
3+
## Table of contents
4+
5+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
6+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
7+
8+
- [Introduction](#introduction)
9+
- [Configuration](#configuration)
10+
- [Helper functions](#helper-functions)
11+
- [Misc](#misc)
12+
- [`compute_fork_version`](#compute_fork_version)
13+
- [Fork to Altair](#fork-to-altair)
14+
- [Fork trigger](#fork-trigger)
15+
- [Upgrading the state](#upgrading-the-state)
16+
17+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
18+
19+
## Introduction
20+
21+
This document describes the process of the upgrade of the beacon chain.
22+
23+
## Configuration
24+
25+
Warning: this configuration is not definitive.
26+
27+
| Name | Value |
28+
| - | - |
29+
| `ALTAIR_FORK_VERSION` | `Version('0x01000000')` |
30+
| `ALTAIR_FORK_EPOCH` | `Epoch(74240)` (Oct 27, 2021, 10:56:23am UTC) |
31+
32+
## Helper functions
33+
34+
### Misc
35+
36+
#### `compute_fork_version`
37+
38+
```python
39+
def compute_fork_version(epoch: Epoch) -> Version:
40+
"""
41+
Return the fork version at the given ``epoch``.
42+
"""
43+
if epoch >= ALTAIR_FORK_EPOCH:
44+
return ALTAIR_FORK_VERSION
45+
return GENESIS_FORK_VERSION
46+
```
47+
48+
## Fork to Altair
49+
50+
### Fork trigger
51+
52+
The fork is triggered at epoch `ALTAIR_FORK_EPOCH`.
53+
54+
Note that for the pure Altair networks, we don't apply `upgrade_to_altair` since it starts with Altair version logic.
55+
56+
### Upgrading the state
57+
58+
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.
59+
60+
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`.
61+
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.
62+
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`.
63+
64+
```python
65+
def translate_participation(state: BeaconState, pending_attestations: Sequence[phase0.PendingAttestation]) -> None:
66+
for attestation in pending_attestations:
67+
data = attestation.data
68+
inclusion_delay = attestation.inclusion_delay
69+
# Translate attestation inclusion info to flag indices
70+
participation_flag_indices = get_attestation_participation_flag_indices(state, data, inclusion_delay)
71+
72+
# Apply flags to all attesting validators
73+
epoch_participation = state.previous_epoch_participation
74+
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
75+
for flag_index in participation_flag_indices:
76+
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
77+
78+
79+
def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
80+
epoch = phase0.get_current_epoch(pre)
81+
post = BeaconState(
82+
# Versioning
83+
genesis_time=pre.genesis_time,
84+
genesis_validators_root=pre.genesis_validators_root,
85+
slot=pre.slot,
86+
fork=Fork(
87+
previous_version=pre.fork.current_version,
88+
current_version=ALTAIR_FORK_VERSION,
89+
epoch=epoch,
90+
),
91+
# History
92+
latest_block_header=pre.latest_block_header,
93+
block_roots=pre.block_roots,
94+
state_roots=pre.state_roots,
95+
historical_roots=pre.historical_roots,
96+
# Eth1
97+
eth1_data=pre.eth1_data,
98+
eth1_data_votes=pre.eth1_data_votes,
99+
eth1_deposit_index=pre.eth1_deposit_index,
100+
# Registry
101+
validators=pre.validators,
102+
balances=pre.balances,
103+
# Randomness
104+
randao_mixes=pre.randao_mixes,
105+
# Slashings
106+
slashings=pre.slashings,
107+
# Participation
108+
previous_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
109+
current_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
110+
# Finality
111+
justification_bits=pre.justification_bits,
112+
previous_justified_checkpoint=pre.previous_justified_checkpoint,
113+
current_justified_checkpoint=pre.current_justified_checkpoint,
114+
finalized_checkpoint=pre.finalized_checkpoint,
115+
# Inactivity
116+
inactivity_scores=[uint64(0) for _ in range(len(pre.validators))],
117+
)
118+
# Fill in previous epoch participation from the pre state's pending attestations
119+
translate_participation(post, pre.previous_epoch_attestations)
120+
121+
# Fill in sync committees
122+
# Note: A duplicate committee is assigned for the current and next committee at the fork boundary
123+
post.current_sync_committee = get_next_sync_committee(post)
124+
post.next_sync_committee = get_next_sync_committee(post)
125+
return post
126+
```

0 commit comments

Comments
 (0)