diff --git a/packages/beacon-node/src/chain/validation/blobSidecar.ts b/packages/beacon-node/src/chain/validation/blobSidecar.ts index b79db77e3931..78f40e407925 100644 --- a/packages/beacon-node/src/chain/validation/blobSidecar.ts +++ b/packages/beacon-node/src/chain/validation/blobSidecar.ts @@ -1,5 +1,10 @@ import {ChainConfig} from "@lodestar/config"; -import {KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, KZG_COMMITMENT_SUBTREE_INDEX0} from "@lodestar/params"; +import { + ForkName, + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, + KZG_COMMITMENT_SUBTREE_INDEX0, + isForkPostElectra, +} from "@lodestar/params"; import {computeStartSlotAtEpoch, getBlockHeaderProposerSignatureSet} from "@lodestar/state-transition"; import {BlobIndex, Root, Slot, deneb, ssz} from "@lodestar/types"; import {toRootHex, verifyMerkleBranch} from "@lodestar/utils"; @@ -12,6 +17,7 @@ import {IBeaconChain} from "../interface.js"; import {RegenCaller} from "../regen/index.js"; export async function validateGossipBlobSidecar( + fork: ForkName, chain: IBeaconChain, blobSidecar: deneb.BlobSidecar, subnet: number @@ -19,16 +25,17 @@ export async function validateGossipBlobSidecar( const blobSlot = blobSidecar.signedBlockHeader.message.slot; // [REJECT] The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` -- i.e. `blob_sidecar.index < MAX_BLOBS_PER_BLOCK`. - if (blobSidecar.index >= chain.config.MAX_BLOBS_PER_BLOCK) { + const maxBlobsPerBlock = chain.config.getMaxBlobsPerBlock(fork); + if (blobSidecar.index >= maxBlobsPerBlock) { throw new BlobSidecarGossipError(GossipAction.REJECT, { code: BlobSidecarErrorCode.INDEX_TOO_LARGE, blobIdx: blobSidecar.index, - maxBlobsPerBlock: chain.config.MAX_BLOBS_PER_BLOCK, + maxBlobsPerBlock, }); } // [REJECT] The sidecar is for the correct subnet -- i.e. `compute_subnet_for_blob_sidecar(sidecar.index) == subnet_id`. - if (computeSubnetForBlobSidecar(blobSidecar.index, chain.config) !== subnet) { + if (computeSubnetForBlobSidecar(fork, chain.config, blobSidecar.index) !== subnet) { throw new BlobSidecarGossipError(GossipAction.REJECT, { code: BlobSidecarErrorCode.INVALID_INDEX, blobIdx: blobSidecar.index, @@ -236,6 +243,8 @@ function validateInclusionProof(blobSidecar: deneb.BlobSidecar): boolean { ); } -function computeSubnetForBlobSidecar(blobIndex: BlobIndex, config: ChainConfig): number { - return blobIndex % config.BLOB_SIDECAR_SUBNET_COUNT; +function computeSubnetForBlobSidecar(fork: ForkName, config: ChainConfig, blobIndex: BlobIndex): number { + return ( + blobIndex % (isForkPostElectra(fork) ? config.BLOB_SIDECAR_SUBNET_COUNT_ELECTRA : config.BLOB_SIDECAR_SUBNET_COUNT) + ); } diff --git a/packages/beacon-node/src/chain/validation/block.ts b/packages/beacon-node/src/chain/validation/block.ts index b2623aa4f79d..2b18999db402 100644 --- a/packages/beacon-node/src/chain/validation/block.ts +++ b/packages/beacon-node/src/chain/validation/block.ts @@ -113,11 +113,12 @@ export async function validateGossipBlock( // [REJECT] The length of KZG commitments is less than or equal to the limitation defined in Consensus Layer -- i.e. validate that len(body.signed_beacon_block.message.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK if (isForkBlobs(fork)) { const blobKzgCommitmentsLen = (block as deneb.BeaconBlock).body.blobKzgCommitments.length; - if (blobKzgCommitmentsLen > chain.config.MAX_BLOBS_PER_BLOCK) { + const maxBlobsPerBlock = chain.config.getMaxBlobsPerBlock(fork); + if (blobKzgCommitmentsLen > maxBlobsPerBlock) { throw new BlockGossipError(GossipAction.REJECT, { code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS, blobKzgCommitmentsLen, - commitmentLimit: chain.config.MAX_BLOBS_PER_BLOCK, + commitmentLimit: maxBlobsPerBlock, }); } } diff --git a/packages/beacon-node/src/network/gossip/topic.ts b/packages/beacon-node/src/network/gossip/topic.ts index 83603226a94c..bf44dd90b8af 100644 --- a/packages/beacon-node/src/network/gossip/topic.ts +++ b/packages/beacon-node/src/network/gossip/topic.ts @@ -230,7 +230,11 @@ export function getCoreTopicsAtFork( // After Deneb also track blob_sidecar_{subnet_id} if (ForkSeq[fork] >= ForkSeq.deneb) { - for (let subnet = 0; subnet < config.BLOB_SIDECAR_SUBNET_COUNT; subnet++) { + const subnetCount = isForkPostElectra(fork) + ? config.BLOB_SIDECAR_SUBNET_COUNT_ELECTRA + : config.BLOB_SIDECAR_SUBNET_COUNT; + + for (let subnet = 0; subnet < subnetCount; subnet++) { topics.push({type: GossipType.blob_sidecar, subnet}); } } diff --git a/packages/beacon-node/src/network/network.ts b/packages/beacon-node/src/network/network.ts index 2faf2371e5c7..ae06cbab715f 100644 --- a/packages/beacon-node/src/network/network.ts +++ b/packages/beacon-node/src/network/network.ts @@ -4,7 +4,7 @@ import {PeerId} from "@libp2p/interface"; import {routes} from "@lodestar/api"; import {BeaconConfig} from "@lodestar/config"; import {LoggerNode} from "@lodestar/logger/node"; -import {ForkSeq} from "@lodestar/params"; +import {ForkSeq, isForkPostElectra} from "@lodestar/params"; import {ResponseIncoming} from "@lodestar/reqresp"; import {computeStartSlotAtEpoch, computeTimeAtSlot} from "@lodestar/state-transition"; import { @@ -501,17 +501,29 @@ export class Network implements INetwork { peerId: PeerIdStr, request: deneb.BlobSidecarsByRangeRequest ): Promise { + const fork = this.config.getForkName(request.startSlot); return collectMaxResponseTyped( - this.sendReqRespRequest(peerId, ReqRespMethod.BlobSidecarsByRange, [Version.V1], request), + this.sendReqRespRequest( + peerId, + ReqRespMethod.BlobSidecarsByRange, + [isForkPostElectra(fork) ? Version.V2 : Version.V1], + request + ), // request's count represent the slots, so the actual max count received could be slots * blobs per slot - request.count * this.config.MAX_BLOBS_PER_BLOCK, + request.count * this.config.getMaxBlobsPerBlock(fork), responseSszTypeByMethod[ReqRespMethod.BlobSidecarsByRange] ); } async sendBlobSidecarsByRoot(peerId: PeerIdStr, request: BlobSidecarsByRootRequest): Promise { + const fork = this.config.getForkName(this.clock.currentSlot); return collectMaxResponseTyped( - this.sendReqRespRequest(peerId, ReqRespMethod.BlobSidecarsByRoot, [Version.V1], request), + this.sendReqRespRequest( + peerId, + ReqRespMethod.BlobSidecarsByRoot, + [isForkPostElectra(fork) ? Version.V2 : Version.V1], + request + ), request.length, responseSszTypeByMethod[ReqRespMethod.BlobSidecarsByRoot] ); @@ -523,7 +535,8 @@ export class Network implements INetwork { versions: number[], request: Req ): AsyncIterable { - const requestType = requestSszTypeByMethod(this.config)[method]; + const fork = this.config.getForkName(this.clock.currentSlot); + const requestType = requestSszTypeByMethod(this.config, fork)[method]; const requestData = requestType ? requestType.serialize(request as never) : new Uint8Array(); // ReqResp outgoing request, emit from main thread to worker diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 906d16b33d71..4646797c2425 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -186,6 +186,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand ): Promise { const blobBlockHeader = blobSidecar.signedBlockHeader.message; const slot = blobBlockHeader.slot; + const fork = config.getForkName(slot); const blockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blobBlockHeader); const blockHex = prettyBytes(blockRoot); @@ -203,7 +204,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand ); try { - await validateGossipBlobSidecar(chain, blobSidecar, subnet); + await validateGossipBlobSidecar(fork, chain, blobSidecar, subnet); const recvToValidation = Date.now() / 1000 - seenTimestampSec; const validationTime = recvToValidation - recvToValLatency; diff --git a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts index 96b5c6c0a776..72d9892faec8 100644 --- a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts +++ b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts @@ -207,7 +207,8 @@ export class ReqRespBeaconNode extends ReqResp { versions: number[], request: Req ): AsyncIterable { - const requestType = requestSszTypeByMethod(this.config)[method]; + const fork = ForkName[ForkSeq[this.currentRegisteredFork] as ForkName]; + const requestType = requestSszTypeByMethod(this.config, fork)[method]; const requestData = requestType ? requestType.serialize(request as never) : new Uint8Array(); return this.sendRequestWithoutEncoding(peerId, method, versions, requestData); } @@ -251,12 +252,20 @@ export class ReqRespBeaconNode extends ReqResp { } if (ForkSeq[fork] >= ForkSeq.deneb) { + // TODO Electra: Consider deprecating BlobSidecarsByRootV1 and BlobSidecarsByRangeV1 at fork boundary or after Electra is stable protocolsAtFork.push( [protocols.BlobSidecarsByRoot(this.config), this.getHandler(ReqRespMethod.BlobSidecarsByRoot)], [protocols.BlobSidecarsByRange(this.config), this.getHandler(ReqRespMethod.BlobSidecarsByRange)] ); } + if (ForkSeq[fork] >= ForkSeq.electra) { + protocolsAtFork.push( + [protocols.BlobSidecarsByRootV2(this.config), this.getHandler(ReqRespMethod.BlobSidecarsByRoot)], + [protocols.BlobSidecarsByRangeV2(this.config), this.getHandler(ReqRespMethod.BlobSidecarsByRange)] + ); + } + return protocolsAtFork; } diff --git a/packages/beacon-node/src/network/reqresp/handlers/beaconBlocksByRange.ts b/packages/beacon-node/src/network/reqresp/handlers/beaconBlocksByRange.ts index e8c19fb49628..620b98be63d8 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/beaconBlocksByRange.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/beaconBlocksByRange.ts @@ -85,6 +85,7 @@ export function validateBeaconBlocksByRangeRequest( // step > 1 is deprecated, see https://github.com/ethereum/consensus-specs/pull/2856 if (count > MAX_REQUEST_BLOCKS) { + // TODO: This is probably not right as `BeaconBlocksByRangeV2` takes at most `MAX_REQUEST_BLOCKS_DENEB` count = MAX_REQUEST_BLOCKS; } diff --git a/packages/beacon-node/src/network/reqresp/handlers/index.ts b/packages/beacon-node/src/network/reqresp/handlers/index.ts index 83f6620dbbd4..49b552b58178 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/index.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/index.ts @@ -1,9 +1,10 @@ +import {ForkName} from "@lodestar/params"; import {ProtocolHandler} from "@lodestar/reqresp"; import {ssz} from "@lodestar/types"; import {IBeaconChain} from "../../../chain/index.js"; import {IBeaconDb} from "../../../db/index.js"; import {BlobSidecarsByRootRequestType} from "../../../util/types.js"; -import {GetReqRespHandlerFn, ReqRespMethod} from "../types.js"; +import {GetReqRespHandlerFn, ReqRespMethod, Version} from "../types.js"; import {onBeaconBlocksByRange} from "./beaconBlocksByRange.js"; import {onBeaconBlocksByRoot} from "./beaconBlocksByRoot.js"; import {onBlobSidecarsByRange} from "./blobSidecarsByRange.js"; @@ -38,7 +39,8 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh return onBeaconBlocksByRoot(body, chain, db); }, [ReqRespMethod.BlobSidecarsByRoot]: (req) => { - const body = BlobSidecarsByRootRequestType(chain.config).deserialize(req.data); + const fork = req.version === Version.V2 ? ForkName.electra : ForkName.deneb; + const body = BlobSidecarsByRootRequestType(fork, chain.config).deserialize(req.data); return onBlobSidecarsByRoot(body, chain, db); }, [ReqRespMethod.BlobSidecarsByRange]: (req) => { diff --git a/packages/beacon-node/src/network/reqresp/protocols.ts b/packages/beacon-node/src/network/reqresp/protocols.ts index b254db022101..c84b16695788 100644 --- a/packages/beacon-node/src/network/reqresp/protocols.ts +++ b/packages/beacon-node/src/network/reqresp/protocols.ts @@ -63,12 +63,24 @@ export const BlobSidecarsByRange = toProtocol({ contextBytesType: ContextBytesType.ForkDigest, }); +export const BlobSidecarsByRangeV2 = toProtocol({ + method: ReqRespMethod.BlobSidecarsByRange, + version: Version.V2, + contextBytesType: ContextBytesType.ForkDigest, +}); + export const BlobSidecarsByRoot = toProtocol({ method: ReqRespMethod.BlobSidecarsByRoot, version: Version.V1, contextBytesType: ContextBytesType.ForkDigest, }); +export const BlobSidecarsByRootV2 = toProtocol({ + method: ReqRespMethod.BlobSidecarsByRoot, + version: Version.V2, + contextBytesType: ContextBytesType.ForkDigest, +}); + export const LightClientBootstrap = toProtocol({ method: ReqRespMethod.LightClientBootstrap, version: Version.V1, diff --git a/packages/beacon-node/src/network/reqresp/rateLimit.ts b/packages/beacon-node/src/network/reqresp/rateLimit.ts index 771d01f6c339..ce8a996a49a8 100644 --- a/packages/beacon-node/src/network/reqresp/rateLimit.ts +++ b/packages/beacon-node/src/network/reqresp/rateLimit.ts @@ -34,11 +34,13 @@ export const rateLimitQuotas: (config: ChainConfig) => Record req.count), }, [ReqRespMethod.BlobSidecarsByRoot]: { // Rationale: quota of BeaconBlocksByRoot * MAX_BLOBS_PER_BLOCK + // TODO Electra: Stays as `MAX_REQUEST_BLOB_SIDECARS` until we have fork-aware `byPeer` and set it to `MAX_REQUEST_BLOB_SIDECARS_ELECTRA` byPeer: {quota: config.MAX_REQUEST_BLOB_SIDECARS, quotaTimeMs: 10_000}, getRequestCount: getRequestCountFn(config, ReqRespMethod.BlobSidecarsByRoot, (req) => req.length), }, diff --git a/packages/beacon-node/src/network/reqresp/types.ts b/packages/beacon-node/src/network/reqresp/types.ts index b7c18ebdfeb5..ac14b24eaf24 100644 --- a/packages/beacon-node/src/network/reqresp/types.ts +++ b/packages/beacon-node/src/network/reqresp/types.ts @@ -70,9 +70,13 @@ type ResponseBodyByMethod = { }; /** Request SSZ type for each method and ForkName */ -export const requestSszTypeByMethod: (config: ChainConfig) => { +// TODO Electra: Currently setting default fork to deneb because not every caller of requestSszTypeByMethod can provide fork info +export const requestSszTypeByMethod: ( + config: ChainConfig, + fork?: ForkName +) => { [K in ReqRespMethod]: RequestBodyByMethod[K] extends null ? null : Type; -} = (config) => ({ +} = (config, fork = ForkName.deneb) => ({ [ReqRespMethod.Status]: ssz.phase0.Status, [ReqRespMethod.Goodbye]: ssz.phase0.Goodbye, [ReqRespMethod.Ping]: ssz.phase0.Ping, @@ -80,7 +84,7 @@ export const requestSszTypeByMethod: (config: ChainConfig) => { [ReqRespMethod.BeaconBlocksByRange]: ssz.phase0.BeaconBlocksByRangeRequest, [ReqRespMethod.BeaconBlocksByRoot]: ssz.phase0.BeaconBlocksByRootRequest, [ReqRespMethod.BlobSidecarsByRange]: ssz.deneb.BlobSidecarsByRangeRequest, - [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequestType(config), + [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequestType(fork, config), [ReqRespMethod.LightClientBootstrap]: ssz.Root, [ReqRespMethod.LightClientUpdatesByRange]: ssz.altair.LightClientUpdatesByRange, [ReqRespMethod.LightClientFinalityUpdate]: null, diff --git a/packages/beacon-node/src/util/types.ts b/packages/beacon-node/src/util/types.ts index 5b9c7a784277..2a99fc34bcc2 100644 --- a/packages/beacon-node/src/util/types.ts +++ b/packages/beacon-node/src/util/types.ts @@ -1,5 +1,6 @@ import {ContainerType, ListCompositeType, ValueOf} from "@chainsafe/ssz"; import {ChainConfig} from "@lodestar/config"; +import {ForkName, isForkPostElectra} from "@lodestar/params"; import {ssz} from "@lodestar/types"; // Misc SSZ types used only in the beacon-node package, no need to upstream to types @@ -14,6 +15,9 @@ export const signedBLSToExecutionChangeVersionedType = new ContainerType( ); export type SignedBLSToExecutionChangeVersioned = ValueOf; -export const BlobSidecarsByRootRequestType = (config: ChainConfig) => - new ListCompositeType(ssz.deneb.BlobIdentifier, config.MAX_REQUEST_BLOB_SIDECARS); +export const BlobSidecarsByRootRequestType = (fork: ForkName, config: ChainConfig) => + new ListCompositeType( + ssz.deneb.BlobIdentifier, + isForkPostElectra(fork) ? config.MAX_REQUEST_BLOB_SIDECARS_ELECTRA : config.MAX_REQUEST_BLOB_SIDECARS + ); export type BlobSidecarsByRootRequest = ValueOf>; diff --git a/packages/beacon-node/test/unit/util/kzg.test.ts b/packages/beacon-node/test/unit/util/kzg.test.ts index 616505268ae1..589e8d28d834 100644 --- a/packages/beacon-node/test/unit/util/kzg.test.ts +++ b/packages/beacon-node/test/unit/util/kzg.test.ts @@ -45,6 +45,7 @@ describe("C-KZG", () => { afterEachCallbacks.push(() => chain.close()); const slot = 0; + const fork = config.getForkName(slot); const blobs = [generateRandomBlob(), generateRandomBlob()]; const kzgCommitments = blobs.map((blob) => ckzg.blobToKzgCommitment(blob)); @@ -65,7 +66,7 @@ describe("C-KZG", () => { for (const blobSidecar of blobSidecars) { try { - await validateGossipBlobSidecar(chain, blobSidecar, blobSidecar.index); + await validateGossipBlobSidecar(fork, chain, blobSidecar, blobSidecar.index); } catch (_e) { // We expect some error from here // console.log(error); diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index a4adc04a1756..7b332f94b1a6 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -109,6 +109,10 @@ export const chainConfig: ChainConfig = { // Electra // 2**8 * 10**9 (= 256,000,000,000) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000, - // 2*7 * 10**9 (= 128,000,000,000) + // 2**7 * 10**9 (= 128,000,000,000) MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000, + BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: 9, + MAX_BLOBS_PER_BLOCK_ELECTRA: 9, + // MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_ELECTRA + MAX_REQUEST_BLOB_SIDECARS_ELECTRA: 1152, }; diff --git a/packages/config/src/chainConfig/configs/minimal.ts b/packages/config/src/chainConfig/configs/minimal.ts index d16b03e82c28..0902742277e0 100644 --- a/packages/config/src/chainConfig/configs/minimal.ts +++ b/packages/config/src/chainConfig/configs/minimal.ts @@ -108,4 +108,8 @@ export const chainConfig: ChainConfig = { MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 128000000000, // 2**6 * 10**9 (= 64,000,000,000) MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000, + BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: 9, + MAX_BLOBS_PER_BLOCK_ELECTRA: 9, + // MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_ELECTRA + MAX_REQUEST_BLOB_SIDECARS_ELECTRA: 1152, }; diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 291dcc8601a7..8ca338c89a24 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -75,6 +75,9 @@ export type ChainConfig = { BLOB_SIDECAR_SUBNET_COUNT: number; MAX_BLOBS_PER_BLOCK: number; MAX_REQUEST_BLOB_SIDECARS: number; + BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: number; + MAX_BLOBS_PER_BLOCK_ELECTRA: number; + MAX_REQUEST_BLOB_SIDECARS_ELECTRA: number; }; export const chainConfigTypes: SpecTypes = { @@ -142,6 +145,9 @@ export const chainConfigTypes: SpecTypes = { BLOB_SIDECAR_SUBNET_COUNT: "number", MAX_BLOBS_PER_BLOCK: "number", MAX_REQUEST_BLOB_SIDECARS: "number", + BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: "number", + MAX_BLOBS_PER_BLOCK_ELECTRA: "number", + MAX_REQUEST_BLOB_SIDECARS_ELECTRA: "number", }; /** Allows values in a Spec file */ diff --git a/packages/config/src/forkConfig/index.ts b/packages/config/src/forkConfig/index.ts index 725e0a3af572..6540106bb886 100644 --- a/packages/config/src/forkConfig/index.ts +++ b/packages/config/src/forkConfig/index.ts @@ -10,6 +10,7 @@ import { isForkBlobs, isForkExecution, isForkLightClient, + isForkPostElectra, } from "@lodestar/params"; import {Epoch, SSZTypesFor, Slot, Version, sszTypesFor} from "@lodestar/types"; import {ChainConfig} from "../chainConfig/index.js"; @@ -129,5 +130,8 @@ export function createForkConfig(config: ChainConfig): ForkConfig { } return sszTypesFor(forkName); }, + getMaxBlobsPerBlock(fork: ForkName): number { + return isForkPostElectra(fork) ? config.MAX_BLOBS_PER_BLOCK_ELECTRA : config.MAX_BLOBS_PER_BLOCK; + }, }; } diff --git a/packages/config/src/forkConfig/types.ts b/packages/config/src/forkConfig/types.ts index ebb2899a2a21..420cd6bcd244 100644 --- a/packages/config/src/forkConfig/types.ts +++ b/packages/config/src/forkConfig/types.ts @@ -39,4 +39,6 @@ export type ForkConfig = { getExecutionForkTypes(slot: Slot): SSZTypesFor; /** Get blobs SSZ types by hard-fork*/ getBlobsForkTypes(slot: Slot): SSZTypesFor; + /** Get max blobs per block by hard-fork */ + getMaxBlobsPerBlock(fork: ForkName): number; }; diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index 1fb875801ba9..838624e29f23 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -255,11 +255,11 @@ export const BLOB_TX_TYPE = 0x03; export const VERSIONED_HASH_VERSION_KZG = 0x01; // ssz.deneb.BeaconBlockBody.getPathInfo(['blobKzgCommitments',0]).gindex -export const KZG_COMMITMENT_GINDEX0 = ACTIVE_PRESET === PresetName.minimal ? 864 : 221184; +export const KZG_COMMITMENT_GINDEX0 = ACTIVE_PRESET === PresetName.minimal ? 1728 : 221184; export const KZG_COMMITMENT_SUBTREE_INDEX0 = KZG_COMMITMENT_GINDEX0 - 2 ** KZG_COMMITMENT_INCLUSION_PROOF_DEPTH; // ssz.deneb.BlobSidecars.elementType.fixedSize -export const BLOBSIDECAR_FIXED_SIZE = ACTIVE_PRESET === PresetName.minimal ? 131672 : 131928; +export const BLOBSIDECAR_FIXED_SIZE = ACTIVE_PRESET === PresetName.minimal ? 131704 : 131928; // Electra Misc export const UNSET_DEPOSIT_REQUESTS_START_INDEX = 2n ** 64n - 1n; diff --git a/packages/params/src/presets/minimal.ts b/packages/params/src/presets/minimal.ts index 4c2a56a11d82..4595ee9ee879 100644 --- a/packages/params/src/presets/minimal.ts +++ b/packages/params/src/presets/minimal.ts @@ -115,8 +115,8 @@ export const minimalPreset: BeaconPreset = { // DENEB /////////// FIELD_ELEMENTS_PER_BLOB: 4096, - MAX_BLOB_COMMITMENTS_PER_BLOCK: 16, - KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 9, + MAX_BLOB_COMMITMENTS_PER_BLOCK: 32, + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 10, // ELECTRA MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: 4, diff --git a/packages/params/test/e2e/ensure-config-is-synced.test.ts b/packages/params/test/e2e/ensure-config-is-synced.test.ts index b1d9c05a54b1..d09ea85e016e 100644 --- a/packages/params/test/e2e/ensure-config-is-synced.test.ts +++ b/packages/params/test/e2e/ensure-config-is-synced.test.ts @@ -8,7 +8,7 @@ import {loadConfigYaml} from "../yaml.js"; // Not e2e, but slow. Run with e2e tests /** https://github.com/ethereum/consensus-specs/releases */ -const specConfigCommit = "v1.5.0-alpha.8"; +const specConfigCommit = "v1.5.0-alpha.10"; /** * Fields that we filter from local config when doing comparison. * Ideally this should be empty as it is not spec compliant diff --git a/packages/state-transition/src/block/processExecutionPayload.ts b/packages/state-transition/src/block/processExecutionPayload.ts index 0ea2fc7a16f7..ddc24e884d98 100644 --- a/packages/state-transition/src/block/processExecutionPayload.ts +++ b/packages/state-transition/src/block/processExecutionPayload.ts @@ -1,5 +1,5 @@ import {byteArrayEquals} from "@chainsafe/ssz"; -import {ForkSeq} from "@lodestar/params"; +import {ForkName, ForkSeq, isForkBlobs} from "@lodestar/params"; import {BeaconBlockBody, BlindedBeaconBlockBody, deneb, isExecutionPayload} from "@lodestar/types"; import {toHex, toRootHex} from "@lodestar/utils"; import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js"; @@ -18,6 +18,7 @@ export function processExecutionPayload( externalData: Omit ): void { const payload = getFullOrBlindedPayloadFromBody(body); + const forkName = ForkName[ForkSeq[fork] as ForkName]; // Verify consistency of the parent hash, block number, base fee per gas and gas limit // with respect to the previous execution payload header if (isMergeTransitionComplete(state)) { @@ -47,10 +48,11 @@ export function processExecutionPayload( throw Error(`Invalid timestamp ${payload.timestamp} genesisTime=${state.genesisTime} slot=${state.slot}`); } - if (fork >= ForkSeq.deneb) { + if (isForkBlobs(forkName)) { + const maxBlobsPerBlock = state.config.getMaxBlobsPerBlock(forkName); const blobKzgCommitmentsLen = (body as deneb.BeaconBlockBody).blobKzgCommitments?.length ?? 0; - if (blobKzgCommitmentsLen > state.config.MAX_BLOBS_PER_BLOCK) { - throw Error(`blobKzgCommitmentsLen exceeds limit=${state.config.MAX_BLOBS_PER_BLOCK}`); + if (blobKzgCommitmentsLen > maxBlobsPerBlock) { + throw Error(`blobKzgCommitmentsLen exceeds limit=${maxBlobsPerBlock}`); } } diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index 825f60e8c7fa..383275bfb47b 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -137,7 +137,9 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record