From 32b0a49a8686d5f95ba572841949376e527fd7a0 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 15 Apr 2024 19:49:41 +0200 Subject: [PATCH 1/9] Add EIP: Forward compatible consensus data structures --- EIPS/eip-7688.md | 292 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 EIPS/eip-7688.md diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md new file mode 100644 index 0000000000000..3332c2b616d95 --- /dev/null +++ b/EIPS/eip-7688.md @@ -0,0 +1,292 @@ +--- +eip: 7688 +title: Forward compatible consensus data structures +description: Transition consensus SSZ data structures to StableContainer +author: Etan Kissling (@etan-status) +discussions-to: https://ethereum-magicians.org/t/eip-7688-forward-compatible-consensus-data-structures/19673 +status: Draft +type: Standards Track +category: Core +created: 2024-04-15 +requires: 7495 +--- + +## Abstract + +This EIP defines the changes needed to adopt [`StableContainer`](./eip-7495.md) in consensus data structures. + +## Motivation + +Ethereum's consensus data structures make heavy use of [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md) `Container`, which defines how they are serialized and merkleized. The merkleization scheme allows application implementations to verify that individual fields (and partial fields) have not been tampered with. This is useful, for example, in smart contracts of decentralized staking pools that wish to verify that participating validators have not been slashed. + +While SSZ `Container` defines how data structures are merkleized, the merkleization is prone to change across the different forks. When that happens, e.g., because new features are added or old features get removed, existing verifier implementations need to be updated to be able to continue processing proofs. + +[`StableContainer`](./eip-7495.md) is a forward compatible alternative that guarantees a forward compatible merkleization scheme. By transitioning consensus data structures to use `StableContainer`, smart contracts that contain verifier logic no longer have to be maintained in lockstep with Ethereum's fork schedule as long as the underlying features that they verify don't change. For example, as long as the concept of slashing is represented using the boolean `slashed` field, existing verifiers will not break when unrelated features get added or removed. This is also true for off-chain verifiers, e.g., in hardware wallets or in operating systems for mobile devices that are on a different software update cadence than Ethereum. + +## Specification + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. + +### Conversion procedure + +For each converted data structure, a new `StableContainer` type `S` is introduced that serves as the primary definition of each data structure. + +- 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 historical forks are examined and fields that have not been present in all forks are marked as `Optional` in the new `StableContainer` type. +- To guarantee forward and backward compatibility, new fields from future forks MUST be appended to the end of the `StableContainer` definition. Existing fields MAY be converted to `Optional`. + +Furthermore, a `Variant` type is defined that is specific to the fork at which the conversion is applied. This `Variant` is the equivalent of the legacy `Container` type, except that it inherits from `Variant[S]`. The SSZ serialization of `Variant` is compatible with `Container`, but the merkleization and `hash_tree_root` are computed differently. Furthermore, `Variant` MAY use fields of `Optional` type if necessary. + +libp2p topics still exchange fork specific `Variant` definitions using the same serialization as the legacy `Container` type. Only merkleization and `hash_tree_root` are computed differently. + +### Limits + +| Name | Value | Description | +| - | - | - | +| `MAX_EXECUTION_PAYLOAD_FIELDS` | `uint64(2**6)` (= 64) | Maximum number of fields to which `ExecutionPayload` can ever grow in the future | +| `MAX_BEACON_BLOCK_BODY_FIELDS` | `uint64(2**6)` (= 64) | Maximum number of fields to which `BeaconBlockBody` can ever grow in the future | +| `MAX_BEACON_STATE_FIELDS` | `uint64(2**7)` (= 128) | Maximum number of fields to which `BeaconState` can ever grow in the future | + +### Fork-agnostic `StableContainer` definitions + +These type definitions are fork independent and shared across all forks. They are not exchanged over libp2p. + +```python +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: Optional[List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]] + blob_gas_used: Optional[uint64] + excess_blob_gas: Optional[uint64] + ... # Additional features from the fork that introduces this EIP + +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: Optional[Root] + blob_gas_used: Optional[uint64] + excess_blob_gas: Optional[uint64] + +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[AttesterSlashing, MAX_ATTESTER_SLASHINGS] + attestations: List[Attestation, MAX_ATTESTATIONS] + deposits: List[Deposit, MAX_DEPOSITS] + voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + sync_aggregate: Optional[SyncAggregate] + # Execution + execution_payload: Optional[ExecutionPayload] + bls_to_execution_changes: Optional[List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]] + blob_kzg_commitments: Optional[List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]] + ... # Additional features from the fork that introduces this EIP + +class StableBeaconState(StableContainer[MAX_BEACON_STATE_FIELDS]): + # 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: Optional[List[uint64, VALIDATOR_REGISTRY_LIMIT]] + # Sync + current_sync_committee: Optional[SyncCommittee] + next_sync_committee: Optional[SyncCommittee] + # Execution + latest_execution_payload_header: Optional[ExecutionPayloadHeader] + # Withdrawals + next_withdrawal_index: Optional[WithdrawalIndex] + next_withdrawal_validator_index: Optional[ValidatorIndex] + # Deep history valid from Capella onwards + historical_summaries: Optional[List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]] + ... # Additional features from the fork that introduces this EIP +``` + +### Fork-specific `Variant` 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. + +```python +class ExecutionPayload(Variant[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(Variant[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 + +class BeaconBlockBody(Variant[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] + attestations: List[Attestation, MAX_ATTESTATIONS] + 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(Variant[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 + +### Best timing? + +Applying this EIP breaks `hash_tree_root` and Merkle tree verifiers a single time, while promising forward compatibility from the fork going forward. It is best to apply it before merkleization would be broken by different changes. Merkleization is broken by a `Container` reaching a new power of 2 in its number of fields. + +### Can this be applied retroactively? + +While `Variant` 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. + +## 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. + +Note that backwards compatibility is also broken when one of the converted `Container` data structures would reach a new power of 2 in its number of fields. + +## Security Considerations + +None + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From 60ea79059704e5877db5f2254fa35498205e47e0 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 16 Apr 2024 21:23:34 +0200 Subject: [PATCH 2/9] Update EIPS/eip-7688.md Co-authored-by: Nikki Gaudreau <87712502+gaudren@users.noreply.github.com> --- EIPS/eip-7688.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 3332c2b616d95..0f9461f661ef0 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -13,7 +13,7 @@ requires: 7495 ## Abstract -This EIP defines the changes needed to adopt [`StableContainer`](./eip-7495.md) in consensus data structures. +This EIP defines the changes needed to adopt `StableContainer` from [EIP-7495](./eip-7495.md) in consensus data structures. ## Motivation From b6f978926f8f13d10b0349b4c23cfb87caa09708 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 16 Apr 2024 21:23:48 +0200 Subject: [PATCH 3/9] Update EIPS/eip-7688.md Co-authored-by: Nikki Gaudreau <87712502+gaudren@users.noreply.github.com> --- EIPS/eip-7688.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 0f9461f661ef0..92b221257188c 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -21,7 +21,7 @@ Ethereum's consensus data structures make heavy use of [Simple Serialize (SSZ)]( While SSZ `Container` defines how data structures are merkleized, the merkleization is prone to change across the different forks. When that happens, e.g., because new features are added or old features get removed, existing verifier implementations need to be updated to be able to continue processing proofs. -[`StableContainer`](./eip-7495.md) is a forward compatible alternative that guarantees a forward compatible merkleization scheme. By transitioning consensus data structures to use `StableContainer`, smart contracts that contain verifier logic no longer have to be maintained in lockstep with Ethereum's fork schedule as long as the underlying features that they verify don't change. For example, as long as the concept of slashing is represented using the boolean `slashed` field, existing verifiers will not break when unrelated features get added or removed. This is also true for off-chain verifiers, e.g., in hardware wallets or in operating systems for mobile devices that are on a different software update cadence than Ethereum. +`StableContainer`, of [EIP-7495](./eip-7495.md), is a forward compatible alternative that guarantees a forward compatible merkleization scheme. By transitioning consensus data structures to use `StableContainer`, smart contracts that contain verifier logic no longer have to be maintained in lockstep with Ethereum's fork schedule as long as the underlying features that they verify don't change. For example, as long as the concept of slashing is represented using the boolean `slashed` field, existing verifiers will not break when unrelated features get added or removed. This is also true for off-chain verifiers, e.g., in hardware wallets or in operating systems for mobile devices that are on a different software update cadence than Ethereum. ## Specification From 2325f7bc0c25333462befe35e04f3d77c9feeb6c Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 07:03:30 +0200 Subject: [PATCH 4/9] Update EIPS/eip-7688.md Co-authored-by: Cayman --- EIPS/eip-7688.md | 1 + 1 file changed, 1 insertion(+) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 92b221257188c..4ca3f60e7dac1 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -94,6 +94,7 @@ class StableExecutionPayloadHeader(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS] withdrawals_root: Optional[Root] blob_gas_used: Optional[uint64] excess_blob_gas: Optional[uint64] + ... # Additional features from the fork that introduces this EIP class StableBeaconBlockBody(StableContainer[MAX_BEACON_BLOCK_BODY_FIELDS]): randao_reveal: BLSSignature From 6e7ecbc75538b4a143367c666e589caf57a6b85d Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 07:05:00 +0200 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Cayman --- EIPS/eip-7688.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 4ca3f60e7dac1..66861747c993a 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -108,7 +108,7 @@ class StableBeaconBlockBody(StableContainer[MAX_BEACON_BLOCK_BODY_FIELDS]): voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] sync_aggregate: Optional[SyncAggregate] # Execution - execution_payload: Optional[ExecutionPayload] + execution_payload: Optional[StableExecutionPayload] bls_to_execution_changes: Optional[List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]] blob_kzg_commitments: Optional[List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]] ... # Additional features from the fork that introduces this EIP @@ -149,7 +149,7 @@ class StableBeaconState(StableContainer[MAX_BEACON_STATE_FIELDS]): current_sync_committee: Optional[SyncCommittee] next_sync_committee: Optional[SyncCommittee] # Execution - latest_execution_payload_header: Optional[ExecutionPayloadHeader] + latest_execution_payload_header: Optional[StableExecutionPayloadHeader] # Withdrawals next_withdrawal_index: Optional[WithdrawalIndex] next_withdrawal_validator_index: Optional[ValidatorIndex] @@ -205,6 +205,7 @@ class ExecutionPayloadHeader(Variant[StableExecutionPayloadHeader]): withdrawals_root: Root blob_gas_used: uint64 excess_blob_gas: uint64 + ... # Additional features from the fork that introduces this EIP class BeaconBlockBody(Variant[StableBeaconBlockBody]): randao_reveal: BLSSignature From e443fd9e77f0ab53e6960531df6f9a5ced9af574 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 07:06:17 +0200 Subject: [PATCH 6/9] clarifications regarding `Variant` Co-authored-by: Cayman --- EIPS/eip-7688.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 66861747c993a..ea822cac29f0e 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -32,12 +32,14 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S For each converted data structure, a new `StableContainer` type `S` is introduced that serves as the primary definition of each data structure. - 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 historical forks are examined and fields that have not been present in all forks are marked as `Optional` in the new `StableContainer` type. +- The `StableContainer` starts as a copy of the latest fork's `Container` equivalent. - To guarantee forward and backward compatibility, new fields from future forks MUST be appended to the end of the `StableContainer` definition. Existing fields MAY be converted to `Optional`. Furthermore, a `Variant` type is defined that is specific to the fork at which the conversion is applied. This `Variant` is the equivalent of the legacy `Container` type, except that it inherits from `Variant[S]`. The SSZ serialization of `Variant` is compatible with `Container`, but the merkleization and `hash_tree_root` are computed differently. Furthermore, `Variant` MAY use fields of `Optional` type if necessary. -libp2p topics still exchange fork specific `Variant` definitions using the same serialization as the legacy `Container` type. Only merkleization and `hash_tree_root` are computed differently. +If subsequent forks add / remove fields, they specify a new `Variant`. This is similar to the previous approach of specifying a new `Container`. The `StableContainer` is the superset across all `Variant`; fields not present across all `Variant` use an `Optional` type. + +The fork specific `Variant` definitions use the same serialization as the legacy `Container` type. Only merkleization and `hash_tree_root` are computed differently when switching to the new scheme. ### Limits From 3f7d2db2845da87689d04b6efb76bed9b1b7efd3 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 07:07:23 +0200 Subject: [PATCH 7/9] drop `Optional` type for historical features Co-authored-by: Cayman --- EIPS/eip-7688.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index ea822cac29f0e..194859c88a5ed 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -71,9 +71,9 @@ class StableExecutionPayload(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS]): # Extra payload fields block_hash: Hash32 # Hash of execution block transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: Optional[List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]] - blob_gas_used: Optional[uint64] - excess_blob_gas: Optional[uint64] + 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 StableExecutionPayloadHeader(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS]): @@ -93,9 +93,9 @@ class StableExecutionPayloadHeader(StableContainer[MAX_EXECUTION_PAYLOAD_FIELDS] # Extra payload fields block_hash: Hash32 # Hash of execution block transactions_root: Root - withdrawals_root: Optional[Root] - blob_gas_used: Optional[uint64] - excess_blob_gas: Optional[uint64] + withdrawals_root: Root + blob_gas_used: uint64 + excess_blob_gas: uint64 ... # Additional features from the fork that introduces this EIP class StableBeaconBlockBody(StableContainer[MAX_BEACON_BLOCK_BODY_FIELDS]): @@ -108,11 +108,11 @@ class StableBeaconBlockBody(StableContainer[MAX_BEACON_BLOCK_BODY_FIELDS]): attestations: List[Attestation, MAX_ATTESTATIONS] deposits: List[Deposit, MAX_DEPOSITS] voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] - sync_aggregate: Optional[SyncAggregate] + sync_aggregate: SyncAggregate # Execution - execution_payload: Optional[StableExecutionPayload] - bls_to_execution_changes: Optional[List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]] - blob_kzg_commitments: Optional[List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]] + 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 class StableBeaconState(StableContainer[MAX_BEACON_STATE_FIELDS]): @@ -146,17 +146,17 @@ class StableBeaconState(StableContainer[MAX_BEACON_STATE_FIELDS]): current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint # Inactivity - inactivity_scores: Optional[List[uint64, VALIDATOR_REGISTRY_LIMIT]] + inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] # Sync - current_sync_committee: Optional[SyncCommittee] - next_sync_committee: Optional[SyncCommittee] + current_sync_committee: SyncCommittee + next_sync_committee: SyncCommittee # Execution - latest_execution_payload_header: Optional[StableExecutionPayloadHeader] + latest_execution_payload_header: StableExecutionPayloadHeader # Withdrawals - next_withdrawal_index: Optional[WithdrawalIndex] - next_withdrawal_validator_index: Optional[ValidatorIndex] + next_withdrawal_index: WithdrawalIndex + next_withdrawal_validator_index: ValidatorIndex # Deep history valid from Capella onwards - historical_summaries: Optional[List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]] + historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] ... # Additional features from the fork that introduces this EIP ``` From 1be24579f4fd1075169fc3b1a4cf5089a97279b2 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 07:12:13 +0200 Subject: [PATCH 8/9] add author --- EIPS/eip-7688.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 194859c88a5ed..96c8e4e69976e 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -2,7 +2,7 @@ eip: 7688 title: Forward compatible consensus data structures description: Transition consensus SSZ data structures to StableContainer -author: Etan Kissling (@etan-status) +author: Etan Kissling (@etan-status), Cayman (@wemeetagain) discussions-to: https://ethereum-magicians.org/t/eip-7688-forward-compatible-consensus-data-structures/19673 status: Draft type: Standards Track From c78ccc96ca861ae7d27d7faae9b55319129fea0a Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 2 May 2024 11:38:29 +0200 Subject: [PATCH 9/9] Update EIPS/eip-7688.md Co-authored-by: g11tech --- EIPS/eip-7688.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-7688.md b/EIPS/eip-7688.md index 96c8e4e69976e..ac1ffaadcd0db 100644 --- a/EIPS/eip-7688.md +++ b/EIPS/eip-7688.md @@ -33,7 +33,7 @@ For each converted data structure, a new `StableContainer` type `S` is introduce - 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. -- To guarantee forward and backward compatibility, new fields from future forks MUST be appended to the end of the `StableContainer` definition. Existing fields MAY be converted to `Optional`. +- To guarantee forward and backward compatibility, new fields from future forks MUST only be appended to the `StableContainer` definition. Existing fields MAY be converted to `Optional`. Furthermore, a `Variant` type is defined that is specific to the fork at which the conversion is applied. This `Variant` is the equivalent of the legacy `Container` type, except that it inherits from `Variant[S]`. The SSZ serialization of `Variant` is compatible with `Container`, but the merkleization and `hash_tree_root` are computed differently. Furthermore, `Variant` MAY use fields of `Optional` type if necessary.