diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index 087ff9515003..603d66b11308 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -34,6 +34,8 @@ import { ATTESTATION_SUBNET_COUNT, TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE, SYNC_COMMITTEE_SUBNET_COUNT, + BLOB_TX_TYPE, + VERSIONED_HASH_VERSION_KZG, } from "@lodestar/params"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -94,4 +96,8 @@ export const specConstants = { // ## Capella domain types DOMAIN_BLS_TO_EXECUTION_CHANGE, + + // EIP4844 types + BLOB_TX_TYPE, + VERSIONED_HASH_VERSION_KZG, }; diff --git a/packages/beacon-node/src/network/gossip/encoding.ts b/packages/beacon-node/src/network/gossip/encoding.ts index a05d4b550e17..3ca2ebd4890a 100644 --- a/packages/beacon-node/src/network/gossip/encoding.ts +++ b/packages/beacon-node/src/network/gossip/encoding.ts @@ -39,16 +39,14 @@ export function msgIdFn(gossipTopicCache: GossipTopicCache, msg: Message): Uint8 let vec: Uint8Array[]; - switch (topic.fork) { + if (topic.fork === ForkName.phase0) { // message id for phase0. // ``` // SHA256(MESSAGE_DOMAIN_VALID_SNAPPY + snappy_decompress(message.data))[:20] // ``` - case ForkName.phase0: - vec = [MESSAGE_DOMAIN_VALID_SNAPPY, msg.data]; - break; - - // message id for altair. + vec = [MESSAGE_DOMAIN_VALID_SNAPPY, msg.data]; + } else { + // message id for altair and subsequent future forks. // ``` // SHA256( // MESSAGE_DOMAIN_VALID_SNAPPY + @@ -58,14 +56,7 @@ export function msgIdFn(gossipTopicCache: GossipTopicCache, msg: Message): Uint8 // )[:20] // ``` // https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.7/specs/altair/p2p-interface.md#topics-and-messages - // - // TODO: check if the capella handling is same as the other forks - case ForkName.altair: - case ForkName.bellatrix: - case ForkName.capella: { - vec = [MESSAGE_DOMAIN_VALID_SNAPPY, intToBytes(msg.topic.length, 8), Buffer.from(msg.topic), msg.data]; - break; - } + vec = [MESSAGE_DOMAIN_VALID_SNAPPY, intToBytes(msg.topic.length, 8), Buffer.from(msg.topic), msg.data]; } return Buffer.from(digest(Buffer.concat(vec))).subarray(0, 20); diff --git a/packages/beacon-node/test/e2e/api/impl/config.test.ts b/packages/beacon-node/test/e2e/api/impl/config.test.ts index deb6fc442d12..9913cf400b5a 100644 --- a/packages/beacon-node/test/e2e/api/impl/config.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/config.test.ts @@ -9,6 +9,9 @@ const CONSTANT_NAMES_SKIP_LIST = new Set([ // This constant can also be derived from existing constants so it's not critical. // PARTICIPATION_FLAG_WEIGHTS = [TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_WEIGHT, TIMELY_HEAD_WEIGHT] "PARTICIPATION_FLAG_WEIGHTS", + // TODO EIP-4844: This constant was added then removed on a spec re-write. + // When developing eip-4844 branch the tracked version still doesn't have released the removal + "DOMAIN_BLOBS_SIDECAR", ]); describe("api / impl / config", function () { diff --git a/packages/beacon-node/test/spec/presets/fork.ts b/packages/beacon-node/test/spec/presets/fork.ts index 776c45db2210..b004ffb5ecf3 100644 --- a/packages/beacon-node/test/spec/presets/fork.ts +++ b/packages/beacon-node/test/spec/presets/fork.ts @@ -29,6 +29,8 @@ export const fork: TestRunnerFn = (forkNext) return slotFns.upgradeStateToBellatrix(preState as CachedBeaconStateAltair); case ForkName.capella: return slotFns.upgradeStateToCapella(preState as CachedBeaconStateBellatrix); + case ForkName.eip4844: + throw Error("eip4844 not implemented"); } }, options: { diff --git a/packages/beacon-node/test/spec/presets/transition.ts b/packages/beacon-node/test/spec/presets/transition.ts index e0b0b0f8e5f6..83444a181f17 100644 --- a/packages/beacon-node/test/spec/presets/transition.ts +++ b/packages/beacon-node/test/spec/presets/transition.ts @@ -84,6 +84,8 @@ function getTransitionConfig(fork: ForkName, forkEpoch: number): Partial = { phase0: { @@ -47,6 +49,14 @@ function getForkConfig({ prevVersion: Buffer.from([0, 0, 0, 2]), prevForkName: ForkName.bellatrix, }, + eip4844: { + name: ForkName.eip4844, + seq: ForkSeq.eip4844, + epoch: eip4844, + version: Buffer.from([0, 0, 0, 4]), + prevVersion: Buffer.from([0, 0, 0, 3]), + prevForkName: ForkName.capella, + }, }; const forksAscendingEpochOrder = Object.values(forks); const forksDescendingEpochOrder = Object.values(forks).reverse(); @@ -122,9 +132,11 @@ const testScenarios = [ for (const testScenario of testScenarios) { const {phase0, altair, bellatrix, capella, testCases} = testScenario; + // TODO EIP-4844: Is it necessary to test? + const eip4844 = Infinity; describe(`network / fork: phase0: ${phase0}, altair: ${altair}, bellatrix: ${bellatrix} capella: ${capella}`, () => { - const forkConfig = getForkConfig({phase0, altair, bellatrix, capella}); + const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, eip4844}); const forks = forkConfig.forks; for (const testCase of testCases) { const {epoch, currentFork, nextFork, activeForks} = testCase; diff --git a/packages/config/src/chainConfig/presets/mainnet.ts b/packages/config/src/chainConfig/presets/mainnet.ts index e437c8fdac58..900450e236b8 100644 --- a/packages/config/src/chainConfig/presets/mainnet.ts +++ b/packages/config/src/chainConfig/presets/mainnet.ts @@ -41,6 +41,10 @@ export const chainConfig: IChainConfig = { CAPELLA_FORK_VERSION: b("0x03000000"), CAPELLA_FORK_EPOCH: Infinity, + // EIP-4844 + EIP4844_FORK_VERSION: b("0x04000000"), + EIP4844_FORK_EPOCH: Infinity, + // Time parameters // --------------------------------------------------------------- // 12 seconds @@ -74,4 +78,10 @@ export const chainConfig: IChainConfig = { DEPOSIT_CHAIN_ID: 1, DEPOSIT_NETWORK_ID: 1, DEPOSIT_CONTRACT_ADDRESS: b("0x00000000219ab540356cBB839Cbe05303d7705Fa"), + + // Blobs + // --------------------------------------------------------------- + // https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/p2p-interface.md#configuration + MAX_REQUEST_BLOBS_SIDECARS: 128, + MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS: 4096, }; diff --git a/packages/config/src/chainConfig/presets/minimal.ts b/packages/config/src/chainConfig/presets/minimal.ts index 0885c6d79e9f..f63dad4e00d7 100644 --- a/packages/config/src/chainConfig/presets/minimal.ts +++ b/packages/config/src/chainConfig/presets/minimal.ts @@ -39,6 +39,9 @@ export const chainConfig: IChainConfig = { // Capella CAPELLA_FORK_VERSION: b("0x03000001"), CAPELLA_FORK_EPOCH: Infinity, + // EIP-4844 + EIP4844_FORK_VERSION: b("0x04000001"), + EIP4844_FORK_EPOCH: Infinity, // Time parameters // --------------------------------------------------------------- @@ -74,4 +77,10 @@ export const chainConfig: IChainConfig = { DEPOSIT_NETWORK_ID: 5, // Configured on a per testnet basis DEPOSIT_CONTRACT_ADDRESS: b("0x1234567890123456789012345678901234567890"), + + // Blobs + // --------------------------------------------------------------- + // https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/p2p-interface.md#configuration + MAX_REQUEST_BLOBS_SIDECARS: 128, + MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS: 4096, }; diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 728c8273ed37..84430e18abe6 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -37,6 +37,9 @@ export type IChainConfig = { // Capella CAPELLA_FORK_VERSION: Uint8Array; CAPELLA_FORK_EPOCH: number; + // EIP-4844 + EIP4844_FORK_VERSION: Uint8Array; + EIP4844_FORK_EPOCH: number; // Time parameters SECONDS_PER_SLOT: number; @@ -59,6 +62,12 @@ export type IChainConfig = { DEPOSIT_CHAIN_ID: number; DEPOSIT_NETWORK_ID: number; DEPOSIT_CONTRACT_ADDRESS: Uint8Array; + + // EIP-4844 + // https://github.com/ethereum/consensus-specs/blob/11a037fd9227e29ee809c9397b09f8cc3383a8c0/specs/eip4844/p2p-interface.md#configuration + MAX_REQUEST_BLOBS_SIDECARS: number; + /** The minimum epoch range over which a node must serve blobs sidecars */ + MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS: number; }; export const chainConfigTypes: SpecTypes = { @@ -86,6 +95,9 @@ export const chainConfigTypes: SpecTypes = { // Capella CAPELLA_FORK_VERSION: "bytes", CAPELLA_FORK_EPOCH: "number", + // EIP-4844 + EIP4844_FORK_VERSION: "bytes", + EIP4844_FORK_EPOCH: "number", // Time parameters SECONDS_PER_SLOT: "number", @@ -108,6 +120,10 @@ export const chainConfigTypes: SpecTypes = { DEPOSIT_CHAIN_ID: "number", DEPOSIT_NETWORK_ID: "number", DEPOSIT_CONTRACT_ADDRESS: "bytes", + + // Blobs + MAX_REQUEST_BLOBS_SIDECARS: "number", + MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS: "number", }; /** Allows values in a Spec file */ diff --git a/packages/config/src/forkConfig/index.ts b/packages/config/src/forkConfig/index.ts index 149fe6a4f377..3ef70c13ef31 100644 --- a/packages/config/src/forkConfig/index.ts +++ b/packages/config/src/forkConfig/index.ts @@ -39,10 +39,18 @@ export function createIForkConfig(config: IChainConfig): IForkConfig { prevVersion: config.BELLATRIX_FORK_VERSION, prevForkName: ForkName.bellatrix, }; + const eip4844: IForkInfo = { + name: ForkName.eip4844, + seq: ForkSeq.eip4844, + epoch: config.EIP4844_FORK_EPOCH, + version: config.EIP4844_FORK_VERSION, + prevVersion: config.CAPELLA_FORK_VERSION, + prevForkName: ForkName.capella, + }; /** Forks in order order of occurence, `phase0` first */ // Note: Downstream code relies on proper ordering. - const forks = {phase0, altair, bellatrix, capella}; + const forks = {phase0, altair, bellatrix, capella, eip4844}; // Prevents allocating an array on every getForkInfo() call const forksAscendingEpochOrder = Object.values(forks); diff --git a/packages/params/src/forkName.ts b/packages/params/src/forkName.ts index 604cd8260f16..632a58375690 100644 --- a/packages/params/src/forkName.ts +++ b/packages/params/src/forkName.ts @@ -6,6 +6,7 @@ export enum ForkName { altair = "altair", bellatrix = "bellatrix", capella = "capella", + eip4844 = "eip4844", } /** @@ -16,4 +17,5 @@ export enum ForkSeq { altair = 1, bellatrix = 2, capella = 3, + eip4844 = 4, } diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index a93da339cbcc..5540d9bcebb8 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -88,6 +88,9 @@ export const { WITHDRAWAL_QUEUE_LIMIT, MAX_BLS_TO_EXECUTION_CHANGES, MAX_WITHDRAWALS_PER_PAYLOAD, + + FIELD_ELEMENTS_PER_BLOB, + MAX_BLOBS_PER_BLOCK, } = {...presets[ACTIVE_PRESET], ...userOverrides}; //////////// @@ -205,3 +208,8 @@ export const MAX_REQUEST_LIGHT_CLIENT_COMMITTEE_HASHES = 128; */ export const SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY = 128; export const INTERVALS_PER_SLOT = 3; + +// EIP-4844: Crypto const +export const BYTES_PER_FIELD_ELEMENT = 32; +export const BLOB_TX_TYPE = 0x05; +export const VERSIONED_HASH_VERSION_KZG = 0x01; diff --git a/packages/params/src/interface/eip4844.ts b/packages/params/src/interface/eip4844.ts new file mode 100644 index 000000000000..e4eafdf4795d --- /dev/null +++ b/packages/params/src/interface/eip4844.ts @@ -0,0 +1,5 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +export type EIP4844Preset = { + FIELD_ELEMENTS_PER_BLOB: number; + MAX_BLOBS_PER_BLOCK: number; +}; diff --git a/packages/params/src/interface/index.ts b/packages/params/src/interface/index.ts index aeded4086d14..f3a4c3894c25 100644 --- a/packages/params/src/interface/index.ts +++ b/packages/params/src/interface/index.ts @@ -2,5 +2,6 @@ import {Phase0Preset} from "./phase0.js"; import {AltairPreset} from "./altair.js"; import {BellatrixPreset} from "./bellatrix.js"; import {CapellaPreset} from "./capella.js"; +import {EIP4844Preset} from "./eip4844.js"; -export type BeaconPreset = Phase0Preset & AltairPreset & BellatrixPreset & CapellaPreset; +export type BeaconPreset = Phase0Preset & AltairPreset & BellatrixPreset & CapellaPreset & EIP4844Preset; diff --git a/packages/params/src/presets/mainnet/eip4844.ts b/packages/params/src/presets/mainnet/eip4844.ts new file mode 100644 index 000000000000..c47f1b6ac22b --- /dev/null +++ b/packages/params/src/presets/mainnet/eip4844.ts @@ -0,0 +1,8 @@ +import {EIP4844Preset} from "../../interface/eip4844.js"; + +/* eslint-disable @typescript-eslint/naming-convention */ +export const eip4844: EIP4844Preset = { + // https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/eip4844.yaml + FIELD_ELEMENTS_PER_BLOB: 4096, + MAX_BLOBS_PER_BLOCK: 16, +}; diff --git a/packages/params/src/presets/mainnet/index.ts b/packages/params/src/presets/mainnet/index.ts index 67b8d3b073da..c4290535d5c3 100644 --- a/packages/params/src/presets/mainnet/index.ts +++ b/packages/params/src/presets/mainnet/index.ts @@ -3,6 +3,7 @@ import {phase0} from "./phase0.js"; import {altair} from "./altair.js"; import {bellatrix} from "./bellatrix.js"; import {capella} from "./capella.js"; +import {eip4844} from "./eip4844.js"; export const commit = "v1.2.0"; @@ -11,4 +12,5 @@ export const preset: BeaconPreset = { ...altair, ...bellatrix, ...capella, + ...eip4844, }; diff --git a/packages/params/src/presets/minimal/eip4844.ts b/packages/params/src/presets/minimal/eip4844.ts new file mode 100644 index 000000000000..99b153b098da --- /dev/null +++ b/packages/params/src/presets/minimal/eip4844.ts @@ -0,0 +1,8 @@ +import {EIP4844Preset} from "../../interface/eip4844.js"; + +/* eslint-disable @typescript-eslint/naming-convention */ +export const eip4844: EIP4844Preset = { + // https://github.com/ethereum/consensus-specs/blob/dev/presets/minimal/eip4844.yaml + FIELD_ELEMENTS_PER_BLOB: 4, + MAX_BLOBS_PER_BLOCK: 16, +}; diff --git a/packages/params/src/presets/minimal/index.ts b/packages/params/src/presets/minimal/index.ts index 67b8d3b073da..c4290535d5c3 100644 --- a/packages/params/src/presets/minimal/index.ts +++ b/packages/params/src/presets/minimal/index.ts @@ -3,6 +3,7 @@ import {phase0} from "./phase0.js"; import {altair} from "./altair.js"; import {bellatrix} from "./bellatrix.js"; import {capella} from "./capella.js"; +import {eip4844} from "./eip4844.js"; export const commit = "v1.2.0"; @@ -11,4 +12,5 @@ export const preset: BeaconPreset = { ...altair, ...bellatrix, ...capella, + ...eip4844, }; diff --git a/packages/state-transition/src/cache/stateCache.ts b/packages/state-transition/src/cache/stateCache.ts index c7b8b23984b1..83c834c1d6aa 100644 --- a/packages/state-transition/src/cache/stateCache.ts +++ b/packages/state-transition/src/cache/stateCache.ts @@ -1,11 +1,13 @@ import {IBeaconConfig} from "@lodestar/config"; import {EpochContext, EpochContextImmutableData, EpochContextOpts} from "./epochContext.js"; import { + BeaconStateAllForks, + BeaconStateExecutions, BeaconStatePhase0, BeaconStateAltair, BeaconStateBellatrix, BeaconStateCapella, - BeaconStateAllForks, + BeaconStateEip4844, } from "./types.js"; export type BeaconStateCache = { @@ -115,8 +117,10 @@ export type CachedBeaconStatePhase0 = CachedBeaconState; export type CachedBeaconStateAltair = CachedBeaconState; export type CachedBeaconStateBellatrix = CachedBeaconState; export type CachedBeaconStateCapella = CachedBeaconState; +export type CachedBeaconStateEip4844 = CachedBeaconState; + export type CachedBeaconStateAllForks = CachedBeaconState; -export type CachedBeaconStateExecutions = CachedBeaconStateBellatrix | CachedBeaconStateCapella; +export type CachedBeaconStateExecutions = CachedBeaconState; /** * Create CachedBeaconState computing a new EpochContext instance */ diff --git a/packages/state-transition/src/cache/types.ts b/packages/state-transition/src/cache/types.ts index 5d9e7c7c0a24..9010863cbab0 100644 --- a/packages/state-transition/src/cache/types.ts +++ b/packages/state-transition/src/cache/types.ts @@ -5,11 +5,17 @@ export type BeaconStatePhase0 = CompositeViewDU; export type BeaconStateAltair = CompositeViewDU; export type BeaconStateBellatrix = CompositeViewDU; export type BeaconStateCapella = CompositeViewDU; +export type BeaconStateEip4844 = CompositeViewDU; // Union at the TreeViewDU level // - Works well as function argument and as generic type for allForks functions // // Quasy equivalent to // CompositeViewDU -export type BeaconStateAllForks = BeaconStatePhase0 | BeaconStateAltair | BeaconStateBellatrix | BeaconStateCapella; -export type BeaconStateExecutions = BeaconStateBellatrix | BeaconStateCapella; +export type BeaconStateAllForks = + | BeaconStatePhase0 + | BeaconStateAltair + | BeaconStateBellatrix + | BeaconStateCapella + | BeaconStateEip4844; +export type BeaconStateExecutions = BeaconStateBellatrix | BeaconStateCapella | BeaconStateEip4844; diff --git a/packages/state-transition/src/index.ts b/packages/state-transition/src/index.ts index 59b57729becd..02bbeb20be2f 100644 --- a/packages/state-transition/src/index.ts +++ b/packages/state-transition/src/index.ts @@ -8,12 +8,16 @@ export { CachedBeaconStatePhase0, CachedBeaconStateAltair, CachedBeaconStateBellatrix, + CachedBeaconStateCapella, + CachedBeaconStateEip4844, CachedBeaconStateAllForks, CachedBeaconStateExecutions, // Non-cached states BeaconStatePhase0, BeaconStateAltair, BeaconStateBellatrix, + BeaconStateCapella, + BeaconStateEip4844, BeaconStateAllForks, BeaconStateExecutions, } from "./types.js"; diff --git a/packages/state-transition/src/types.ts b/packages/state-transition/src/types.ts index e2f83cbe6c31..e879a88e8b5b 100644 --- a/packages/state-transition/src/types.ts +++ b/packages/state-transition/src/types.ts @@ -2,19 +2,21 @@ export {EpochContext} from "./cache/epochContext.js"; export {EpochProcess} from "./cache/epochProcess.js"; export { + CachedBeaconStateAllForks, + CachedBeaconStateExecutions, CachedBeaconStatePhase0, CachedBeaconStateAltair, CachedBeaconStateBellatrix, - CachedBeaconStateAllForks, CachedBeaconStateCapella, - CachedBeaconStateExecutions, + CachedBeaconStateEip4844, } from "./cache/stateCache.js"; export { + BeaconStateAllForks, + BeaconStateExecutions, BeaconStatePhase0, BeaconStateAltair, BeaconStateBellatrix, BeaconStateCapella, - BeaconStateAllForks, - BeaconStateExecutions, + BeaconStateEip4844, } from "./cache/types.js"; diff --git a/packages/types/package.json b/packages/types/package.json index 3a2891e3834a..a12e28b4517e 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -26,6 +26,12 @@ "./bellatrix": { "import": "./lib/bellatrix/index.js" }, + "./capella": { + "import": "./lib/capella/index.js" + }, + "./eip4844": { + "import": "./lib/eip4844/index.js" + }, "./phase0": { "import": "./lib/phase0/index.js" } diff --git a/packages/types/src/allForks/sszTypes.ts b/packages/types/src/allForks/sszTypes.ts index 416909e20d16..352d7196c438 100644 --- a/packages/types/src/allForks/sszTypes.ts +++ b/packages/types/src/allForks/sszTypes.ts @@ -2,6 +2,7 @@ import {ssz as phase0} from "../phase0/index.js"; import {ssz as altair} from "../altair/index.js"; import {ssz as bellatrix} from "../bellatrix/index.js"; import {ssz as capella} from "../capella/index.js"; +import {ssz as eip4844} from "../eip4844/index.js"; /** * Index the ssz types that differ by fork @@ -36,6 +37,13 @@ export const allForks = { BeaconState: capella.BeaconState, Metadata: altair.Metadata, }, + eip4844: { + BeaconBlockBody: eip4844.BeaconBlockBody, + BeaconBlock: eip4844.BeaconBlock, + SignedBeaconBlock: eip4844.SignedBeaconBlock, + BeaconState: eip4844.BeaconState, + Metadata: altair.Metadata, + }, }; /** @@ -60,6 +68,14 @@ export const allForksExecution = { ExecutionPayload: capella.ExecutionPayload, ExecutionPayloadHeader: capella.ExecutionPayloadHeader, }, + eip4844: { + BeaconBlockBody: eip4844.BeaconBlockBody, + BeaconBlock: eip4844.BeaconBlock, + SignedBeaconBlock: eip4844.SignedBeaconBlock, + BeaconState: eip4844.BeaconState, + ExecutionPayload: eip4844.ExecutionPayload, + ExecutionPayloadHeader: eip4844.ExecutionPayloadHeader, + }, }; /** @@ -77,4 +93,9 @@ export const allForksBlinded = { BeaconBlock: capella.BlindedBeaconBlock, SignedBeaconBlock: capella.SignedBlindedBeaconBlock, }, + eip4844: { + BeaconBlockBody: eip4844.BlindedBeaconBlockBody, + BeaconBlock: eip4844.BlindedBeaconBlock, + SignedBeaconBlock: eip4844.SignedBlindedBeaconBlock, + }, }; diff --git a/packages/types/src/allForks/types.ts b/packages/types/src/allForks/types.ts index 16042dca7520..6294a1eaa97b 100644 --- a/packages/types/src/allForks/types.ts +++ b/packages/types/src/allForks/types.ts @@ -3,11 +3,13 @@ import {ts as phase0} from "../phase0/index.js"; 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 eip4844} from "../eip4844/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 eip4844Ssz} from "../eip4844/index.js"; // Re-export union types for types that are _known_ to differ @@ -15,28 +17,49 @@ export type BeaconBlockBody = | phase0.BeaconBlockBody | altair.BeaconBlockBody | bellatrix.BeaconBlockBody - | capella.BeaconBlockBody; -export type BeaconBlock = phase0.BeaconBlock | altair.BeaconBlock | bellatrix.BeaconBlock | capella.BeaconBlock; + | capella.BeaconBlockBody + | eip4844.BeaconBlockBody; +export type BeaconBlock = + | phase0.BeaconBlock + | altair.BeaconBlock + | bellatrix.BeaconBlock + | capella.BeaconBlock + | eip4844.BeaconBlock; export type SignedBeaconBlock = | phase0.SignedBeaconBlock | altair.SignedBeaconBlock | bellatrix.SignedBeaconBlock - | capella.SignedBeaconBlock; -export type BeaconState = phase0.BeaconState | altair.BeaconState | bellatrix.BeaconState | capella.BeaconState; + | capella.SignedBeaconBlock + | eip4844.SignedBeaconBlock; +export type BeaconState = + | phase0.BeaconState + | altair.BeaconState + | bellatrix.BeaconState + | capella.BeaconState + | eip4844.BeaconState; export type Metadata = phase0.Metadata | altair.Metadata; export type Validator = phase0.Validator | capella.Validator; // For easy reference in the assemble block for building payloads -export type ExecutionBlockBody = bellatrix.BeaconBlockBody | capella.BeaconBlockBody; +export type ExecutionBlockBody = bellatrix.BeaconBlockBody | capella.BeaconBlockBody | eip4844.BeaconBlockBody; // These two additional types will also change bellatrix forward -export type ExecutionPayload = bellatrix.ExecutionPayload | capella.ExecutionPayload; -export type ExecutionPayloadHeader = bellatrix.ExecutionPayloadHeader | capella.ExecutionPayloadHeader; +export type ExecutionPayload = bellatrix.ExecutionPayload | capella.ExecutionPayload | eip4844.ExecutionPayload; +export type ExecutionPayloadHeader = + | bellatrix.ExecutionPayloadHeader + | capella.ExecutionPayloadHeader + | eip4844.ExecutionPayloadHeader; // Blinded types that will change across forks -export type BlindedBeaconBlockBody = bellatrix.BlindedBeaconBlockBody | capella.BlindedBeaconBlockBody; -export type BlindedBeaconBlock = bellatrix.BlindedBeaconBlock | capella.BlindedBeaconBlock; -export type SignedBlindedBeaconBlock = bellatrix.SignedBlindedBeaconBlock | capella.SignedBlindedBeaconBlock; +export type BlindedBeaconBlockBody = + | bellatrix.BlindedBeaconBlockBody + | capella.BlindedBeaconBlockBody + | eip4844.BlindedBeaconBlockBody; +export type BlindedBeaconBlock = bellatrix.BlindedBeaconBlock | capella.BlindedBeaconBlock | eip4844.BlindedBeaconBlock; +export type SignedBlindedBeaconBlock = + | bellatrix.SignedBlindedBeaconBlock + | capella.SignedBlindedBeaconBlock + | eip4844.SignedBlindedBeaconBlock; // Full or blinded types export type FullOrBlindedExecutionPayload = ExecutionPayload | ExecutionPayloadHeader; @@ -98,43 +121,67 @@ export type AllForksSSZTypes = { | typeof altairSsz.BeaconBlockBody | typeof bellatrixSsz.BeaconBlockBody | typeof capellaSsz.BeaconBlockBody + | typeof eip4844Ssz.BeaconBlockBody >; BeaconBlock: AllForksTypeOf< | typeof phase0Ssz.BeaconBlock | typeof altairSsz.BeaconBlock | typeof bellatrixSsz.BeaconBlock | typeof capellaSsz.BeaconBlock + | typeof eip4844Ssz.BeaconBlock >; SignedBeaconBlock: AllForksTypeOf< | typeof phase0Ssz.SignedBeaconBlock | typeof altairSsz.SignedBeaconBlock | typeof bellatrixSsz.SignedBeaconBlock | typeof capellaSsz.SignedBeaconBlock + | typeof eip4844Ssz.SignedBeaconBlock >; BeaconState: AllForksTypeOf< | typeof phase0Ssz.BeaconState | typeof altairSsz.BeaconState | typeof bellatrixSsz.BeaconState | typeof capellaSsz.BeaconState + | typeof eip4844Ssz.BeaconState >; Metadata: AllForksTypeOf; }; export type AllForksExecutionSSZTypes = { - BeaconBlockBody: AllForksTypeOf; - BeaconBlock: AllForksTypeOf; - SignedBeaconBlock: AllForksTypeOf; - BeaconState: AllForksTypeOf; - ExecutionPayload: AllForksTypeOf; + BeaconBlockBody: AllForksTypeOf< + typeof bellatrixSsz.BeaconBlockBody | typeof capellaSsz.BeaconBlockBody | typeof eip4844Ssz.BeaconBlockBody + >; + BeaconBlock: AllForksTypeOf< + typeof bellatrixSsz.BeaconBlock | typeof capellaSsz.BeaconBlock | typeof eip4844Ssz.BeaconBlock + >; + SignedBeaconBlock: AllForksTypeOf< + typeof bellatrixSsz.SignedBeaconBlock | typeof capellaSsz.SignedBeaconBlock | typeof eip4844Ssz.SignedBeaconBlock + >; + BeaconState: AllForksTypeOf< + typeof bellatrixSsz.BeaconState | typeof capellaSsz.BeaconState | typeof eip4844Ssz.BeaconState + >; + ExecutionPayload: AllForksTypeOf< + typeof bellatrixSsz.ExecutionPayload | typeof capellaSsz.ExecutionPayload | typeof eip4844Ssz.ExecutionPayload + >; ExecutionPayloadHeader: AllForksTypeOf< - typeof bellatrixSsz.ExecutionPayloadHeader | typeof capellaSsz.ExecutionPayloadHeader + | typeof bellatrixSsz.ExecutionPayloadHeader + | typeof capellaSsz.ExecutionPayloadHeader + | typeof eip4844Ssz.ExecutionPayloadHeader >; }; export type AllForksBlindedSSZTypes = { - BeaconBlockBody: AllForksTypeOf; - BeaconBlock: AllForksTypeOf; + BeaconBlockBody: AllForksTypeOf< + | typeof bellatrixSsz.BlindedBeaconBlockBody + | typeof capellaSsz.BlindedBeaconBlock + | typeof eip4844Ssz.BlindedBeaconBlock + >; + BeaconBlock: AllForksTypeOf< + typeof bellatrixSsz.BlindedBeaconBlock | typeof capellaSsz.BlindedBeaconBlock | typeof eip4844Ssz.BlindedBeaconBlock + >; SignedBeaconBlock: AllForksTypeOf< - typeof bellatrixSsz.SignedBlindedBeaconBlock | typeof capellaSsz.SignedBlindedBeaconBlock + | typeof bellatrixSsz.SignedBlindedBeaconBlock + | typeof capellaSsz.SignedBlindedBeaconBlock + | typeof eip4844Ssz.SignedBlindedBeaconBlock >; }; diff --git a/packages/types/src/capella/types.ts b/packages/types/src/capella/types.ts index 9d9dd7d40fec..3ee8d616f71d 100644 --- a/packages/types/src/capella/types.ts +++ b/packages/types/src/capella/types.ts @@ -3,6 +3,7 @@ import * as ssz from "./sszTypes.js"; export type Withdrawal = ValueOf; export type BLSToExecutionChange = ValueOf; +export type BLSToExecutionChanges = ValueOf; export type SignedBLSToExecutionChange = ValueOf; export type ExecutionPayload = ValueOf; diff --git a/packages/types/src/eip4844/index.ts b/packages/types/src/eip4844/index.ts new file mode 100644 index 000000000000..7856cd729620 --- /dev/null +++ b/packages/types/src/eip4844/index.ts @@ -0,0 +1,3 @@ +export * from "./types.js"; +export * as ts from "./types.js"; +export * as ssz from "./sszTypes.js"; diff --git a/packages/types/src/eip4844/sszTypes.ts b/packages/types/src/eip4844/sszTypes.ts new file mode 100644 index 000000000000..486b66aaef65 --- /dev/null +++ b/packages/types/src/eip4844/sszTypes.ts @@ -0,0 +1,212 @@ +import {ContainerType, ListCompositeType, ByteVectorType} from "@chainsafe/ssz"; +import { + HISTORICAL_ROOTS_LIMIT, + FIELD_ELEMENTS_PER_BLOB, + MAX_BLOBS_PER_BLOCK, + MAX_REQUEST_BLOCKS, + BYTES_PER_FIELD_ELEMENT, +} 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 capellaSsz} from "../capella/index.js"; + +const {UintNum64, Slot, Root, BLSSignature, UintBn256, Bytes32, Bytes48, Bytes96} = primitiveSsz; + +// Polynomial commitments +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md + +// Custom types +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#custom-types +export const G1Point = Bytes48; +export const G2Point = Bytes96; +export const BLSFieldElement = Bytes32; +export const KZGCommitment = Bytes48; +export const KZGProof = Bytes48; + +// Beacon chain + +// Custom types +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#custom-types + +export const Blob = new ByteVectorType(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB); +export const Blobs = new ListCompositeType(Blob, MAX_BLOBS_PER_BLOCK); +export const VersionedHash = Bytes32; +export const BlobKzgCommitments = new ListCompositeType(KZGCommitment, MAX_BLOBS_PER_BLOCK); + +// Constants + +// Validator types +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/validator.md + +// A polynomial in evaluation form +export const Polynomial = new ListCompositeType(BLSFieldElement, FIELD_ELEMENTS_PER_BLOB); + +// class BlobsAndCommitments(Container): +// blobs: List[Blob, MAX_BLOBS_PER_BLOCK] +// kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] +export const BlobsAndCommitments = new ContainerType( + { + blobs: Blobs, + kzgCommitments: BlobKzgCommitments, + }, + {typeName: "BlobsAndCommitments", jsonCase: "eth2"} +); + +// class PolynomialAndCommitment(Container): +// polynomial: Polynomial +// kzg_commitment: KZGCommitment +export const PolynomialAndCommitment = new ContainerType( + { + polynomial: Polynomial, + kzgCommitment: KZGCommitment, + }, + {typeName: "PolynomialAndCommitment", jsonCase: "eth2"} +); + +// ReqResp types +// ============= + +export const BlobsSidecarsByRangeRequest = new ContainerType( + { + startSlot: Slot, + count: UintNum64, + }, + {typeName: "BlobsSidecarsByRangeRequest", jsonCase: "eth2"} +); + +export const BeaconBlockAndBlobsSidecarByRootRequest = new ListCompositeType(Root, MAX_REQUEST_BLOCKS); + +// Beacon Chain types +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#containers + +export const ExecutionPayload = new ContainerType( + { + ...capellaSsz.ExecutionPayload.fields, + excessDataGas: UintBn256, // New in EIP-4844 + }, + {typeName: "ExecutionPayload", jsonCase: "eth2"} +); + +export const ExecutionPayloadHeader = new ContainerType( + { + ...capellaSsz.ExecutionPayloadHeader.fields, + excessDataGas: UintBn256, // New in EIP-4844 + }, + {typeName: "ExecutionPayloadHeader", jsonCase: "eth2"} +); + +// We have to preserve Fields ordering while changing the type of ExecutionPayload +export const BeaconBlockBody = new ContainerType( + { + ...altairSsz.BeaconBlockBody.fields, + executionPayload: ExecutionPayload, // Modified in EIP-4844 + blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges, + blobKzgCommitments: BlobKzgCommitments, // New in EIP-4844 + }, + {typeName: "BeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const BeaconBlock = new ContainerType( + { + ...capellaSsz.BeaconBlock.fields, + body: BeaconBlockBody, // Modified in EIP-4844 + }, + {typeName: "BeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const SignedBeaconBlock = new ContainerType( + { + message: BeaconBlock, // Modified in EIP-4844 + signature: BLSSignature, + }, + {typeName: "SignedBeaconBlock", jsonCase: "eth2"} +); + +export const BlobsSidecar = new ContainerType( + { + beaconBlockRoot: Root, + beaconBlockSlot: Slot, + blobs: Blobs, + kzgAggregatedProof: KZGProof, + }, + {typeName: "BlobsSidecar", jsonCase: "eth2"} +); + +export const SignedBeaconBlockAndBlobsSidecar = new ContainerType( + { + beaconBlock: SignedBeaconBlock, + blobsSidecar: BlobsSidecar, + }, + {typeName: "SignedBeaconBlockAndBlobsSidecar", jsonCase: "eth2"} +); + +export const BlindedBeaconBlockBody = new ContainerType( + { + ...BeaconBlockBody.fields, + executionPayloadHeader: ExecutionPayloadHeader, // Modified in EIP-4844 + }, + {typeName: "BlindedBeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const BlindedBeaconBlock = new ContainerType( + { + ...capellaSsz.BlindedBeaconBlock.fields, + body: BlindedBeaconBlockBody, // Modified in EIP-4844 + }, + {typeName: "BlindedBeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const SignedBlindedBeaconBlock = new ContainerType( + { + message: BlindedBeaconBlock, // Modified in EIP-4844 + signature: BLSSignature, + }, + {typeName: "SignedBlindedBeaconBlock", 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( + { + genesisTime: UintNum64, + genesisValidatorsRoot: Root, + slot: primitiveSsz.Slot, + fork: phase0Ssz.Fork, + // History + latestBlockHeader: phase0Ssz.BeaconBlockHeader, + blockRoots: capellaSsz.HistoricalBlockRoots, + stateRoots: capellaSsz.HistoricalStateRoots, + historicalRoots: new ListCompositeType(Root, HISTORICAL_ROOTS_LIMIT), + // Eth1 + eth1Data: phase0Ssz.Eth1Data, + eth1DataVotes: phase0Ssz.Eth1DataVotes, + eth1DepositIndex: UintNum64, + // Registry + validators: capellaSsz.Validators, // [Modified in Capella] + 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 EIP-4844 + // Withdrawals + withdrawalQueue: capellaSsz.WithdrawalQueue, + nextWithdrawalIndex: capellaSsz.BeaconState.fields.nextWithdrawalIndex, + nextPartialWithdrawalValidatorIndex: capellaSsz.BeaconState.fields.nextPartialWithdrawalValidatorIndex, + }, + {typeName: "BeaconState", jsonCase: "eth2"} +); diff --git a/packages/types/src/eip4844/types.ts b/packages/types/src/eip4844/types.ts new file mode 100644 index 000000000000..21e7a4bcf262 --- /dev/null +++ b/packages/types/src/eip4844/types.ts @@ -0,0 +1,29 @@ +import {ValueOf} from "@chainsafe/ssz"; +import * as ssz from "./sszTypes.js"; + +export type KZGProof = ValueOf; +export type KZGCommitment = ValueOf; +export type Blob = ValueOf; +export type Blobs = ValueOf; +export type BlobsSidecar = ValueOf; +export type BlobKzgCommitments = ValueOf; +export type Polynomial = ValueOf; +export type PolynomialAndCommitment = ValueOf; +export type BLSFieldElement = ValueOf; + +export type BlobsSidecarsByRangeRequest = ValueOf; +export type BeaconBlockAndBlobsSidecarByRootRequest = ValueOf; + +export type ExecutionPayload = ValueOf; +export type ExecutionPayloadHeader = ValueOf; + +export type BeaconBlockBody = ValueOf; +export type BeaconBlock = ValueOf; +export type SignedBeaconBlock = ValueOf; +export type SignedBeaconBlockAndBlobsSidecar = ValueOf; + +export type BeaconState = ValueOf; + +export type BlindedBeaconBlockBody = ValueOf; +export type BlindedBeaconBlock = ValueOf; +export type SignedBlindedBeaconBlock = ValueOf; diff --git a/packages/types/src/sszTypes.ts b/packages/types/src/sszTypes.ts index 61a828c98c59..8b0c245e5407 100644 --- a/packages/types/src/sszTypes.ts +++ b/packages/types/src/sszTypes.ts @@ -3,6 +3,7 @@ export {ssz as phase0} from "./phase0/index.js"; export {ssz as altair} from "./altair/index.js"; export {ssz as bellatrix} from "./bellatrix/index.js"; export {ssz as capella} from "./capella/index.js"; +export {ssz as eip4844} from "./eip4844/index.js"; import {ssz as allForksSsz} from "./allForks/index.js"; export const allForks = allForksSsz.allForks; diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 9212e44fce8d..ef9663c2b756 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -3,6 +3,7 @@ export {ts as phase0} from "./phase0/index.js"; export {ts as altair} from "./altair/index.js"; export {ts as bellatrix} from "./bellatrix/index.js"; export {ts as capella} from "./capella/index.js"; +export {ts as eip4844} from "./eip4844/index.js"; export {ts as allForks} from "./allForks/index.js"; diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index aad34d76b985..9b6e9716af43 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -72,6 +72,7 @@ function getSpecCriticalParams(localConfig: IChainConfig): Record