add `historical_state_roots`

* enables proving the state for empty slots
* allows verifying the backfilled fields against the previous
`historical_roots` field
* allows trivially computing `historical_roots`, for any existing use
cases
This commit is contained in:
Jacek Sieka 2021-05-24 20:03:24 +02:00
parent 6b20da3d24
commit 96dc7f6061
No known key found for this signature in database
GPG Key ID: A1B09461ABB656B8
4 changed files with 20 additions and 30 deletions

View File

@ -1,10 +1,5 @@
# Mainnet preset - Altair
# State vector lengths
# ---------------------------------------------------------------
# 2**24 (= 16,777,216) historical roots, ~26,131 years
HISTORICAL_BLOCK_ROOTS_LIMIT: 16777216
# Updated penalty values
# ---------------------------------------------------------------
# 3 * 2**24 (= 50,331,648)

View File

@ -1,10 +1,5 @@
# Minimal preset - Altair
# State vector lengths
# ---------------------------------------------------------------
# 2**24 (= 16,777,216) historical roots, ~26,131 years
HISTORICAL_BLOCK_ROOTS_LIMIT: 16777216
# Updated penalty values
# ---------------------------------------------------------------
# 3 * 2**24 (= 50,331,648)

View File

@ -16,7 +16,6 @@
- [Preset](#preset)
- [Updated penalty values](#updated-penalty-values)
- [Sync committee](#sync-committee)
- [State list lengths](#state-list-lengths)
- [Configuration](#configuration)
- [Inactivity penalties](#inactivity-penalties)
- [Containers](#containers)
@ -133,12 +132,6 @@ This patch updates a few configuration values to move penalty parameters closer
| `SYNC_COMMITTEE_SIZE` | `uint64(2**9)` (= 512) | Validators | |
| `EPOCHS_PER_SYNC_COMMITTEE_PERIOD` | `uint64(2**9)` (= 512) | epochs | ~54 hours |
### State list lengths
| Name | Value | Unit | Duration |
| - | - | :-: | :-: |
| `HISTORICAL_BLOCK_ROOTS_LIMIT` | `uint64(2**24)` (= 16,777,216) | historical roots | ~52,262 years |
## Configuration
### Inactivity penalties
@ -182,8 +175,8 @@ class BeaconState(Container):
latest_block_header: BeaconBlockHeader
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
historical_root: Root
historical_block_roots: List[Root, HISTORICAL_BLOCK_ROOTS_LIMIT]
historical_block_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
historical_state_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
# Eth1
eth1_data: Eth1Data
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
@ -607,7 +600,7 @@ def process_epoch(state: BeaconState) -> None:
process_effective_balance_updates(state)
process_slashings_reset(state)
process_randao_mixes_reset(state)
process_historical_block_roots_update(state)
process_historical_roots_update(state)
process_participation_flag_updates(state) # [New in Altair]
process_sync_committee_updates(state) # [New in Altair]
```
@ -698,14 +691,15 @@ def process_participation_flag_updates(state: BeaconState) -> None:
#### Historical roots updates
*Note*: The function `process_historical_block_roots_update` is new and replaces the `process_historical_roots_update` function from phase0.
*Note*: The function `process_historical_roots_update` changes definition compared to phase0.
```python
def process_historical_block_roots_update(state: BeaconState) -> None:
def process_historical_roots_update(state: BeaconState) -> None:
# Set historical block root accumulator
next_epoch = Epoch(get_current_epoch(state) + 1)
if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
state.historical_block_roots.append(hash_tree_root(state.block_roots))
state.historical_state_roots.append(hash_tree_root(state.state_roots))
```
#### Sync committee updates

View File

@ -58,13 +58,17 @@ def translate_participation(state: BeaconState, pending_attestations: Sequence[p
for flag_index in participation_flag_indices:
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
def backfill_historical_block_roots(pre: BeaconState) -> List[Root, HISTORICAL_BLOCK_ROOTS_LIMIT]:
# Split historical blocks into chunks of SLOTS_PER_HISTORICAL_ROOT
# For each chunk, compute hash_tree_root(chunk) and add to returned list
# For new altair-based chains, use an empty list
# Backfilling requires access to external block storage.
def backfill_historical_roots(state: BeaconState, pre: BeaconState) -> None:
# Clients need to recreate `historical_block_roots` and
# `historical_state_roots` from their history. A large part can be
# precalculated and verified against historical_roots in state.
# Before the fork, clients should start collecting the part that has not
# been pre-calculated.
#
# The calclulated split historical roots can be verified against the existing
# historical_roots field up to the fork.
return []
def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
epoch = phase0.get_current_epoch(pre)
@ -82,8 +86,8 @@ def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
latest_block_header=pre.latest_block_header,
block_roots=pre.block_roots,
state_roots=pre.state_roots,
historical_root=hash_tree_root(pre.historical_roots),
historical_block_roots=backfill_historical_block_roots(pre),
historical_block_roots=[],
historical_state_roots=[],
# Eth1
eth1_data=pre.eth1_data,
eth1_data_votes=pre.eth1_data_votes,
@ -109,6 +113,8 @@ def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
# Fill in previous epoch participation from the pre state's pending attestations
translate_participation(post, pre.previous_epoch_attestations)
backfill_historical_roots(post, pre)
# Fill in sync committees
# 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)