diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 006e960b3de33..857294e0586d9 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: Core created: 2024-04-15 -requires: 7495, 7549 +requires: 6110, 7002, 7251, 7495, 7549, 7569 --- ## Abstract @@ -34,9 +34,9 @@ For each converted data structure, a new fork agnostic `StableContainer` type `B - Each `StableContainer` is assigned a capacity to represent its potential design space that SHALL NOT change across future forks; if it is later determined that it is insufficient, a new field can be added to contain additional fields in a sub-container. - The `StableContainer` starts as a copy of the latest fork's `Container` equivalent, except that all field types `T` are wrapped into `Optional[T]`. - To guarantee forward and backward compatibility, new fields from future forks MUST only be appended to the `StableContainer` definition. -- The type of existing fields MUST NOT change, including the capacity of `List`/`Bitlist`. If a change is necessary, the old field SHALL NOT be used anymore and a `_v2` field SHALL be considered. It is important to anticipate potential future extensions when deciding on the capacities of the `StableContainer[N]` itself and of the various lists. +- The type of existing fields MUST NOT change, including the capacity of `List`/`Bitlist`. If a change is necessary, the old field SHALL NOT be used anymore and a new field with a new name SHALL be considered. It is important to anticipate potential future extensions when deciding on the capacities of the `StableContainer` itself and of the various lists. - For `List`/`Bitlist`, the opportunity SHOULD be used to re-evaluate their design space capacity. If the design space is increased, application logic SHALL check the fork specific length limit; the SSZ library solely defines the merkleization limit, not the serialization limit. -- The conversion process is repeated for each field type. All field types referred to by the `StableContainer[N]` MUST be `StableContainer` themselves, or be considered immutable (e.g., a `uint64`). +- The conversion process is repeated for each field type. All field types referred to by the `StableContainer` MUST be `StableContainer` themselves, or are considered immutable. Subsequently, for each `StableContainer` base type `B`, a fork specific `Profile[B]` type is introduced that matches the latest fork's `Container` equivalent. The old `Container` is no longer necessary. The SSZ serialization of `Profile` is compatible with `Container`, but the merkleization and `hash_tree_root` are computed differently. Furthermore, `Profile` MAY use fields of `Optional` type if necessary. @@ -46,7 +46,52 @@ Subsequent forks specify a new `Profile`. - If old fields are deprecated, they are kept in the `StableContainer` to retain the stable merkleization scheme. In the new fork's `Profile`, the field is omitted from the definition. The SSZ library guarantees that `hash_tree_root` and all generalized indices remain the same. - Other fields MAY be changed between `T` (required) and `Optional[T]` (optional) in the new fork's `Profile`. No changes to the `StableContainer` are required for such changes. -### Limits +### Immutable types + +These types are used as part of the `StableContainer` definitions, and, as they are not `StableContainer` themselves, are considered to have immutable Merkleization. If a future fork requires changing these types in an incompatible way, a new type SHALL be defined and assigned a new field name. + +| Type | Description | +| - | - | +| [`Slot`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Slot number on the beacon chain | +| [`Epoch`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Epoch number on the beacon chain, a group of slots | +| [`CommitteeIndex`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Index of a committee within a slot | +| [`ValidatorIndex`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Unique index of a beacon chain validator | +| [`Gwei`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Amount in Gwei (1 ETH = 10^9 Gwei = 10^18 Wei) | +| [`Root`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Byte vector containing an SSZ Merkle root | +| [`Hash32`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Byte vector containing an opaque 32-byte hash | +| [`Version`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Consensus fork version number | +| [`BLSPubkey`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Cryptographic type representing a BLS12-381 public key | +| [`BLSSignature`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#custom-types) | Cryptographic type representing a BLS12-381 signature | +| [`KZGCommitment`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/_features/sharding/polynomial-commitments.md#custom-types) | G1 curve point for the KZG polynomial commitment scheme | +| [`Fork`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#fork) | Consensus fork information | +| [`Checkpoint`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#checkpoint) | Tuple referring to the most recent beacon block up through an epoch's start slot | +| [`Validator`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#validator) | Information about a beacon chain validator | +| [`AttestationData`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#attestationdata) | Vote that attests to the availability and validity of a particular consensus block | +| [`Eth1Data`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#eth1data) | Target tracker for importing deposits from transaction logs | +| [`DepositData`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#depositdata) | Log data emitted as part of a transaction's receipt when depositing to the beacon chain | +| [`BeaconBlockHeader`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#beaconblockheader) | Consensus block header | +| [`ProposerSlashing`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#proposerslashing) | Tuple of two equivocating consensus block headers | +| [`Deposit`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#deposit) | Tuple of deposit data and its inclusion proof | +| [`VoluntaryExit`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#voluntaryexit) | Consensus originated request to exit a validator from the beacon chain | +| [`SignedVoluntaryExit`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#signedvoluntaryexit) | Tuple of voluntary exit request and its signature | +| [`SyncAggregate`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/beacon-chain.md#syncaggregate) | Cryptographic type representing an aggregate sync committee signature | +| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/bellatrix/beacon-chain.md#custom-types) | Byte vector containing an account address on the execution layer | +| [`Transaction`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/bellatrix/beacon-chain.md#custom-types) | Byte list containing an RLP encoded transaction | +| [`WithdrawalIndex`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/capella/beacon-chain.md#custom-types) | Unique index of a withdrawal from any validator's balance to the execution layer | +| [`Withdrawal`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/capella/beacon-chain.md#withdrawal) | Withdrawal from a beacon chain validator's balance to the execution layer | +| [`DepositReceipt`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#depositreceipt) | Tuple of flattened deposit data and its sequential index | +| [`ExecutionLayerWithdrawalRequest`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#executionlayerwithdrawalrequest) | Execution originated request to withdraw from a validator to the execution layer | +| [`BLSToExecutionChange`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/capella/beacon-chain.md#blstoexecutionchange) | Request to register the withdrawal account address of a beacon chain validator | +| [`SignedBLSToExecutionChange`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/capella/beacon-chain.md#signedblstoexecutionchange) | Tuple of withdrawal account address registration request and its signature | +| [`Consolidation`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#consolidation) | Request to consolidate the balances of two beacon chain validators into one | +| [`SignedConsolidation`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#signedconsolidation) | Tuple of consolidation request and its signature | +| [`ParticipationFlags`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/beacon-chain.md#custom-types) | Participation tracker of a beacon chain validator within an epoch | +| [`HistoricalSummary`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/capella/beacon-chain.md#historicalsummary) | Tuple combining a historical block root and historical state root | +| [`PendingBalanceDeposit`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#pendingbalancedeposit) | Pending operation for depositing to a beacon chain validator | +| [`PendingPartialWithdrawal`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#pendingpartialwithdrawal) | Pending operation for withdrawing from a beacon chain validator | +| [`PendingConsolidation`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md#pendingconsolidation) | Pending operation for consolidating two beacon chain validators | + +### `StableContainer` capacities | Name | Value | Description | | - | - | - | @@ -56,260 +101,165 @@ Subsequent forks specify a new `Profile`. | `MAX_BEACON_BLOCK_BODY_FIELDS` | `uint64(2**6)` (= 64) | Maximum number of fields to which `StableBeaconBlockBody` can ever grow in the future | | `MAX_BEACON_STATE_FIELDS` | `uint64(2**7)` (= 128) | Maximum number of fields to which `StableBeaconState` can ever grow in the future | +Maximum proof depth: + +- `StableBeaconState` > `validators` (1 + 7) > `` (1 + 40) > `pubkey` (3) > `` (1) = 53 bits +- `StableBeaconBlockBody` > `execution_payload` (1 + 6) > `transactions` (1 + 6) > `` (1 + 20) > `` (1 + 25) = 61 bits + ### Fork-agnostic `StableContainer` definitions These type definitions are fork independent and shared across all forks. They are not exchanged over libp2p. ```python class StableAttestation(StableContainer[MAX_ATTESTATION_FIELDS]): - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - data: AttestationData - signature: BLSSignature - committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] - ... # Additional features from the fork that introduces this EIP + aggregation_bits: Optional[Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]] + data: Optional[AttestationData] + signature: Optional[BLSSignature] + committee_bits: Optional[Bitvector[MAX_COMMITTEES_PER_SLOT]] class StableIndexedAttestation(StableContainer[MAX_INDEXED_ATTESTATION_FIELDS]): - attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - data: AttestationData - signature: BLSSignature - ... # Additional features from the fork that introduces this EIP + attesting_indices: Optional[List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]] + data: Optional[AttestationData] + signature: Optional[BLSSignature] class StableAttesterSlashing(Container): attestation_1: StableIndexedAttestation attestation_2: StableIndexedAttestation class StableExecutionPayload(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS]): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress # 'beneficiary' in the yellow paper - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 # 'difficulty' in the yellow paper - block_number: uint64 # 'number' in the yellow paper - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 # Hash of execution block - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] - blob_gas_used: uint64 - excess_blob_gas: uint64 - ... # Additional features from the fork that introduces this EIP + parent_hash: Optional[Hash32] + fee_recipient: Optional[ExecutionAddress] # 'beneficiary' in the yellow paper + state_root: Optional[Bytes32] + receipts_root: Optional[Bytes32] + logs_bloom: Optional[ByteVector[BYTES_PER_LOGS_BLOOM]] + prev_randao: Optional[Bytes32] # 'difficulty' in the yellow paper + block_number: Optional[uint64] # 'number' in the yellow paper + gas_limit: Optional[uint64] + gas_used: Optional[uint64] + timestamp: Optional[uint64] + extra_data: Optional[ByteList[MAX_EXTRA_DATA_BYTES]] + base_fee_per_gas: Optional[uint256] + block_hash: Optional[Hash32] # Hash of execution block + transactions: Optional[List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]] + withdrawals: Optional[List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]] # [New in Capella] + blob_gas_used: Optional[uint64] # [New in Deneb:EIP4844] + excess_blob_gas: Optional[uint64] # [New in Deneb:EIP4844] + deposit_receipts: Optional[List[DepositReceipt, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD]] # [New in Electra:EIP6110] + # [New in Electra:EIP7002:EIP7251] + withdrawal_requests: Optional[List[ExecutionLayerWithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]] class StableExecutionPayloadHeader(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS]): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 # Hash of execution block - transactions_root: Root - withdrawals_root: Root - blob_gas_used: uint64 - excess_blob_gas: uint64 - ... # Additional features from the fork that introduces this EIP + parent_hash: Optional[Hash32] + fee_recipient: Optional[ExecutionAddress] + state_root: Optional[Bytes32] + receipts_root: Optional[Bytes32] + logs_bloom: Optional[ByteVector[BYTES_PER_LOGS_BLOOM]] + prev_randao: Optional[Bytes32] + block_number: Optional[uint64] + gas_limit: Optional[uint64] + gas_used: Optional[uint64] + timestamp: Optional[uint64] + extra_data: Optional[ByteList[MAX_EXTRA_DATA_BYTES]] + base_fee_per_gas: Optional[uint256] + block_hash: Optional[Hash32] # Hash of execution block + transactions_root: Optional[Root] + withdrawals_root: Optional[Root] # [New in Capella] + blob_gas_used: Optional[uint64] # [New in Deneb:EIP4844] + excess_blob_gas: Optional[uint64] # [New in Deneb:EIP4844] + deposit_receipts_root: Optional[Root] # [New in Electra:EIP6110] + withdrawal_requests_root: Optional[Root] # [New in Electra:EIP7002:EIP7251] class StableBeaconBlockBody(StableContainer[MAX_BEACON_BLOCK_BODY_FIELDS]): - randao_reveal: BLSSignature - eth1_data: Eth1Data # Eth1 data vote - graffiti: Bytes32 # Arbitrary data - # Operations - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[StableAttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] - attestations: List[StableAttestation, MAX_ATTESTATIONS_ELECTRA] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] - sync_aggregate: SyncAggregate - # Execution - execution_payload: StableExecutionPayload - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - ... # Additional features from the fork that introduces this EIP + randao_reveal: Optional[BLSSignature] + eth1_data: Optional[Eth1Data] # Eth1 data vote + graffiti: Optional[Bytes32] # Arbitrary data + proposer_slashings: Optional[List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]] + attester_slashings: Optional[List[StableAttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA]] # [Modified in Electra:EIP7549] + attestations: Optional[List[StableAttestation, MAX_ATTESTATIONS_ELECTRA]] # [Modified in Electra:EIP7549] + deposits: Optional[List[Deposit, MAX_DEPOSITS]] + voluntary_exits: Optional[List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]] + sync_aggregate: Optional[SyncAggregate] # [New in Altair] + execution_payload: Optional[StableExecutionPayload] # [New in Bellatrix] + bls_to_execution_changes: Optional[List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]] # [New in Capella] + blob_kzg_commitments: Optional[List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]] # [New in Deneb:EIP4844] + consolidations: Optional[List[SignedConsolidation, MAX_CONSOLIDATIONS]] # [New in Electra:EIP7251] class StableBeaconState(StableContainer[MAX_BEACON_STATE_FIELDS]): # Versioning - genesis_time: uint64 - genesis_validators_root: Root - slot: Slot - fork: Fork + genesis_time: Optional[uint64] + genesis_validators_root: Optional[Root] + slot: Optional[Slot] + fork: Optional[Fork] # History - latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] # Frozen in Capella, replaced by historical_summaries + latest_block_header: Optional[BeaconBlockHeader] + block_roots: Optional[Vector[Root, SLOTS_PER_HISTORICAL_ROOT]] + state_roots: Optional[Vector[Root, SLOTS_PER_HISTORICAL_ROOT]] + historical_roots: Optional[List[Root, HISTORICAL_ROOTS_LIMIT]] # Frozen in Capella, replaced by historical_summaries # Eth1 - eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_data: Optional[Eth1Data] + eth1_data_votes: Optional[List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]] + eth1_deposit_index: Optional[uint64] # Registry - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] + validators: Optional[List[Validator, VALIDATOR_REGISTRY_LIMIT]] + balances: Optional[List[Gwei, VALIDATOR_REGISTRY_LIMIT]] # Randomness - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] + randao_mixes: Optional[Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]] # Slashings - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances + slashings: Optional[Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR]] # Per-epoch sums of slashed effective balances # Participation - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] + previous_epoch_participation: Optional[List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]] # [Modified in Altair] + current_epoch_participation: Optional[List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]] # [Modified in Altair] # Finality - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch - previous_justified_checkpoint: Checkpoint - current_justified_checkpoint: Checkpoint - finalized_checkpoint: Checkpoint + justification_bits: Optional[Bitvector[JUSTIFICATION_BITS_LENGTH]] # Bit set for every recent justified epoch + previous_justified_checkpoint: Optional[Checkpoint] + current_justified_checkpoint: Optional[Checkpoint] + finalized_checkpoint: Optional[Checkpoint] # Inactivity - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: Optional[List[uint64, VALIDATOR_REGISTRY_LIMIT]] # [New in Altair] # Sync - current_sync_committee: SyncCommittee - next_sync_committee: SyncCommittee + current_sync_committee: Optional[SyncCommittee] # [New in Altair] + next_sync_committee: Optional[SyncCommittee] # [New in Altair] # Execution - latest_execution_payload_header: StableExecutionPayloadHeader + latest_execution_payload_header: Optional[StableExecutionPayloadHeader] # [New in Bellatrix] # Withdrawals - next_withdrawal_index: WithdrawalIndex - next_withdrawal_validator_index: ValidatorIndex + next_withdrawal_index: Optional[WithdrawalIndex] # [New in Capella] + next_withdrawal_validator_index: Optional[ValidatorIndex] # [New in Capella] # Deep history valid from Capella onwards - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - ... # Additional features from the fork that introduces this EIP + historical_summaries: Optional[List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]] # [New in Capella] + deposit_receipts_start_index: Optional[uint64] # [New in Electra:EIP6110] + deposit_balance_to_consume: Optional[Gwei] # [New in Electra:EIP7251] + exit_balance_to_consume: Optional[Gwei] # [New in Electra:EIP7251] + earliest_exit_epoch: Optional[Epoch] # [New in Electra:EIP7251] + consolidation_balance_to_consume: Optional[Gwei] # [New in Electra:EIP7251] + earliest_consolidation_epoch: Optional[Epoch] # [New in Electra:EIP7251] + pending_balance_deposits: Optional[List[PendingBalanceDeposit, PENDING_BALANCE_DEPOSITS_LIMIT]] # [New in Electra:EIP7251] + # [New in Electra:EIP7251] + pending_partial_withdrawals: Optional[List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]] + pending_consolidations: Optional[List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]] # [New in Electra:EIP7251] ``` ### Fork-specific `Profile` definitions -These type definitions are specific to the fork that introduces this EIP. They are used in place of the legacy fork-specific `Container` definitions. +The consensus type definitions specific to the fork that introduces this EIP are updated to inherit the Merkleization of the `StableContainer` definitions. Fields are kept as is. ```python class Attestation(Profile[StableAttestation]): - data: AttestationData - signature: BLSSignature - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] - ... # Additional features from the fork that introduces this EIP + ... class IndexedAttestation(Profile[StableIndexedAttestation]): - data: AttestationData - signature: BLSSignature - attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - ... # Additional features from the fork that introduces this EIP - -class AttesterSlashing(Profile[StableAttesterSlashing]): - attestation_1: IndexedAttestation - attestation_2: IndexedAttestation + ... class ExecutionPayload(Profile[StableExecutionPayload]): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress # 'beneficiary' in the yellow paper - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 # 'difficulty' in the yellow paper - block_number: uint64 # 'number' in the yellow paper - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 # Hash of execution block - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] - blob_gas_used: uint64 - excess_blob_gas: uint64 - ... # Additional features from the fork that introduces this EIP + ... class ExecutionPayloadHeader(Profile[StableExecutionPayloadHeader]): - # Execution block header fields - parent_hash: Hash32 - fee_recipient: ExecutionAddress - state_root: Bytes32 - receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] - prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 - # Extra payload fields - block_hash: Hash32 # Hash of execution block - transactions_root: Root - withdrawals_root: Root - blob_gas_used: uint64 - excess_blob_gas: uint64 - ... # Additional features from the fork that introduces this EIP + ... class BeaconBlockBody(Profile[StableBeaconBlockBody]): - randao_reveal: BLSSignature - eth1_data: Eth1Data # Eth1 data vote - graffiti: Bytes32 # Arbitrary data - # Operations - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] - attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] - sync_aggregate: SyncAggregate - # Execution - execution_payload: ExecutionPayload - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - ... # Additional features from the fork that introduces this EIP + ... class BeaconState(Profile[StableBeaconState]): - # Versioning - genesis_time: uint64 - genesis_validators_root: Root - slot: Slot - fork: Fork - # History - latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] # Frozen in Capella, replaced by historical_summaries - # Eth1 - eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 - # Registry - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - # Randomness - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - # Slashings - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances - # Participation - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - # Finality - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch - previous_justified_checkpoint: Checkpoint - current_justified_checkpoint: Checkpoint - finalized_checkpoint: Checkpoint - # Inactivity - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] - # Sync - current_sync_committee: SyncCommittee - next_sync_committee: SyncCommittee - # Execution - latest_execution_payload_header: ExecutionPayloadHeader - # Withdrawals - next_withdrawal_index: WithdrawalIndex - next_withdrawal_validator_index: ValidatorIndex - # Deep history valid from Capella onwards - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - ... # Additional features from the fork that introduces this EIP + ... ``` ## Rationale @@ -322,6 +272,19 @@ Applying this EIP breaks `hash_tree_root` and Merkle tree verifiers a single tim While `Profile` serializes in the same way as the legacy `Container`, the merkleization and `hash_tree_root` of affected data structures changes. Therefore, verifiers that wish to process Merkle proofs of legacy variants still need to support the corresponding legacy schemes. +### Immutability + +Once a field in a `StableContainer` has been published, its name can no longer be used to represent a different type in the future. This includes list types with a higher capacity than originally intended. This is in line with historical management of certain cases: + +- Phase0: `BeaconState` contained `previous_epoch_attestations` / `current_epoch_attestations` +- Altair: `BeaconState` replaced these fields with `previous_epoch_participation` / `current_epoch_participation` + +Furthermore, new fields have to be appended at the end of `StableContainer`. This is in line with historical management of other cases: + +- Capella appended `historical_summaries` to `BeaconState` instead of squeezing the new field next to `historical_roots` + +With `StableContainer`, stable Merkleization requires these rules to become strict. + ## Backwards Compatibility Existing Merkle proof verifiers need to be updated to support the new Merkle tree shape. This includes verifiers in smart contracts on different blockchains and verifiers in hardware wallets, if applicable.