From 8b053caa37c5a5fd2c79f07395abc2f8f1067b2c Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 15 Mar 2024 17:17:22 +0530 Subject: [PATCH] feat: add inclusion lists for censorship resistance --- .../src/api/impl/config/constants.ts | 3 + .../test/spec/presets/fork.test.ts | 3 +- packages/params/src/forkName.ts | 6 + packages/params/src/index.ts | 5 +- .../state-transition/src/cache/stateCache.ts | 2 + packages/state-transition/src/cache/types.ts | 6 +- packages/state-transition/src/slot/index.ts | 1 + .../src/slot/upgradeStateToElectra.ts | 36 ++++ .../state-transition/src/stateTransition.ts | 5 + packages/state-transition/src/types.ts | 2 + packages/state-transition/src/util/genesis.ts | 10 + .../test/unit/upgradeState.test.ts | 16 ++ packages/types/src/allForks/sszTypes.ts | 2 +- packages/types/src/allForks/types.ts | 178 ++++++++++++++---- packages/types/src/deneb/sszTypes.ts | 4 +- packages/types/src/electra/sszTypes.ts | 166 +++++++++++++--- packages/types/src/electra/types.ts | 14 +- 17 files changed, 378 insertions(+), 81 deletions(-) create mode 100644 packages/state-transition/src/slot/upgradeStateToElectra.ts diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index 87ffce91b4d9..755c42eee128 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -18,6 +18,7 @@ import { DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, DOMAIN_CONTRIBUTION_AND_PROOF, DOMAIN_BLS_TO_EXECUTION_CHANGE, + DOMAIN_INCLUSION_LIST_SUMMARY, DOMAIN_APPLICATION_BUILDER, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX, @@ -100,4 +101,6 @@ export const specConstants = { // Deneb types BLOB_TX_TYPE, VERSIONED_HASH_VERSION_KZG, + + DOMAIN_INCLUSION_LIST_SUMMARY, }; diff --git a/packages/beacon-node/test/spec/presets/fork.test.ts b/packages/beacon-node/test/spec/presets/fork.test.ts index c880d24bbbe3..c121e651fcea 100644 --- a/packages/beacon-node/test/spec/presets/fork.test.ts +++ b/packages/beacon-node/test/spec/presets/fork.test.ts @@ -5,6 +5,7 @@ import { CachedBeaconStateAltair, CachedBeaconStatePhase0, CachedBeaconStateCapella, + CachedBeaconStateDeneb, } from "@lodestar/state-transition"; import * as slotFns from "@lodestar/state-transition/slot"; import {phase0, ssz} from "@lodestar/types"; @@ -36,7 +37,7 @@ const fork: TestRunnerFn = (forkNext) => { case ForkName.deneb: return slotFns.upgradeStateToDeneb(preState as CachedBeaconStateCapella); case ForkName.electra: - throw Error("not Implemented"); + return slotFns.upgradeStateToElectra(preState as CachedBeaconStateDeneb); } }, options: { diff --git a/packages/params/src/forkName.ts b/packages/params/src/forkName.ts index bbb72a7972fa..31cb1229efb5 100644 --- a/packages/params/src/forkName.ts +++ b/packages/params/src/forkName.ts @@ -45,3 +45,9 @@ export type ForkBlobs = Exclude; export function isForkBlobs(fork: ForkName): fork is ForkBlobs { return isForkWithdrawals(fork) && fork !== ForkName.capella; } + +export type ForkPreILs = ForkPreBlobs | ForkName.deneb; +export type ForkILs = Exclude; +export function isForkILs(fork: ForkName): fork is ForkILs { + return isForkBlobs(fork) && fork !== ForkName.deneb; +} diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index 6a95e3ca632e..71c448dfcda1 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -128,7 +128,7 @@ export const DOMAIN_SYNC_COMMITTEE = Uint8Array.from([7, 0, 0, 0]); export const DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF = Uint8Array.from([8, 0, 0, 0]); export const DOMAIN_CONTRIBUTION_AND_PROOF = Uint8Array.from([9, 0, 0, 0]); export const DOMAIN_BLS_TO_EXECUTION_CHANGE = Uint8Array.from([10, 0, 0, 0]); -export const DOMAIN_BLOB_SIDECAR = Uint8Array.from([11, 0, 0, 0]); +export const DOMAIN_INCLUSION_LIST_SUMMARY = Uint8Array.from([11, 0, 0, 0]); // Application specific domains @@ -244,3 +244,6 @@ export const KZG_COMMITMENT_SUBTREE_INDEX0 = KZG_COMMITMENT_GINDEX0 - 2 ** KZG_C // ssz.deneb.BlobSidecars.elementType.fixedSize export const BLOBSIDECAR_FIXED_SIZE = ACTIVE_PRESET === PresetName.minimal ? 131672 : 131928; + +// might be rounded to nearest power of 2 +export const MAX_TRANSACTIONS_PER_INCLUSION_LIST = 143; diff --git a/packages/state-transition/src/cache/stateCache.ts b/packages/state-transition/src/cache/stateCache.ts index 8b45152a3646..3015011da554 100644 --- a/packages/state-transition/src/cache/stateCache.ts +++ b/packages/state-transition/src/cache/stateCache.ts @@ -11,6 +11,7 @@ import { BeaconStateBellatrix, BeaconStateCapella, BeaconStateDeneb, + BeaconStateElectra, } from "./types.js"; import {RewardCache, createEmptyRewardCache} from "./rewardCache.js"; @@ -131,6 +132,7 @@ export type CachedBeaconStateAltair = CachedBeaconState; export type CachedBeaconStateBellatrix = CachedBeaconState; export type CachedBeaconStateCapella = CachedBeaconState; export type CachedBeaconStateDeneb = CachedBeaconState; +export type CachedBeaconStateElectra = CachedBeaconState; export type CachedBeaconStateAllForks = CachedBeaconState; export type CachedBeaconStateExecutions = CachedBeaconState; diff --git a/packages/state-transition/src/cache/types.ts b/packages/state-transition/src/cache/types.ts index 39b1dbb4b45b..a865aa4f4183 100644 --- a/packages/state-transition/src/cache/types.ts +++ b/packages/state-transition/src/cache/types.ts @@ -7,6 +7,7 @@ export type BeaconStateAltair = CompositeViewDU; export type BeaconStateBellatrix = CompositeViewDU; export type BeaconStateCapella = CompositeViewDU; export type BeaconStateDeneb = CompositeViewDU; +export type BeaconStateElectra = CompositeViewDU; // Union at the TreeViewDU level // - Works well as function argument and as generic type for allForks functions @@ -18,8 +19,9 @@ export type BeaconStateAllForks = | BeaconStateAltair | BeaconStateBellatrix | BeaconStateCapella - | BeaconStateDeneb; + | BeaconStateDeneb + | BeaconStateElectra; -export type BeaconStateExecutions = BeaconStateBellatrix | BeaconStateCapella | BeaconStateDeneb; +export type BeaconStateExecutions = BeaconStateBellatrix | BeaconStateCapella | BeaconStateDeneb | BeaconStateElectra; export type ShufflingGetter = (shufflingEpoch: Epoch, dependentRoot: RootHex) => EpochShuffling | null; diff --git a/packages/state-transition/src/slot/index.ts b/packages/state-transition/src/slot/index.ts index 6c4add1d1230..b05bd7ac93f2 100644 --- a/packages/state-transition/src/slot/index.ts +++ b/packages/state-transition/src/slot/index.ts @@ -7,6 +7,7 @@ export {upgradeStateToAltair} from "./upgradeStateToAltair.js"; export {upgradeStateToBellatrix} from "./upgradeStateToBellatrix.js"; export {upgradeStateToCapella} from "./upgradeStateToCapella.js"; export {upgradeStateToDeneb} from "./upgradeStateToDeneb.js"; +export {upgradeStateToElectra} from "./upgradeStateToElectra.js"; /** * Dial state to next slot. Common for all forks diff --git a/packages/state-transition/src/slot/upgradeStateToElectra.ts b/packages/state-transition/src/slot/upgradeStateToElectra.ts new file mode 100644 index 000000000000..1dde905bb7fe --- /dev/null +++ b/packages/state-transition/src/slot/upgradeStateToElectra.ts @@ -0,0 +1,36 @@ +import {ssz} from "@lodestar/types"; +import {getCachedBeaconState} from "../cache/stateCache.js"; +import {CachedBeaconStateDeneb} from "../types.js"; +import {CachedBeaconStateElectra} from "../types.js"; + +/** + * Upgrade a state from Capella to Deneb. + */ +export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): CachedBeaconStateElectra { + const {config} = stateDeneb; + + const stateDenebNode = ssz.deneb.BeaconState.commitViewDU(stateDeneb); + const stateElectraView = ssz.electra.BeaconState.getViewDU(stateDenebNode); + + const stateElectra = getCachedBeaconState(stateElectraView, stateDeneb); + + stateElectra.fork = ssz.phase0.Fork.toViewDU({ + previousVersion: stateDeneb.fork.currentVersion, + currentVersion: config.ELECTRA_FORK_VERSION, + epoch: stateDeneb.epochCtx.epoch, + }); + + // TODO ELECTRA: check if this is following is required, since it seemed to be an issue in deneb state u[grade + // (see upgradeStateToDeneb) + // + // stateElectra.latestExecutionPayloadHeader = ssz.electra.BeaconState.fields.latestExecutionPayloadHeader.toViewDU({ + // ...stateDeneb.latestExecutionPayloadHeader.toValue(), + // previousInclusionListSummaryRoot: ssz.Root.defaultValue(), + // }); + + stateElectra.commit(); + // Clear cache to ensure the cache of capella fields is not used by new deneb fields + stateElectra["clearCache"](); + + return stateElectra; +} diff --git a/packages/state-transition/src/stateTransition.ts b/packages/state-transition/src/stateTransition.ts index b3f3b41eb865..049f04dce287 100644 --- a/packages/state-transition/src/stateTransition.ts +++ b/packages/state-transition/src/stateTransition.ts @@ -9,6 +9,7 @@ import { CachedBeaconStateAltair, CachedBeaconStateBellatrix, CachedBeaconStateCapella, + CachedBeaconStateDeneb, } from "./types.js"; import {computeEpochAtSlot} from "./util/index.js"; import {verifyProposerSignature} from "./signatureSets/index.js"; @@ -18,6 +19,7 @@ import { upgradeStateToBellatrix, upgradeStateToCapella, upgradeStateToDeneb, + upgradeStateToElectra, } from "./slot/index.js"; import {processBlock} from "./block/index.js"; import {EpochTransitionStep, processEpoch} from "./epoch/index.js"; @@ -230,6 +232,9 @@ function processSlotsWithTransientCache( if (stateSlot === config.DENEB_FORK_EPOCH) { postState = upgradeStateToDeneb(postState as CachedBeaconStateCapella) as CachedBeaconStateAllForks; } + if (stateSlot === config.ELECTRA_FORK_EPOCH) { + postState = upgradeStateToElectra(postState as CachedBeaconStateDeneb) as CachedBeaconStateAllForks; + } } else { postState.slot++; } diff --git a/packages/state-transition/src/types.ts b/packages/state-transition/src/types.ts index 6b6b1f6260b2..d3a1ed69a7a9 100644 --- a/packages/state-transition/src/types.ts +++ b/packages/state-transition/src/types.ts @@ -9,6 +9,7 @@ export type { CachedBeaconStateBellatrix, CachedBeaconStateCapella, CachedBeaconStateDeneb, + CachedBeaconStateElectra, } from "./cache/stateCache.js"; export type { @@ -19,4 +20,5 @@ export type { BeaconStateBellatrix, BeaconStateCapella, BeaconStateDeneb, + BeaconStateElectra, } from "./cache/types.js"; diff --git a/packages/state-transition/src/util/genesis.ts b/packages/state-transition/src/util/genesis.ts index 1041c33d0eb3..1edbab34ad57 100644 --- a/packages/state-transition/src/util/genesis.ts +++ b/packages/state-transition/src/util/genesis.ts @@ -214,6 +214,7 @@ export function initializeBeaconStateFromEth1( | typeof ssz.bellatrix.ExecutionPayloadHeader | typeof ssz.capella.ExecutionPayloadHeader | typeof ssz.deneb.ExecutionPayloadHeader + | typeof ssz.electra.ExecutionPayloadHeader > ): CachedBeaconStateAllForks { const stateView = getGenesisBeaconState( @@ -284,6 +285,15 @@ export function initializeBeaconStateFromEth1( ssz.deneb.ExecutionPayloadHeader.defaultViewDU(); } + if (GENESIS_SLOT >= config.ELECTRA_FORK_EPOCH) { + const stateElectra = state as CompositeViewDU; + stateElectra.fork.previousVersion = config.ELECTRA_FORK_VERSION; + stateElectra.fork.currentVersion = config.ELECTRA_FORK_VERSION; + stateElectra.latestExecutionPayloadHeader = + (executionPayloadHeader as CompositeViewDU) ?? + ssz.electra.ExecutionPayloadHeader.defaultViewDU(); + } + state.commit(); return state; diff --git a/packages/state-transition/test/unit/upgradeState.test.ts b/packages/state-transition/test/unit/upgradeState.test.ts index 75ba415c1bea..df9b052542f9 100644 --- a/packages/state-transition/test/unit/upgradeState.test.ts +++ b/packages/state-transition/test/unit/upgradeState.test.ts @@ -5,6 +5,7 @@ import {createBeaconConfig, ChainForkConfig, createChainForkConfig} from "@lodes import {config as chainConfig} from "@lodestar/config/default"; import {upgradeStateToDeneb} from "../../src/slot/upgradeStateToDeneb.js"; +import {upgradeStateToElectra} from "../../src/slot/upgradeStateToElectra.js"; import {createCachedBeaconState} from "../../src/cache/stateCache.js"; import {PubkeyIndexMap} from "../../src/cache/pubkeyCache.js"; @@ -24,6 +25,21 @@ describe("upgradeState", () => { const newState = upgradeStateToDeneb(stateView); expect(() => newState.toValue()).not.toThrow(); }); + it("upgradeStateToElectra", () => { + const denebState = ssz.deneb.BeaconState.defaultViewDU(); + const config = getConfig(ForkName.deneb); + const stateView = createCachedBeaconState( + denebState, + { + config: createBeaconConfig(config, denebState.genesisValidatorsRoot), + pubkey2index: new PubkeyIndexMap(), + index2pubkey: [], + }, + {skipSyncCommitteeCache: true} + ); + const newState = upgradeStateToElectra(stateView); + expect(() => newState.toValue()).not.toThrow(); + }); }); const ZERO_HASH = Buffer.alloc(32, 0); diff --git a/packages/types/src/allForks/sszTypes.ts b/packages/types/src/allForks/sszTypes.ts index 6030215ac8ca..84c6bb86ce5f 100644 --- a/packages/types/src/allForks/sszTypes.ts +++ b/packages/types/src/allForks/sszTypes.ts @@ -192,7 +192,7 @@ export const allForksBlobs = { ExecutionPayloadAndBlobsBundle: deneb.ExecutionPayloadAndBlobsBundle, }, electra: { - BlobSidecar: electra.BlobSidecar, + BlobSidecar: deneb.BlobSidecar, ExecutionPayloadAndBlobsBundle: electra.ExecutionPayloadAndBlobsBundle, }, }; diff --git a/packages/types/src/allForks/types.ts b/packages/types/src/allForks/types.ts index 59768a5a3308..d097f6db2936 100644 --- a/packages/types/src/allForks/types.ts +++ b/packages/types/src/allForks/types.ts @@ -4,12 +4,14 @@ import {ts as altair} from "../altair/index.js"; import {ts as bellatrix} from "../bellatrix/index.js"; import {ts as capella} from "../capella/index.js"; import {ts as deneb} from "../deneb/index.js"; +import {ts as electra} from "../electra/index.js"; import {ssz as phase0Ssz} from "../phase0/index.js"; import {ssz as altairSsz} from "../altair/index.js"; import {ssz as bellatrixSsz} from "../bellatrix/index.js"; import {ssz as capellaSsz} from "../capella/index.js"; import {ssz as denebSsz} from "../deneb/index.js"; +import {ssz as electraSsz} from "../electra/index.js"; // Re-export union types for types that are _known_ to differ @@ -18,52 +20,69 @@ export type BeaconBlockBody = | altair.BeaconBlockBody | bellatrix.BeaconBlockBody | capella.BeaconBlockBody - | deneb.BeaconBlockBody; + | deneb.BeaconBlockBody + | electra.BeaconBlockBody; export type BeaconBlock = | phase0.BeaconBlock | altair.BeaconBlock | bellatrix.BeaconBlock | capella.BeaconBlock - | deneb.BeaconBlock; + | deneb.BeaconBlock + | electra.BeaconBlock; export type SignedBeaconBlock = | phase0.SignedBeaconBlock | altair.SignedBeaconBlock | bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock - | deneb.SignedBeaconBlock; + | deneb.SignedBeaconBlock + | electra.SignedBeaconBlock; export type BeaconState = | phase0.BeaconState | altair.BeaconState | bellatrix.BeaconState | capella.BeaconState - | deneb.BeaconState; + | deneb.BeaconState + | electra.BeaconState; export type Metadata = phase0.Metadata | altair.Metadata; // For easy reference in the assemble block for building payloads -export type ExecutionBlockBody = bellatrix.BeaconBlockBody | capella.BeaconBlockBody | deneb.BeaconBlockBody; +export type ExecutionBlockBody = + | bellatrix.BeaconBlockBody + | capella.BeaconBlockBody + | deneb.BeaconBlockBody + | electra.BeaconBlockBody; // These two additional types will also change bellatrix forward -export type ExecutionPayload = bellatrix.ExecutionPayload | capella.ExecutionPayload | deneb.ExecutionPayload; +export type ExecutionPayload = + | bellatrix.ExecutionPayload + | capella.ExecutionPayload + | deneb.ExecutionPayload + | electra.ExecutionPayload; export type ExecutionPayloadHeader = | bellatrix.ExecutionPayloadHeader | capella.ExecutionPayloadHeader - | deneb.ExecutionPayloadHeader; + | deneb.ExecutionPayloadHeader + | electra.ExecutionPayloadHeader; // Blinded types that will change across forks export type BlindedBeaconBlockBody = | bellatrix.BlindedBeaconBlockBody | capella.BlindedBeaconBlockBody - | deneb.BlindedBeaconBlockBody; -export type BlindedBeaconBlock = bellatrix.BlindedBeaconBlock | capella.BlindedBeaconBlock | deneb.BlindedBeaconBlock; + | deneb.BlindedBeaconBlockBody + | electra.BlindedBeaconBlockBody; +export type BlindedBeaconBlock = + | bellatrix.BlindedBeaconBlock + | capella.BlindedBeaconBlock + | deneb.BlindedBeaconBlock + | electra.BlindedBeaconBlock; export type SignedBlindedBeaconBlock = | bellatrix.SignedBlindedBeaconBlock | capella.SignedBlindedBeaconBlock - | deneb.SignedBlindedBeaconBlock; + | deneb.SignedBlindedBeaconBlock + | electra.SignedBlindedBeaconBlock; // Full or blinded types -export type FullOrBlindedExecutionPayload = - | bellatrix.FullOrBlindedExecutionPayload - | capella.FullOrBlindedExecutionPayload; +export type FullOrBlindedExecutionPayload = ExecutionPayload | ExecutionPayloadHeader; export type FullOrBlindedBeaconBlockBody = BeaconBlockBody | BlindedBeaconBlockBody; export type FullOrBlindedBeaconBlock = BeaconBlock | BlindedBeaconBlock; export type FullOrBlindedSignedBeaconBlock = SignedBeaconBlock | SignedBlindedBeaconBlock; @@ -80,30 +99,52 @@ export type SignedBeaconBlockOrContents = SignedBeaconBlock | SignedBlockContent export type FullOrBlindedBeaconBlockOrContents = BeaconBlockOrContents | BlindedBeaconBlock; -export type BuilderBid = bellatrix.BuilderBid | capella.BuilderBid | deneb.BuilderBid; -export type SignedBuilderBid = bellatrix.SignedBuilderBid | capella.SignedBuilderBid | deneb.SignedBuilderBid; -export type ExecutionPayloadAndBlobsBundle = deneb.ExecutionPayloadAndBlobsBundle; +export type BuilderBid = bellatrix.BuilderBid | capella.BuilderBid | deneb.BuilderBid | electra.BuilderBid; +export type SignedBuilderBid = + | bellatrix.SignedBuilderBid + | capella.SignedBuilderBid + | deneb.SignedBuilderBid + | electra.SignedBuilderBid; +export type ExecutionPayloadAndBlobsBundle = + | deneb.ExecutionPayloadAndBlobsBundle + | electra.ExecutionPayloadAndBlobsBundle; -export type LightClientHeader = altair.LightClientHeader | capella.LightClientHeader | deneb.LightClientHeader; +export type LightClientHeader = + | altair.LightClientHeader + | capella.LightClientHeader + | deneb.LightClientHeader + | electra.LightClientHeader; export type LightClientBootstrap = | altair.LightClientBootstrap | capella.LightClientBootstrap - | deneb.LightClientBootstrap; -export type LightClientUpdate = altair.LightClientUpdate | capella.LightClientUpdate | deneb.LightClientUpdate; + | deneb.LightClientBootstrap + | electra.LightClientBootstrap; +export type LightClientUpdate = + | altair.LightClientUpdate + | capella.LightClientUpdate + | deneb.LightClientUpdate + | electra.LightClientUpdate; export type LightClientFinalityUpdate = | altair.LightClientFinalityUpdate | capella.LightClientFinalityUpdate - | deneb.LightClientFinalityUpdate; + | deneb.LightClientFinalityUpdate + | electra.LightClientFinalityUpdate; export type LightClientOptimisticUpdate = | altair.LightClientOptimisticUpdate | capella.LightClientOptimisticUpdate - | deneb.LightClientOptimisticUpdate; -export type LightClientStore = altair.LightClientStore | capella.LightClientStore | deneb.LightClientStore; + | deneb.LightClientOptimisticUpdate + | electra.LightClientOptimisticUpdate; +export type LightClientStore = + | altair.LightClientStore + | capella.LightClientStore + | deneb.LightClientStore + | electra.LightClientStore; export type SSEPayloadAttributes = | bellatrix.SSEPayloadAttributes | capella.SSEPayloadAttributes - | deneb.SSEPayloadAttributes; + | deneb.SSEPayloadAttributes + | electra.SSEPayloadAttributes; /** * Types known to change between forks @@ -128,7 +169,12 @@ export type AllForksBlindedTypes = { }; export type AllForksLightClient = { - BeaconBlock: altair.BeaconBlock | bellatrix.BeaconBlock | capella.BeaconBlock | deneb.BeaconBlock; + BeaconBlock: + | altair.BeaconBlock + | bellatrix.BeaconBlock + | capella.BeaconBlock + | deneb.BeaconBlock + | electra.BeaconBlock; LightClientHeader: LightClientHeader; LightClientBootstrap: LightClientBootstrap; LightClientUpdate: LightClientUpdate; @@ -138,8 +184,12 @@ export type AllForksLightClient = { }; export type AllForksExecution = { - BeaconBlock: bellatrix.BeaconBlock | capella.BeaconBlock | deneb.BeaconBlock; - BeaconBlockBody: bellatrix.BeaconBlockBody | capella.BeaconBlockBody | deneb.BeaconBlockBody; + BeaconBlock: bellatrix.BeaconBlock | capella.BeaconBlock | deneb.BeaconBlock | electra.BeaconBlock; + BeaconBlockBody: + | bellatrix.BeaconBlockBody + | capella.BeaconBlockBody + | deneb.BeaconBlockBody + | electra.BeaconBlockBody; }; /** @@ -178,6 +228,7 @@ export type AllForksSSZTypes = { | typeof bellatrixSsz.BeaconBlockBody | typeof capellaSsz.BeaconBlockBody | typeof denebSsz.BeaconBlockBody + | typeof electraSsz.BeaconBlockBody >; BeaconBlock: AllForksTypeOf< | typeof phase0Ssz.BeaconBlock @@ -185,6 +236,7 @@ export type AllForksSSZTypes = { | typeof bellatrixSsz.BeaconBlock | typeof capellaSsz.BeaconBlock | typeof denebSsz.BeaconBlock + | typeof electraSsz.BeaconBlock >; SignedBeaconBlock: AllForksTypeOf< | typeof phase0Ssz.SignedBeaconBlock @@ -192,6 +244,7 @@ export type AllForksSSZTypes = { | typeof bellatrixSsz.SignedBeaconBlock | typeof capellaSsz.SignedBeaconBlock | typeof denebSsz.SignedBeaconBlock + | typeof electraSsz.SignedBeaconBlock >; BeaconState: AllForksTypeOf< | typeof phase0Ssz.BeaconState @@ -199,57 +252,86 @@ export type AllForksSSZTypes = { | typeof bellatrixSsz.BeaconState | typeof capellaSsz.BeaconState | typeof denebSsz.BeaconState + | typeof electraSsz.BeaconState >; Metadata: AllForksTypeOf; }; export type AllForksExecutionSSZTypes = { BeaconBlockBody: AllForksTypeOf< - typeof bellatrixSsz.BeaconBlockBody | typeof capellaSsz.BeaconBlockBody | typeof denebSsz.BeaconBlockBody + | typeof bellatrixSsz.BeaconBlockBody + | typeof capellaSsz.BeaconBlockBody + | typeof denebSsz.BeaconBlockBody + | typeof electraSsz.BeaconBlockBody >; BeaconBlock: AllForksTypeOf< - typeof bellatrixSsz.BeaconBlock | typeof capellaSsz.BeaconBlock | typeof denebSsz.BeaconBlock + | typeof bellatrixSsz.BeaconBlock + | typeof capellaSsz.BeaconBlock + | typeof denebSsz.BeaconBlock + | typeof electraSsz.BeaconBlock >; SignedBeaconBlock: AllForksTypeOf< - typeof bellatrixSsz.SignedBeaconBlock | typeof capellaSsz.SignedBeaconBlock | typeof denebSsz.SignedBeaconBlock + | typeof bellatrixSsz.SignedBeaconBlock + | typeof capellaSsz.SignedBeaconBlock + | typeof denebSsz.SignedBeaconBlock + | typeof electraSsz.SignedBeaconBlock >; BeaconState: AllForksTypeOf< - typeof bellatrixSsz.BeaconState | typeof capellaSsz.BeaconState | typeof denebSsz.BeaconState + | typeof bellatrixSsz.BeaconState + | typeof capellaSsz.BeaconState + | typeof denebSsz.BeaconState + | typeof electraSsz.BeaconState >; ExecutionPayload: AllForksTypeOf< - typeof bellatrixSsz.ExecutionPayload | typeof capellaSsz.ExecutionPayload | typeof denebSsz.ExecutionPayload + | typeof bellatrixSsz.ExecutionPayload + | typeof capellaSsz.ExecutionPayload + | typeof denebSsz.ExecutionPayload + | typeof electraSsz.ExecutionPayload >; ExecutionPayloadHeader: AllForksTypeOf< | typeof bellatrixSsz.ExecutionPayloadHeader | typeof capellaSsz.ExecutionPayloadHeader | typeof denebSsz.ExecutionPayloadHeader + | typeof electraSsz.ExecutionPayloadHeader >; BuilderBid: AllForksTypeOf< - typeof bellatrixSsz.BuilderBid | typeof capellaSsz.BuilderBid | typeof denebSsz.BuilderBid + | typeof bellatrixSsz.BuilderBid + | typeof capellaSsz.BuilderBid + | typeof denebSsz.BuilderBid + | typeof electraSsz.BuilderBid >; SignedBuilderBid: AllForksTypeOf< - typeof bellatrixSsz.SignedBuilderBid | typeof capellaSsz.SignedBuilderBid | typeof denebSsz.SignedBuilderBid + | typeof bellatrixSsz.SignedBuilderBid + | typeof capellaSsz.SignedBuilderBid + | typeof denebSsz.SignedBuilderBid + | typeof electraSsz.SignedBuilderBid >; SSEPayloadAttributes: AllForksTypeOf< | typeof bellatrixSsz.SSEPayloadAttributes | typeof capellaSsz.SSEPayloadAttributes | typeof denebSsz.SSEPayloadAttributes + | typeof electraSsz.SSEPayloadAttributes >; }; export type AllForksBlindedSSZTypes = { BeaconBlockBody: AllForksTypeOf< | typeof bellatrixSsz.BlindedBeaconBlockBody - | typeof capellaSsz.BlindedBeaconBlock - | typeof denebSsz.BlindedBeaconBlock + | typeof capellaSsz.BlindedBeaconBlockBody + | typeof denebSsz.BlindedBeaconBlockBody + | typeof electraSsz.BlindedBeaconBlockBody >; BeaconBlock: AllForksTypeOf< - typeof bellatrixSsz.BlindedBeaconBlock | typeof capellaSsz.BlindedBeaconBlock | typeof denebSsz.BlindedBeaconBlock + | typeof bellatrixSsz.BlindedBeaconBlock + | typeof capellaSsz.BlindedBeaconBlock + | typeof denebSsz.BlindedBeaconBlock + | typeof electraSsz.BlindedBeaconBlock >; SignedBeaconBlock: AllForksTypeOf< | typeof bellatrixSsz.SignedBlindedBeaconBlock | typeof capellaSsz.SignedBlindedBeaconBlock | typeof denebSsz.SignedBlindedBeaconBlock + | typeof electraSsz.SignedBlindedBeaconBlock >; }; @@ -259,40 +341,56 @@ export type AllForksLightClientSSZTypes = { | typeof bellatrixSsz.BeaconBlock | typeof capellaSsz.BeaconBlock | typeof denebSsz.BeaconBlock + | typeof electraSsz.BeaconBlock >; BeaconBlockBody: AllForksTypeOf< | typeof altairSsz.BeaconBlockBody | typeof bellatrixSsz.BeaconBlockBody | typeof capellaSsz.BeaconBlockBody | typeof denebSsz.BeaconBlockBody + | typeof electraSsz.BeaconBlockBody >; LightClientHeader: AllForksTypeOf< - typeof altairSsz.LightClientHeader | typeof capellaSsz.LightClientHeader | typeof denebSsz.LightClientHeader + | typeof altairSsz.LightClientHeader + | typeof capellaSsz.LightClientHeader + | typeof denebSsz.LightClientHeader + | typeof electraSsz.LightClientHeader >; LightClientBootstrap: AllForksTypeOf< | typeof altairSsz.LightClientBootstrap | typeof capellaSsz.LightClientBootstrap | typeof denebSsz.LightClientBootstrap + | typeof electraSsz.LightClientBootstrap >; LightClientUpdate: AllForksTypeOf< - typeof altairSsz.LightClientUpdate | typeof capellaSsz.LightClientUpdate | typeof denebSsz.LightClientUpdate + | typeof altairSsz.LightClientUpdate + | typeof capellaSsz.LightClientUpdate + | typeof denebSsz.LightClientUpdate + | typeof electraSsz.LightClientUpdate >; LightClientFinalityUpdate: AllForksTypeOf< | typeof altairSsz.LightClientFinalityUpdate | typeof capellaSsz.LightClientFinalityUpdate | typeof denebSsz.LightClientFinalityUpdate + | typeof electraSsz.LightClientFinalityUpdate >; LightClientOptimisticUpdate: AllForksTypeOf< | typeof altairSsz.LightClientOptimisticUpdate | typeof capellaSsz.LightClientOptimisticUpdate | typeof denebSsz.LightClientOptimisticUpdate + | typeof electraSsz.LightClientOptimisticUpdate >; LightClientStore: AllForksTypeOf< - typeof altairSsz.LightClientStore | typeof capellaSsz.LightClientStore | typeof denebSsz.LightClientStore + | typeof altairSsz.LightClientStore + | typeof capellaSsz.LightClientStore + | typeof denebSsz.LightClientStore + | typeof electraSsz.LightClientStore >; }; export type AllForksBlobsSSZTypes = { BlobSidecar: AllForksTypeOf; - ExecutionPayloadAndBlobsBundle: AllForksTypeOf; + ExecutionPayloadAndBlobsBundle: AllForksTypeOf< + typeof denebSsz.ExecutionPayloadAndBlobsBundle | typeof electraSsz.ExecutionPayloadAndBlobsBundle + >; }; diff --git a/packages/types/src/deneb/sszTypes.ts b/packages/types/src/deneb/sszTypes.ts index c93c3f145beb..052db6a3f2d9 100644 --- a/packages/types/src/deneb/sszTypes.ts +++ b/packages/types/src/deneb/sszTypes.ts @@ -98,7 +98,7 @@ export const BeaconBlockBody = new ContainerType( export const BeaconBlock = new ContainerType( { - ...capellaSsz.BeaconBlock.fields, + ...phase0Ssz.BeaconBlock.fields, body: BeaconBlockBody, // Modified in DENEB }, {typeName: "BeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} @@ -149,7 +149,7 @@ export const BlindedBeaconBlockBody = new ContainerType( export const BlindedBeaconBlock = new ContainerType( { - ...capellaSsz.BlindedBeaconBlock.fields, + ...bellatrixSsz.BlindedBeaconBlock.fields, body: BlindedBeaconBlockBody, // Modified in DENEB }, {typeName: "BlindedBeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index 30690a499845..bdbade4a94a5 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -1,12 +1,43 @@ -import {ContainerType} from "@chainsafe/ssz"; +import {ContainerType, ListCompositeType} from "@chainsafe/ssz"; +import { + EPOCHS_PER_SYNC_COMMITTEE_PERIOD, + SLOTS_PER_EPOCH, + HISTORICAL_ROOTS_LIMIT, + MAX_TRANSACTIONS_PER_INCLUSION_LIST, +} from "@lodestar/params"; import {ssz as primitiveSsz} from "../primitive/index.js"; +import {ssz as phase0Ssz} from "../phase0/index.js"; +import {ssz as altairSsz} from "../altair/index.js"; +import {ssz as bellatrixSsz} from "../bellatrix/index.js"; +import {ssz as capellaSsz} from "../capella/index.js"; import {ssz as denebSsz} from "../deneb/index.js"; -const {BLSSignature} = primitiveSsz; +const {BLSSignature, ExecutionAddress, Root, UintBn256, BLSPubkey, ValidatorIndex, Slot, UintNum64} = primitiveSsz; + +export const ILSummary = new ListCompositeType(ExecutionAddress, MAX_TRANSACTIONS_PER_INCLUSION_LIST); +export const ILTransactions = new ListCompositeType(bellatrixSsz.Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST); + +export const SignedInclusionListSummary = new ContainerType( + { + summary: ILSummary, + signature: BLSSignature, + }, + {typeName: "SignedInclusionListSummary", jsonCase: "eth2"} +); + +export const NewInclusionListRequest = new ContainerType( + { + inclusionList: ILTransactions, + summary: ILSummary, + parentBlockHash: Root, + }, + {typeName: "NewInclusionListRequest", jsonCase: "eth2"} +); export const ExecutionPayload = new ContainerType( { ...denebSsz.ExecutionPayload.fields, + previousInclusionListSummary: SignedInclusionListSummary, }, {typeName: "ExecutionPayload", jsonCase: "eth2"} ); @@ -14,20 +45,25 @@ export const ExecutionPayload = new ContainerType( export const ExecutionPayloadHeader = new ContainerType( { ...denebSsz.ExecutionPayloadHeader.fields, + previousInclusionListSummaryRoot: Root, }, {typeName: "ExecutionPayloadHeader", jsonCase: "eth2"} ); export const BeaconBlockBody = new ContainerType( { - ...denebSsz.BeaconBlockBody.fields, + ...altairSsz.BeaconBlockBody.fields, + executionPayload: ExecutionPayload, // Modified in ELECTRA + blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges, + blobKzgCommitments: denebSsz.BlobKzgCommitments, }, {typeName: "BeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} ); export const BeaconBlock = new ContainerType( { - ...denebSsz.BeaconBlock.fields, + ...phase0Ssz.BeaconBlock.fields, + body: BeaconBlockBody, // Modified in ELECTRA }, {typeName: "BeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} ); @@ -40,23 +76,20 @@ export const SignedBeaconBlock = new ContainerType( {typeName: "SignedBeaconBlock", jsonCase: "eth2"} ); -export const BlobSidecar = new ContainerType( - { - ...denebSsz.BlobSidecar.fields, - }, - {typeName: "BlobSidecar", jsonCase: "eth2"} -); - export const BlindedBeaconBlockBody = new ContainerType( { - ...denebSsz.BlindedBeaconBlockBody.fields, + ...altairSsz.BeaconBlockBody.fields, + executionPayloadHeader: ExecutionPayloadHeader, // Modified in ELECTRA + blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges, + blobKzgCommitments: denebSsz.BlobKzgCommitments, }, {typeName: "BlindedBeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} ); export const BlindedBeaconBlock = new ContainerType( { - ...denebSsz.BlindedBeaconBlock.fields, + ...bellatrixSsz.BlindedBeaconBlock.fields, + body: BlindedBeaconBlockBody, // Modified in ELECTRA }, {typeName: "BlindedBeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} ); @@ -71,78 +104,153 @@ export const SignedBlindedBeaconBlock = new ContainerType( export const BuilderBid = new ContainerType( { - ...denebSsz.BuilderBid.fields, + header: ExecutionPayloadHeader, + blobKzgCommitments: denebSsz.BlobKzgCommitments, + value: UintBn256, + pubkey: BLSPubkey, }, {typeName: "BuilderBid", jsonCase: "eth2"} ); -export const SignedBuilderBid = new ContainerType( +export const ExecutionPayloadAndBlobsBundle = new ContainerType( { - message: BuilderBid, - signature: BLSSignature, + executionPayload: ExecutionPayload, + blobsBundle: denebSsz.BlobsBundle, }, - {typeName: "SignedBuilderBid", jsonCase: "eth2"} + {typeName: "ExecutionPayloadAndBlobsBundle", jsonCase: "eth2"} ); -export const ExecutionPayloadAndBlobsBundle = new ContainerType( +export const SignedBuilderBid = new ContainerType( { - ...denebSsz.ExecutionPayloadAndBlobsBundle.fields, + message: BuilderBid, + signature: BLSSignature, }, - {typeName: "ExecutionPayloadAndBlobsBundle", jsonCase: "eth2"} + {typeName: "SignedBuilderBid", jsonCase: "eth2"} ); +// We don't spread capella.BeaconState fields since we need to replace +// latestExecutionPayloadHeader and we cannot keep order doing that export const BeaconState = new ContainerType( { - ...denebSsz.BeaconState.fields, + genesisTime: UintNum64, + genesisValidatorsRoot: Root, + slot: primitiveSsz.Slot, + fork: phase0Ssz.Fork, + // History + latestBlockHeader: phase0Ssz.BeaconBlockHeader, + blockRoots: phase0Ssz.HistoricalBlockRoots, + stateRoots: phase0Ssz.HistoricalStateRoots, + // historical_roots Frozen in Capella, replaced by historical_summaries + historicalRoots: new ListCompositeType(Root, HISTORICAL_ROOTS_LIMIT), + // Eth1 + eth1Data: phase0Ssz.Eth1Data, + eth1DataVotes: phase0Ssz.Eth1DataVotes, + eth1DepositIndex: UintNum64, + // Registry + validators: phase0Ssz.Validators, + balances: phase0Ssz.Balances, + randaoMixes: phase0Ssz.RandaoMixes, + // Slashings + slashings: phase0Ssz.Slashings, + // Participation + previousEpochParticipation: altairSsz.EpochParticipation, + currentEpochParticipation: altairSsz.EpochParticipation, + // Finality + justificationBits: phase0Ssz.JustificationBits, + previousJustifiedCheckpoint: phase0Ssz.Checkpoint, + currentJustifiedCheckpoint: phase0Ssz.Checkpoint, + finalizedCheckpoint: phase0Ssz.Checkpoint, + // Inactivity + inactivityScores: altairSsz.InactivityScores, + // Sync + currentSyncCommittee: altairSsz.SyncCommittee, + nextSyncCommittee: altairSsz.SyncCommittee, + // Execution + latestExecutionPayloadHeader: ExecutionPayloadHeader, // Modified in ELECTRA + // Withdrawals + nextWithdrawalIndex: capellaSsz.BeaconState.fields.nextWithdrawalIndex, + nextWithdrawalValidatorIndex: capellaSsz.BeaconState.fields.nextWithdrawalValidatorIndex, + // Deep history valid from Capella onwards + historicalSummaries: capellaSsz.BeaconState.fields.historicalSummaries, + // Inclusion list validation + previousProposerIndex: ValidatorIndex, // New in Electra }, {typeName: "BeaconState", jsonCase: "eth2"} ); export const LightClientHeader = new ContainerType( { - ...denebSsz.LightClientHeader.fields, + beacon: phase0Ssz.BeaconBlockHeader, + execution: ExecutionPayloadHeader, + executionBranch: capellaSsz.LightClientHeader.fields.executionBranch, }, {typeName: "LightClientHeader", jsonCase: "eth2"} ); export const LightClientBootstrap = new ContainerType( { - ...denebSsz.LightClientBootstrap.fields, + header: LightClientHeader, + currentSyncCommittee: altairSsz.SyncCommittee, + currentSyncCommitteeBranch: altairSsz.LightClientBootstrap.fields.currentSyncCommitteeBranch, }, {typeName: "LightClientBootstrap", jsonCase: "eth2"} ); export const LightClientUpdate = new ContainerType( { - ...denebSsz.LightClientUpdate.fields, + attestedHeader: LightClientHeader, + nextSyncCommittee: altairSsz.SyncCommittee, + nextSyncCommitteeBranch: altairSsz.LightClientUpdate.fields.nextSyncCommitteeBranch, + finalizedHeader: LightClientHeader, + finalityBranch: altairSsz.LightClientUpdate.fields.finalityBranch, + syncAggregate: altairSsz.SyncAggregate, + signatureSlot: Slot, }, {typeName: "LightClientUpdate", jsonCase: "eth2"} ); export const LightClientFinalityUpdate = new ContainerType( { - ...denebSsz.LightClientFinalityUpdate.fields, + attestedHeader: LightClientHeader, + finalizedHeader: LightClientHeader, + finalityBranch: altairSsz.LightClientFinalityUpdate.fields.finalityBranch, + syncAggregate: altairSsz.SyncAggregate, + signatureSlot: Slot, }, {typeName: "LightClientFinalityUpdate", jsonCase: "eth2"} ); export const LightClientOptimisticUpdate = new ContainerType( { - ...denebSsz.LightClientOptimisticUpdate.fields, + attestedHeader: LightClientHeader, + syncAggregate: altairSsz.SyncAggregate, + signatureSlot: Slot, }, {typeName: "LightClientOptimisticUpdate", jsonCase: "eth2"} ); export const LightClientStore = new ContainerType( { - ...denebSsz.LightClientStore.fields, + snapshot: LightClientBootstrap, + validUpdates: new ListCompositeType(LightClientUpdate, EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH), }, {typeName: "LightClientStore", jsonCase: "eth2"} ); +// PayloadAttributes primarily for SSE event +export const PayloadAttributes = new ContainerType( + { + ...capellaSsz.PayloadAttributes.fields, + parentBeaconBlockRoot: Root, + previousInclusionListSummary: SignedInclusionListSummary, + }, + {typeName: "PayloadAttributes", jsonCase: "eth2"} +); + export const SSEPayloadAttributes = new ContainerType( { - ...denebSsz.SSEPayloadAttributes.fields, + ...bellatrixSsz.SSEPayloadAttributesCommon.fields, + payloadAttributes: PayloadAttributes, }, {typeName: "SSEPayloadAttributes", jsonCase: "eth2"} ); diff --git a/packages/types/src/electra/types.ts b/packages/types/src/electra/types.ts index 198259eed1dd..e5ecf598db49 100644 --- a/packages/types/src/electra/types.ts +++ b/packages/types/src/electra/types.ts @@ -1,8 +1,10 @@ import {ValueOf} from "@chainsafe/ssz"; import * as ssz from "./sszTypes.js"; -export type BlobSidecar = ValueOf; -export type ExecutionPayloadAndBlobsBundle = ValueOf; +export type ILSummary = ValueOf; +export type ILTransactions = ValueOf; +export type SignedInclusionListSummary = ValueOf; +export type NewInclusionListRequest = ValueOf; export type ExecutionPayload = ValueOf; export type ExecutionPayloadHeader = ValueOf; @@ -11,15 +13,15 @@ export type BeaconBlockBody = ValueOf; export type BeaconBlock = ValueOf; export type SignedBeaconBlock = ValueOf; -export type BeaconState = ValueOf; - export type BlindedBeaconBlockBody = ValueOf; export type BlindedBeaconBlock = ValueOf; export type SignedBlindedBeaconBlock = ValueOf; export type BuilderBid = ValueOf; +export type ExecutionPayloadAndBlobsBundle = ValueOf; export type SignedBuilderBid = ValueOf; -export type SSEPayloadAttributes = ValueOf; + +export type BeaconState = ValueOf; export type LightClientHeader = ValueOf; export type LightClientBootstrap = ValueOf; @@ -27,3 +29,5 @@ export type LightClientUpdate = ValueOf; export type LightClientFinalityUpdate = ValueOf; export type LightClientOptimisticUpdate = ValueOf; export type LightClientStore = ValueOf; + +export type SSEPayloadAttributes = ValueOf;