Skip to content

Commit 3cebedb

Browse files
gballetdankrad
andcommitted
Spec draft for the verge
Co-Authored-By: Dankrad Feist <[email protected]>
1 parent 270a66e commit 3cebedb

File tree

2 files changed

+351
-0
lines changed

2 files changed

+351
-0
lines changed

specs/verge/beacon-chain.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# The Verge -- The Beacon Chain
2+
3+
## Table of contents
4+
5+
<!-- TOC -->
6+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
7+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
8+
9+
- [Introduction](#introduction)
10+
- [Custom types](#custom-types)
11+
- [Preset](#preset)
12+
- [Execution](#execution)
13+
- [Containers](#containers)
14+
- [Extended containers](#extended-containers)
15+
- [`ExecutionPayload`](#executionpayload)
16+
- [`ExecutionPayloadHeader`](#executionpayloadheader)
17+
- [New containers](#new-containers)
18+
- [`SuffixStateDiff`](#suffixstatediff)
19+
- [`StemStateDiff`](#stemstatediff)
20+
- [`IPAProof`](#ipaproof)
21+
- [`VerkleProof`](#verkleproof)
22+
- [`ExecutionWitness`](#executionwitness)
23+
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
24+
- [Execution engine](#execution-engine)
25+
- [`notify_new_payload`](#notify_new_payload)
26+
- [Block processing](#block-processing)
27+
- [Execution payload](#execution-payload)
28+
- [`process_execution_payload`](#process_execution_payload)
29+
- [Testing](#testing)
30+
31+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
32+
<!-- /TOC -->
33+
34+
## Introduction
35+
36+
This upgrade adds transaction execution to the beacon chain as part of the Verge upgrade.
37+
38+
## Custom types
39+
40+
| Name | SSZ equivalent | Description |
41+
| - | - | - |
42+
| `StateDiff` | `List[StemStateDiff, MAX_STEMS]` | Only valid if list is sorted by stems |
43+
| `BandersnatchGroupElement` | `Bytes32` | |
44+
| `BandersnatchFieldElement` | `Bytes32` | |
45+
| `Stem` | `Bytes31` | |
46+
47+
## Preset
48+
49+
### Execution
50+
51+
| Name | Value |
52+
| - | - |
53+
| `MAX_STEMS` | `2**16` |
54+
| `MAX_COMMITMENTS_PER_STEM` | `33` |
55+
| `VERKLE_WIDTH` | `256` |
56+
| `IPA_PROOF_DEPTH` | `8` |
57+
58+
## Containers
59+
60+
### Extended containers
61+
62+
#### `ExecutionPayload`
63+
64+
```python
65+
class ExecutionPayload(Container):
66+
# Execution block header fields
67+
parent_hash: Hash32
68+
fee_recipient: ExecutionAddress # 'beneficiary' in the yellow paper
69+
state_root: Bytes32
70+
receipts_root: Bytes32
71+
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
72+
prev_randao: Bytes32 # 'difficulty' in the yellow paper
73+
block_number: uint64 # 'number' in the yellow paper
74+
gas_limit: uint64
75+
gas_used: uint64
76+
timestamp: uint64
77+
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
78+
base_fee_per_gas: uint256
79+
block_hash: Hash32 # Hash of execution block
80+
# Extra payload field
81+
execution_witness: ExecutionWitness
82+
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
83+
```
84+
85+
#### `ExecutionPayloadHeader`
86+
87+
```python
88+
class ExecutionPayloadHeader(Container):
89+
# Execution block header fields
90+
parent_hash: Hash32
91+
fee_recipient: ExecutionAddress
92+
state_root: Bytes32
93+
receipts_root: Bytes32
94+
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
95+
prev_randao: Bytes32
96+
block_number: uint64
97+
gas_limit: uint64
98+
gas_used: uint64
99+
timestamp: uint64
100+
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
101+
base_fee_per_gas: uint256
102+
block_hash: Hash32 # Hash of execution block
103+
transactions_root: Root
104+
# Extra payload fields
105+
execution_witness: ExecutionWitness
106+
```
107+
108+
### New containers
109+
110+
#### `SuffixStateDiff`
111+
112+
```python
113+
class SuffixStateDiff(Container):
114+
suffix: Byte
115+
116+
# Null means not currently present
117+
current_value: Union[Null, Bytes32]
118+
119+
# Null means value not updated
120+
new_value: Union[Null, Bytes32]
121+
```
122+
123+
*Note*: on the Kaustinen testnet, `new_value` is ommitted from the container.
124+
125+
#### `StemStateDiff`
126+
127+
```python
128+
class StemStateDiff(Container):
129+
stem: Stem
130+
# Valid only if list is sorted by suffixes
131+
suffix_diffs: List[SuffixStateDiff, VERKLE_WIDTH]
132+
```
133+
134+
```python
135+
# Valid only if list is sorted by stems
136+
StateDiff = List[StemStateDiff, MAX_STEMS]
137+
```
138+
139+
#### `IPAProof`
140+
141+
```python
142+
class IpaProof(Container):
143+
C_L = Vector[BandersnatchGroupElement, IPA_PROOF_DEPTH]
144+
C_R = Vector[BandersnatchGroupElement, IPA_PROOF_DEPTH]
145+
final_evaluation = BandersnatchFieldElement
146+
```
147+
148+
#### `VerkleProof`
149+
150+
```python
151+
class VerkleProof(Container):
152+
other_stems: List[Bytes32, MAX_STEMS]
153+
depth_extension_present: List[uint8, MAX_STEMS]
154+
commitments_by_path: List[BandersnatchGroupElement, MAX_STEMS * MAX_COMMITMENTS_PER_STEM]
155+
D: BandersnatchGroupElement
156+
ipa_proof: IpaProof
157+
```
158+
159+
#### `ExecutionWitness`
160+
161+
```python
162+
class ExecutionWitness(container):
163+
state_diff: StateDiff
164+
verkle_proof: VerkleProof
165+
```
166+
167+
## Beacon chain state transition function
168+
169+
### Block processing
170+
171+
#### Execution payload
172+
173+
##### `process_execution_payload`
174+
175+
```python
176+
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
177+
# Verify consistency of the parent hash with respect to the previous execution payload header
178+
if is_merge_transition_complete(state):
179+
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
180+
# Verify prev_randao
181+
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
182+
# Verify timestamp
183+
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
184+
# Verify the execution payload is valid
185+
assert execution_engine.notify_new_payload(payload)
186+
# Cache execution payload header
187+
state.latest_execution_payload_header = ExecutionPayloadHeader(
188+
parent_hash=payload.parent_hash,
189+
fee_recipient=payload.fee_recipient,
190+
state_root=payload.state_root,
191+
receipts_root=payload.receipts_root,
192+
logs_bloom=payload.logs_bloom,
193+
prev_randao=payload.prev_randao,
194+
block_number=payload.block_number,
195+
gas_limit=payload.gas_limit,
196+
gas_used=payload.gas_used,
197+
timestamp=payload.timestamp,
198+
extra_data=payload.extra_data,
199+
base_fee_per_gas=payload.base_fee_per_gas,
200+
block_hash=payload.block_hash,
201+
transactions_root=hash_tree_root(payload.transactions),
202+
execution_witness=payload.execution_witness,
203+
)
204+
```
205+
206+
## Testing
207+
208+
TBD

specs/verge/fork.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# The Verge -- 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+
- [Modified `compute_fork_version`](#modified-compute_fork_version)
13+
- [Fork to the Verge](#fork-to-capella)
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 Verge upgrade.
22+
23+
## Configuration
24+
25+
Warning: this configuration is not definitive.
26+
27+
| Name | Value |
28+
| - | - |
29+
| `VERGE_FORK_VERSION` | `Version('0x05000000')` |
30+
| `VERGE_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
31+
32+
33+
## Helper functions
34+
35+
### Misc
36+
37+
#### Modified `compute_fork_version`
38+
39+
```python
40+
def compute_fork_version(epoch: Epoch) -> Version:
41+
"""
42+
Return the fork version at the given ``epoch``.
43+
"""
44+
if epoch >= VERGE_FORK_EPOCH:
45+
return VERGE_FORK_VERSION
46+
if epoch >= CAPELLA_FORK_EPOCH:
47+
return CAPELLA_FORK_VERSION
48+
if epoch >= BELLATRIX_FORK_EPOCH:
49+
return BELLATRIX_FORK_VERSION
50+
if epoch >= ALTAIR_FORK_EPOCH:
51+
return ALTAIR_FORK_VERSION
52+
return GENESIS_FORK_VERSION
53+
```
54+
55+
## Fork to the Verge
56+
57+
### Fork trigger
58+
59+
The fork is triggered at epoch `VERGE_FORK_EPOCH`.
60+
61+
Note that for the pure verge networks, we don't apply `upgrade_to_verge` since it starts with the Verge version logic.
62+
63+
### Upgrading the state
64+
65+
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == VERGE_FORK_EPOCH`,
66+
an irregular state change is made to upgrade to the Verge.
67+
68+
The upgrade occurs after the completion of the inner loop of `process_slots` that sets `state.slot` equal to `VERGE_FORK_EPOCH * SLOTS_PER_EPOCH`.
69+
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.
70+
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`.
71+
72+
```python
73+
def upgrade_to_verge(pre: capella.BeaconState) -> BeaconState:
74+
epoch = capella.get_current_epoch(pre)
75+
latest_execution_payload_header = ExecutionPayloadHeader(
76+
parent_hash=pre.latest_execution_payload_header.parent_hash,
77+
fee_recipient=pre.latest_execution_payload_header.fee_recipient,
78+
state_root=pre.latest_execution_payload_header.state_root,
79+
receipts_root=pre.latest_execution_payload_header.receipts_root,
80+
logs_bloom=pre.latest_execution_payload_header.logs_bloom,
81+
prev_randao=pre.latest_execution_payload_header.prev_randao,
82+
block_number=pre.latest_execution_payload_header.block_number,
83+
gas_limit=pre.latest_execution_payload_header.gas_limit,
84+
gas_used=pre.latest_execution_payload_header.gas_used,
85+
timestamp=pre.latest_execution_payload_header.timestamp,
86+
extra_data=pre.latest_execution_payload_header.extra_data,
87+
base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas,
88+
block_hash=pre.latest_execution_payload_header.block_hash,
89+
transactions_root=pre.latest_execution_payload_header.transactions_root,
90+
withdrawals_root=pre.latest_execution_payload_header.withdrawals_root,
91+
execution_witness=ExecutionWitness([], []) # New in the Verge
92+
)
93+
post = BeaconState(
94+
# Versioning
95+
genesis_time=pre.genesis_time,
96+
genesis_validators_root=pre.genesis_validators_root,
97+
slot=pre.slot,
98+
fork=Fork(
99+
previous_version=pre.fork.current_version,
100+
current_version=VERGE_FORK_VERSION,
101+
epoch=epoch,
102+
),
103+
# History
104+
latest_block_header=pre.latest_block_header,
105+
block_roots=pre.block_roots,
106+
state_roots=pre.state_roots,
107+
historical_roots=pre.historical_roots,
108+
# Eth1
109+
eth1_data=pre.eth1_data,
110+
eth1_data_votes=pre.eth1_data_votes,
111+
eth1_deposit_index=pre.eth1_deposit_index,
112+
# Registry
113+
validators=pre.validators,
114+
balances=pre.balances,
115+
# Randomness
116+
randao_mixes=pre.randao_mixes,
117+
# Slashings
118+
slashings=pre.slashings,
119+
# Participation
120+
previous_epoch_participation=pre.previous_epoch_participation,
121+
current_epoch_participation=pre.current_epoch_participation,
122+
# Finality
123+
justification_bits=pre.justification_bits,
124+
previous_justified_checkpoint=pre.previous_justified_checkpoint,
125+
current_justified_checkpoint=pre.current_justified_checkpoint,
126+
finalized_checkpoint=pre.finalized_checkpoint,
127+
# Inactivity
128+
inactivity_scores=pre.inactivity_scores,
129+
# Sync
130+
current_sync_committee=pre.current_sync_committee,
131+
next_sync_committee=pre.next_sync_committee,
132+
# Execution-layer
133+
latest_execution_payload_header=latest_execution_payload_header,
134+
# Withdrawals
135+
next_withdrawal_index=pre.next_withdrawal_index,
136+
next_withdrawal_validator_index=pre.next_withdrawal_validator_index,
137+
# Deep history valid from Capella onwards
138+
# FIXME most likely wrong
139+
historical_summaries=List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]([]), # [New in Capella]
140+
)
141+
142+
return post
143+
```

0 commit comments

Comments
 (0)