Rebase Capella on EIP-4844
This also introduces an `ENABLE_WITHDRAWALS` feature-flag to allow implementers test EIP-4844 without including Capella-specific state changes.
This commit is contained in:
parent
6181035d5d
commit
242e1b73bb
|
@ -15,6 +15,7 @@
|
|||
- [Domain types](#domain-types)
|
||||
- [Preset](#preset)
|
||||
- [Execution](#execution)
|
||||
- [Test Parameters](#test-parameters)
|
||||
- [Configuration](#configuration)
|
||||
- [Containers](#containers)
|
||||
- [Extended containers](#extended-containers)
|
||||
|
@ -27,9 +28,11 @@
|
|||
- [`tx_peek_blob_versioned_hashes`](#tx_peek_blob_versioned_hashes)
|
||||
- [`verify_kzg_commitments_against_transactions`](#verify_kzg_commitments_against_transactions)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Epoch processing](#epoch-processing)
|
||||
- [Block processing](#block-processing)
|
||||
- [Execution payload](#execution-payload)
|
||||
- [`process_execution_payload`](#process_execution_payload)
|
||||
- [Modified `process_operations`](#modified-process_operations)
|
||||
- [Blob KZG commitments](#blob-kzg-commitments)
|
||||
- [Testing](#testing)
|
||||
|
||||
|
@ -38,7 +41,7 @@
|
|||
|
||||
## Introduction
|
||||
|
||||
This upgrade adds blobs to the beacon chain as part of EIP-4844.
|
||||
This upgrade adds blobs to the beacon chain as part of EIP-4844. This is an extension of the Capella upgrade. We introduce a new feature flag, `ENABLE_WITHDRAWALS`, to disable Capella-specific updates to the state transition function. This is done to minimize Capella specific issues that may arise during testing. `ENABLE_WITHDRAWALS` will be removed in the final upgrade specification.
|
||||
|
||||
## Custom types
|
||||
|
||||
|
@ -72,6 +75,10 @@ This upgrade adds blobs to the beacon chain as part of EIP-4844.
|
|||
| - | - |
|
||||
| `MAX_BLOBS_PER_BLOCK` | `uint64(2**4)` (= 16) |
|
||||
|
||||
### Test Parameters
|
||||
| Name | Value |
|
||||
| `ENABLE_WITHDRAWALS` | `uint64(0)` |
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
|
@ -97,6 +104,7 @@ class BeaconBlockBody(Container):
|
|||
sync_aggregate: SyncAggregate
|
||||
# Execution
|
||||
execution_payload: ExecutionPayload
|
||||
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
|
||||
blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] # [New in EIP-4844]
|
||||
```
|
||||
|
||||
|
@ -121,6 +129,7 @@ class ExecutionPayload(Container):
|
|||
# Extra payload fields
|
||||
block_hash: Hash32 # Hash of execution block
|
||||
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
|
||||
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
|
||||
```
|
||||
|
||||
#### `ExecutionPayloadHeader`
|
||||
|
@ -144,6 +153,7 @@ class ExecutionPayloadHeader(Container):
|
|||
# Extra payload fields
|
||||
block_hash: Hash32 # Hash of execution block
|
||||
transactions_root: Root
|
||||
withdrawals_root: Root
|
||||
```
|
||||
|
||||
## Helper functions
|
||||
|
@ -192,13 +202,37 @@ def verify_kzg_commitments_against_transactions(transactions: Sequence[Transacti
|
|||
|
||||
## Beacon chain state transition function
|
||||
|
||||
### Epoch processing
|
||||
|
||||
```python
|
||||
def process_epoch(state: BeaconState) -> None:
|
||||
process_justification_and_finalization(state)
|
||||
process_inactivity_updates(state)
|
||||
process_rewards_and_penalties(state)
|
||||
process_registry_updates(state)
|
||||
process_slashings(state)
|
||||
process_eth1_data_reset(state)
|
||||
process_effective_balance_updates(state)
|
||||
process_slashings_reset(state)
|
||||
process_randao_mixes_reset(state)
|
||||
process_historical_roots_update(state)
|
||||
process_participation_flag_updates(state)
|
||||
process_sync_committee_updates(state)
|
||||
if ENABLE_WITHDRAWALS:
|
||||
process_full_withdrawals(state)
|
||||
process_partial_withdrawals(state)
|
||||
```
|
||||
|
||||
|
||||
### Block processing
|
||||
|
||||
```python
|
||||
def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||
process_block_header(state, block)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE)
|
||||
if ENABLE_WITHDRAWALS: # [New in EIP-4844]
|
||||
process_withdrawals(state, block.body.execution_payload)
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [Modified in EIP-4844]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body)
|
||||
|
@ -221,6 +255,7 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
assert execution_engine.notify_new_payload(payload)
|
||||
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
parent_hash=payload.parent_hash,
|
||||
|
@ -238,9 +273,32 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
excess_blobs=payload.excess_blobs, # [New in EIP-4844]
|
||||
block_hash=payload.block_hash,
|
||||
transactions_root=hash_tree_root(payload.transactions),
|
||||
)
|
||||
withdrawals_root=hash_tree_root(payload.withdrawals) if ENABLE_WITHDRAWALS else Bytes32(), # [New in EIP-4844]
|
||||
```
|
||||
|
||||
#### Modified `process_operations`
|
||||
|
||||
*Note*: The function `process_operations` is modified to feature flag Withdrawals.
|
||||
|
||||
```python
|
||||
def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
# Verify that outstanding deposits are processed up to the maximum number of deposits
|
||||
assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
|
||||
|
||||
def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None:
|
||||
for operation in operations:
|
||||
fn(state, operation)
|
||||
|
||||
for_ops(body.proposer_slashings, process_proposer_slashing)
|
||||
for_ops(body.attester_slashings, process_attester_slashing)
|
||||
for_ops(body.attestations, process_attestation)
|
||||
for_ops(body.deposits, process_deposit)
|
||||
for_ops(body.voluntary_exits, process_voluntary_exit)
|
||||
if ENABLE_WITHDRAWALS: # [New in EIP-4844]
|
||||
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
|
||||
```
|
||||
|
||||
|
||||
#### Blob KZG commitments
|
||||
|
||||
```python
|
||||
|
|
|
@ -44,6 +44,8 @@ def compute_fork_version(epoch: Epoch) -> Version:
|
|||
"""
|
||||
if epoch >= EIP4844_FORK_EPOCH:
|
||||
return EIP4844_FORK_VERSION
|
||||
if epoch >= CAPELLA_FORK_EPOCH:
|
||||
return CAPELLA_FORK_VERSION
|
||||
if epoch >= BELLATRIX_FORK_EPOCH:
|
||||
return BELLATRIX_FORK_VERSION
|
||||
if epoch >= ALTAIR_FORK_EPOCH:
|
||||
|
@ -62,12 +64,11 @@ Note that for the pure EIP-4844 networks, we don't apply `upgrade_to_eip4844` si
|
|||
|
||||
### Upgrading the state
|
||||
|
||||
Since the `eip4844.BeaconState` format is equal to the `bellatrix.BeaconState` format, we only have to update `BeaconState.fork`.
|
||||
Since the `eip4844.BeaconState` format is equal to the `Capella.BeaconState` format, we only have to update `BeaconState.fork`.
|
||||
|
||||
```python
|
||||
def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState:
|
||||
# TODO: if Capella gets scheduled, add sync it with Capella.BeaconState
|
||||
epoch = bellatrix.get_current_epoch(pre)
|
||||
def upgrade_to_eip4844(pre: Capella.BeaconState) -> BeaconState:
|
||||
epoch = capella.get_current_epoch(pre)
|
||||
post = BeaconState(
|
||||
# Versioning
|
||||
genesis_time=pre.genesis_time,
|
||||
|
@ -109,6 +110,10 @@ def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState:
|
|||
next_sync_committee=pre.next_sync_committee,
|
||||
# Execution-layer
|
||||
latest_execution_payload_header=pre.latest_execution_payload_header,
|
||||
# Withdrawals
|
||||
withdrawal_queue=[],
|
||||
next_withdrawal_index=WithdrawalIndex(0),
|
||||
next_partial_withdrawal_validator_index=ValidatorIndex(0),
|
||||
)
|
||||
|
||||
return post
|
||||
|
|
|
@ -67,7 +67,7 @@ Some gossip meshes are upgraded in the fork of EIP4844 to support upgraded types
|
|||
Topics follow the same specification as in prior upgrades.
|
||||
All topics remain stable except the beacon block topic which is updated with the modified type.
|
||||
|
||||
The specification around the creation, validation, and dissemination of messages has not changed from the Bellatrix document unless explicitly noted here.
|
||||
The specification around the creation, validation, and dissemination of messages has not changed from the Capella document unless explicitly noted here.
|
||||
|
||||
The derivation of the `message-id` remains stable.
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
- [`BlobsAndCommitments`](#blobsandcommitments)
|
||||
- [`PolynomialAndCommitment`](#polynomialandcommitment)
|
||||
- [Helpers](#helpers)
|
||||
- [Protocols](#protocols)
|
||||
- [`ExecutionEngine`](#executionengine)
|
||||
- [`get_payload`](#get_payload)
|
||||
- [`is_data_available`](#is_data_available)
|
||||
- [`hash_to_bls_field`](#hash_to_bls_field)
|
||||
- [`compute_powers`](#compute_powers)
|
||||
|
@ -27,6 +30,7 @@
|
|||
- [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody)
|
||||
- [Blob KZG commitments](#blob-kzg-commitments)
|
||||
- [Beacon Block publishing time](#beacon-block-publishing-time)
|
||||
- [ExecutionPayload](#executionpayload)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
@ -37,7 +41,7 @@ This document represents the changes to be made in the code of an "honest valida
|
|||
|
||||
## Prerequisites
|
||||
|
||||
This document is an extension of the [Bellatrix -- Honest Validator](../bellatrix/validator.md) guide.
|
||||
This document is an extension of the [Capella -- Honest Validator](../capella/validator.md) guide.
|
||||
All behaviors and definitions defined in this document, and documents it extends, carry over unless explicitly noted or overridden.
|
||||
|
||||
All terminology, constants, functions, and protocol mechanics defined in the updated [Beacon Chain doc of EIP4844](./beacon-chain.md) are requisite for this document and used throughout.
|
||||
|
@ -70,6 +74,14 @@ class PolynomialAndCommitment(Container):
|
|||
|
||||
## Helpers
|
||||
|
||||
## Protocols
|
||||
|
||||
### `ExecutionEngine`
|
||||
|
||||
#### `get_payload`
|
||||
|
||||
`get_payload` returns the upgraded EIP-4844 `ExecutionPayload` type.
|
||||
|
||||
### `is_data_available`
|
||||
|
||||
The implementation of `is_data_available` is meant to change with later sharding upgrades.
|
||||
|
@ -200,7 +212,7 @@ Namely, the blob handling and the addition of `BlobsSidecar`.
|
|||
|
||||
##### Blob KZG commitments
|
||||
|
||||
1. After retrieving the execution payload from the execution engine as specified in Bellatrix,
|
||||
1. After retrieving the execution payload from the execution engine as specified in Capella,
|
||||
use the `payload_id` to retrieve `blobs` and `blob_kzg_commitments` via `get_blobs_and_kzg_commitments(payload_id)`.
|
||||
2. Validate `blobs` and `blob_kzg_commitments`:
|
||||
|
||||
|
@ -252,3 +264,46 @@ The validator MUST hold on to blobs for `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS`
|
|||
to ensure the data-availability of these blobs throughout the network.
|
||||
|
||||
After `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS` nodes MAY prune the blobs and/or stop serving them.
|
||||
|
||||
##### ExecutionPayload
|
||||
|
||||
`ExecutionPayload`s are constructed as they were in Capella, except that we allow withdrawals to be disabled for testing.
|
||||
|
||||
```python
|
||||
def prepare_execution_payload(state: BeaconState,
|
||||
pow_chain: Dict[Hash32, PowBlock],
|
||||
safe_block_hash: Hash32,
|
||||
finalized_block_hash: Hash32,
|
||||
suggested_fee_recipient: ExecutionAddress,
|
||||
execution_engine: ExecutionEngine) -> Optional[PayloadId]:
|
||||
if not is_merge_transition_complete(state):
|
||||
is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32()
|
||||
is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
||||
if is_terminal_block_hash_set and not is_activation_epoch_reached:
|
||||
# Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed
|
||||
return None
|
||||
|
||||
terminal_pow_block = get_terminal_pow_block(pow_chain)
|
||||
if terminal_pow_block is None:
|
||||
# Pre-merge, no prepare payload call is needed
|
||||
return None
|
||||
# Signify merge via producing on top of the terminal PoW block
|
||||
parent_hash = terminal_pow_block.block_hash
|
||||
else:
|
||||
# Post-merge, normal payload
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_timestamp_at_slot(state, state.slot),
|
||||
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
||||
suggested_fee_recipient=suggested_fee_recipient,
|
||||
withdrawals=get_expected_withdrawals(state) if ENABLE_WITHDRAWALS else None, # [New in EIP-4844]
|
||||
)
|
||||
return execution_engine.notify_forkchoice_updated(
|
||||
head_block_hash=parent_hash,
|
||||
safe_block_hash=safe_block_hash,
|
||||
finalized_block_hash=finalized_block_hash,
|
||||
payload_attributes=payload_attributes,
|
||||
)
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue