From 22a5851762382f6dd46cea696ca016bb3d3bcf09 Mon Sep 17 00:00:00 2001 From: harkamal Date: Thu, 4 Apr 2024 17:49:03 +0530 Subject: [PATCH 1/6] feat: add and track blob source for metrics --- .../beacon-node/src/api/impl/beacon/blocks/index.ts | 3 ++- packages/beacon-node/src/chain/blocks/importBlock.ts | 2 ++ packages/beacon-node/src/chain/blocks/types.ts | 12 +++++++++++- .../src/chain/seenCache/seenGossipBlockInput.ts | 2 ++ packages/beacon-node/src/metrics/metrics/lodestar.ts | 7 ++++++- .../network/reqresp/beaconBlocksMaybeBlobsByRange.ts | 8 +++++--- .../network/reqresp/beaconBlocksMaybeBlobsByRoot.ts | 5 +++-- .../test/spec/presets/fork_choice.test.ts | 11 +++++++++-- .../network/beaconBlocksMaybeBlobsByRange.test.ts | 3 ++- 9 files changed, 42 insertions(+), 11 deletions(-) diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index 7a52415b0996..f30da7a50d39 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -4,7 +4,7 @@ import {computeEpochAtSlot, computeTimeAtSlot, reconstructFullBlockOrContents} f import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params"; import {sleep, toHex} from "@lodestar/utils"; import {allForks, deneb, isSignedBlockContents, ProducedBlockSource} from "@lodestar/types"; -import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput} from "../../../../chain/blocks/types.js"; +import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput, BlobSource} from "../../../../chain/blocks/types.js"; import {promiseAllMaybeAsync} from "../../../../util/promises.js"; import {isOptimisticBlock} from "../../../../util/forkChoice.js"; import {computeBlobSidecars} from "../../../../util/blobs.js"; @@ -52,6 +52,7 @@ export function getBeaconBlockApi({ signedBlock, BlockSource.api, blobSidecars, + BlobSource.api, // don't bundle any bytes for block and blobs null, blobSidecars.map(() => null) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index d82448a4e932..9665987fafe5 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -103,6 +103,8 @@ export async function importBlock( }); if (blockInput.type === BlockInputType.postDeneb) { + const {blobSource} = blockInput; + this.metrics?.importBlock.blobBySource.inc({blobSource}); for (const blobSidecar of blockInput.blobs) { const {index, kzgCommitment} = blobSidecar; this.emitter.emit(routes.events.EventType.blobSidecar, { diff --git a/packages/beacon-node/src/chain/blocks/types.ts b/packages/beacon-node/src/chain/blocks/types.ts index e2c7b5a32e0a..707c11db0239 100644 --- a/packages/beacon-node/src/chain/blocks/types.ts +++ b/packages/beacon-node/src/chain/blocks/types.ts @@ -18,6 +18,14 @@ export enum BlockSource { byRoot = "req_resp_by_root", } +/** Enum to represent where blobs come from */ +export enum BlobSource { + gossip = "gossip", + api = "api", + byRange = "req_resp_by_range", + byRoot = "req_resp_by_root", +} + export enum GossipedInputType { block = "block", blob = "blob", @@ -33,7 +41,7 @@ type CachedBlobs = { export type BlockInput = {block: allForks.SignedBeaconBlock; source: BlockSource; blockBytes: Uint8Array | null} & ( | {type: BlockInputType.preDeneb} - | ({type: BlockInputType.postDeneb} & BlockInputBlobs) + | ({type: BlockInputType.postDeneb} & {blobSource: BlobSource} & BlockInputBlobs) | ({type: BlockInputType.blobsPromise} & CachedBlobs) ); export type NullBlockInput = {block: null; blockRootHex: RootHex; blockInputPromise: Promise} & CachedBlobs; @@ -69,6 +77,7 @@ export const getBlockInput = { block: allForks.SignedBeaconBlock, source: BlockSource, blobs: deneb.BlobSidecars, + blobSource: BlobSource, blockBytes: Uint8Array | null, blobsBytes: (Uint8Array | null)[] ): BlockInput { @@ -80,6 +89,7 @@ export const getBlockInput = { block, source, blobs, + blobSource, blockBytes, blobsBytes, }; diff --git a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts index c652eaad9a9b..4cfc8c396d17 100644 --- a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts +++ b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts @@ -13,6 +13,7 @@ import { BlobsCache, GossipedInputType, getBlockInputBlobs, + BlobSource, } from "../blocks/types.js"; import {Metrics} from "../../metrics/index.js"; @@ -143,6 +144,7 @@ export class SeenGossipBlockInput { signedBlock, BlockSource.gossip, blobs, + BlobSource.gossip, blockBytes ?? null, blobsBytes ); diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 20dc0333989a..e622b0905812 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -1,6 +1,6 @@ import {EpochTransitionStep, StateCloneSource, StateHashTreeRootSource} from "@lodestar/state-transition"; import {allForks} from "@lodestar/types"; -import {BlockSource} from "../../chain/blocks/types.js"; +import {BlockSource, BlobSource} from "../../chain/blocks/types.js"; import {JobQueueItemType} from "../../chain/bls/index.js"; import {BlockErrorCode} from "../../chain/errors/index.js"; import {InsertOutcome} from "../../chain/opPools/types.js"; @@ -800,6 +800,11 @@ export function createLodestarMetrics( help: "Total number of imported blocks by source", labelNames: ["source"], }), + blobBySource: register.gauge<{blobSource: BlobSource}>({ + name: "lodestar_import_blob_by_source_total", + help: "Total number of imported blobs by source", + labelNames: ["blobSource"], + }), }, engineNotifyNewPayloadResult: register.gauge<{result: ExecutionPayloadStatus}>({ name: "lodestar_execution_engine_notify_new_payload_result_total", diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts index e57c3e5b7c8e..c0cc60989622 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts @@ -3,7 +3,7 @@ import {deneb, Epoch, phase0, allForks, Slot} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; import {computeEpochAtSlot} from "@lodestar/state-transition"; -import {BlockInput, BlockSource, getBlockInput} from "../../chain/blocks/types.js"; +import {BlobSource, BlockInput, BlockSource, getBlockInput} from "../../chain/blocks/types.js"; import {PeerIdStr} from "../../util/peerId.js"; import {INetwork, WithBytes} from "../interface.js"; @@ -43,7 +43,7 @@ export async function beaconBlocksMaybeBlobsByRange( network.sendBlobSidecarsByRange(peerId, request), ]); - return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, endSlot, BlockSource.byRange); + return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, endSlot, BlockSource.byRange, BlobSource.byRange); } // Post Deneb but old blobs @@ -58,7 +58,8 @@ export function matchBlockWithBlobs( allBlocks: WithBytes[], allBlobSidecars: deneb.BlobSidecar[], endSlot: Slot, - blockSource: BlockSource + blockSource: BlockSource, + blobSource: BlobSource ): BlockInput[] { const blockInputs: BlockInput[] = []; let blobSideCarIndex = 0; @@ -101,6 +102,7 @@ export function matchBlockWithBlobs( block.data, blockSource, blobSidecars, + blobSource, null, Array.from({length: blobKzgCommitmentsLen}, () => null) ) diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts index 9aa262732042..f63e68b18896 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts @@ -9,6 +9,7 @@ import { getBlockInputBlobs, getBlockInput, NullBlockInput, + BlobSource, } from "../../chain/blocks/types.js"; import {PeerIdStr} from "../../util/peerId.js"; import {INetwork} from "../interface.js"; @@ -47,7 +48,7 @@ export async function beaconBlocksMaybeBlobsByRoot( // The last arg is to provide slot to which all blobs should be exausted in matching // and here it should be infinity since all bobs should match - return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, Infinity, BlockSource.byRoot); + return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, Infinity, BlockSource.byRoot, BlobSource.byRoot); } export async function unavailableBeaconBlobsByRoot( @@ -106,5 +107,5 @@ export async function unavailableBeaconBlobsByRoot( resolveAvailability(allBlobs); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.UNKNOWN_SYNC}); - return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, blockBytes, blobsBytes); + return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, BlobSource.byRoot, blockBytes, blobsBytes); } diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index 49d78cc42f6a..3d0c09b8f687 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -27,6 +27,7 @@ import { AttestationImportOpt, BlockSource, BlobSidecarValidation, + BlobSource, } from "../../../src/chain/blocks/types.js"; import {ZERO_HASH_HEX} from "../../../src/constants/constants.js"; import {PowMergeBlock} from "../../../src/eth1/interface.js"; @@ -209,9 +210,15 @@ const forkChoiceTest = }; }); - blockImport = getBlockInput.postDeneb(config, signedBlock, BlockSource.gossip, blobSidecars, null, [ + blockImport = getBlockInput.postDeneb( + config, + signedBlock, + BlockSource.gossip, + blobSidecars, + BlobSource.gossip, null, - ]); + [null] + ); } else { blockImport = getBlockInput.preDeneb(config, signedBlock, BlockSource.gossip, null); } diff --git a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts index 56fb64104744..c4129b29489a 100644 --- a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts +++ b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts @@ -3,7 +3,7 @@ import {ssz, deneb} from "@lodestar/types"; import {createBeaconConfig, createChainForkConfig, defaultChainConfig} from "@lodestar/config"; import {beaconBlocksMaybeBlobsByRange} from "../../../src/network/reqresp/index.js"; -import {BlockInputType, BlockSource} from "../../../src/chain/blocks/types.js"; +import {BlockInputType, BlockSource, BlobSource} from "../../../src/chain/blocks/types.js"; import {initCKZG, loadEthereumTrustedSetup} from "../../../src/util/kzg.js"; import {INetwork} from "../../../src/network/interface.js"; import {ZERO_HASH} from "../../../src/constants/constants.js"; @@ -104,6 +104,7 @@ describe("beaconBlocksMaybeBlobsByRange", () => { block, source: BlockSource.byRange, blobs, + blobSource: BlobSource.byRange, blockBytes: null, blobsBytes: blobs.map(() => null), }; From 2ef990d0d76f0d2da0a4b5b94d7736ab0ca483f1 Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 19 Apr 2024 15:30:04 +0530 Subject: [PATCH 2/6] adding blobsSource for blobsPromise --- .../src/api/impl/beacon/blocks/index.ts | 4 ++-- .../beacon-node/src/chain/blocks/importBlock.ts | 13 ++++++++----- packages/beacon-node/src/chain/blocks/types.ts | 15 ++++++++------- .../src/chain/seenCache/seenGossipBlockInput.ts | 8 ++++---- .../beacon-node/src/metrics/metrics/lodestar.ts | 6 +++--- .../reqresp/beaconBlocksMaybeBlobsByRange.ts | 8 ++++---- .../reqresp/beaconBlocksMaybeBlobsByRoot.ts | 10 +++++----- .../test/spec/presets/fork_choice.test.ts | 4 ++-- .../network/beaconBlocksMaybeBlobsByRange.test.ts | 4 ++-- 9 files changed, 38 insertions(+), 34 deletions(-) diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index f30da7a50d39..ed0224fc9cb6 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -4,7 +4,7 @@ import {computeEpochAtSlot, computeTimeAtSlot, reconstructFullBlockOrContents} f import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params"; import {sleep, toHex} from "@lodestar/utils"; import {allForks, deneb, isSignedBlockContents, ProducedBlockSource} from "@lodestar/types"; -import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput, BlobSource} from "../../../../chain/blocks/types.js"; +import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput, BlobsSource} from "../../../../chain/blocks/types.js"; import {promiseAllMaybeAsync} from "../../../../util/promises.js"; import {isOptimisticBlock} from "../../../../util/forkChoice.js"; import {computeBlobSidecars} from "../../../../util/blobs.js"; @@ -52,7 +52,7 @@ export function getBeaconBlockApi({ signedBlock, BlockSource.api, blobSidecars, - BlobSource.api, + BlobsSource.api, // don't bundle any bytes for block and blobs null, blobSidecars.map(() => null) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 9665987fafe5..9043f7f97dd6 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -95,17 +95,20 @@ export async function importBlock( this.logger.verbose("Added block to forkchoice and state cache", {slot: blockSlot, root: blockRootHex}); // We want to import block asap so call all event handler in the next event loop - setTimeout(() => { + setTimeout(async () => { this.emitter.emit(routes.events.EventType.block, { block: blockRootHex, slot: blockSlot, executionOptimistic: blockSummary != null && isOptimisticBlock(blockSummary), }); - if (blockInput.type === BlockInputType.postDeneb) { - const {blobSource} = blockInput; - this.metrics?.importBlock.blobBySource.inc({blobSource}); - for (const blobSidecar of blockInput.blobs) { + if (blockInput.type === BlockInputType.postDeneb || blockInput.type === BlockInputType.blobsPromise) { + const blobsData = + blockInput.type === BlockInputType.postDeneb ? blockInput : await blockInput.availabilityPromise; + const {blobsSource, blobs} = blobsData; + + this.metrics?.importBlock.blobBySource.inc({blobsSource}); + for (const blobSidecar of blobs) { const {index, kzgCommitment} = blobSidecar; this.emitter.emit(routes.events.EventType.blobSidecar, { blockRoot: blockRootHex, diff --git a/packages/beacon-node/src/chain/blocks/types.ts b/packages/beacon-node/src/chain/blocks/types.ts index 707c11db0239..5071f989d8b0 100644 --- a/packages/beacon-node/src/chain/blocks/types.ts +++ b/packages/beacon-node/src/chain/blocks/types.ts @@ -19,7 +19,7 @@ export enum BlockSource { } /** Enum to represent where blobs come from */ -export enum BlobSource { +export enum BlobsSource { gossip = "gossip", api = "api", byRange = "req_resp_by_range", @@ -32,7 +32,7 @@ export enum GossipedInputType { } export type BlobsCache = Map; -export type BlockInputBlobs = {blobs: deneb.BlobSidecars; blobsBytes: (Uint8Array | null)[]}; +export type BlockInputBlobs = {blobs: deneb.BlobSidecars; blobsBytes: (Uint8Array | null)[]; blobsSource: BlobsSource}; type CachedBlobs = { blobsCache: BlobsCache; availabilityPromise: Promise; @@ -41,7 +41,8 @@ type CachedBlobs = { export type BlockInput = {block: allForks.SignedBeaconBlock; source: BlockSource; blockBytes: Uint8Array | null} & ( | {type: BlockInputType.preDeneb} - | ({type: BlockInputType.postDeneb} & {blobSource: BlobSource} & BlockInputBlobs) + | ({type: BlockInputType.postDeneb} & BlockInputBlobs) + // the blobsSource here is added to BlockInputBlobs when availability is resolved | ({type: BlockInputType.blobsPromise} & CachedBlobs) ); export type NullBlockInput = {block: null; blockRootHex: RootHex; blockInputPromise: Promise} & CachedBlobs; @@ -77,7 +78,7 @@ export const getBlockInput = { block: allForks.SignedBeaconBlock, source: BlockSource, blobs: deneb.BlobSidecars, - blobSource: BlobSource, + blobsSource: BlobsSource, blockBytes: Uint8Array | null, blobsBytes: (Uint8Array | null)[] ): BlockInput { @@ -89,7 +90,7 @@ export const getBlockInput = { block, source, blobs, - blobSource, + blobsSource, blockBytes, blobsBytes, }; @@ -119,7 +120,7 @@ export const getBlockInput = { }, }; -export function getBlockInputBlobs(blobsCache: BlobsCache): BlockInputBlobs { +export function getBlockInputBlobs(blobsCache: BlobsCache, blobsSource: BlobsSource): BlockInputBlobs { const blobs = []; const blobsBytes = []; @@ -132,7 +133,7 @@ export function getBlockInputBlobs(blobsCache: BlobsCache): BlockInputBlobs { blobs.push(blobSidecar); blobsBytes.push(blobBytes); } - return {blobs, blobsBytes}; + return {blobs, blobsBytes, blobsSource}; } export enum AttestationImportOpt { diff --git a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts index 4cfc8c396d17..59caf5632ae4 100644 --- a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts +++ b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts @@ -13,7 +13,7 @@ import { BlobsCache, GossipedInputType, getBlockInputBlobs, - BlobSource, + BlobsSource, } from "../blocks/types.js"; import {Metrics} from "../../metrics/index.js"; @@ -135,16 +135,16 @@ export class SeenGossipBlockInput { } if (blobKzgCommitments.length === blobsCache.size) { - const allBlobs = getBlockInputBlobs(blobsCache); + const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.gossip); resolveAvailability(allBlobs); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.GOSSIP}); - const {blobs, blobsBytes} = allBlobs; + const {blobs, blobsBytes, blobsSource} = allBlobs; const blockInput = getBlockInput.postDeneb( config, signedBlock, BlockSource.gossip, blobs, - BlobSource.gossip, + blobsSource, blockBytes ?? null, blobsBytes ); diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index e622b0905812..636c88a7fe6f 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -1,6 +1,6 @@ import {EpochTransitionStep, StateCloneSource, StateHashTreeRootSource} from "@lodestar/state-transition"; import {allForks} from "@lodestar/types"; -import {BlockSource, BlobSource} from "../../chain/blocks/types.js"; +import {BlockSource, BlobsSource} from "../../chain/blocks/types.js"; import {JobQueueItemType} from "../../chain/bls/index.js"; import {BlockErrorCode} from "../../chain/errors/index.js"; import {InsertOutcome} from "../../chain/opPools/types.js"; @@ -800,10 +800,10 @@ export function createLodestarMetrics( help: "Total number of imported blocks by source", labelNames: ["source"], }), - blobBySource: register.gauge<{blobSource: BlobSource}>({ + blobBySource: register.gauge<{blobsSource: BlobsSource}>({ name: "lodestar_import_blob_by_source_total", help: "Total number of imported blobs by source", - labelNames: ["blobSource"], + labelNames: ["blobsSource"], }), }, engineNotifyNewPayloadResult: register.gauge<{result: ExecutionPayloadStatus}>({ diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts index c0cc60989622..2d66584dd716 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts @@ -3,7 +3,7 @@ import {deneb, Epoch, phase0, allForks, Slot} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; import {computeEpochAtSlot} from "@lodestar/state-transition"; -import {BlobSource, BlockInput, BlockSource, getBlockInput} from "../../chain/blocks/types.js"; +import {BlobsSource, BlockInput, BlockSource, getBlockInput} from "../../chain/blocks/types.js"; import {PeerIdStr} from "../../util/peerId.js"; import {INetwork, WithBytes} from "../interface.js"; @@ -43,7 +43,7 @@ export async function beaconBlocksMaybeBlobsByRange( network.sendBlobSidecarsByRange(peerId, request), ]); - return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, endSlot, BlockSource.byRange, BlobSource.byRange); + return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, endSlot, BlockSource.byRange, BlobsSource.byRange); } // Post Deneb but old blobs @@ -59,7 +59,7 @@ export function matchBlockWithBlobs( allBlobSidecars: deneb.BlobSidecar[], endSlot: Slot, blockSource: BlockSource, - blobSource: BlobSource + blobsSource: BlobsSource ): BlockInput[] { const blockInputs: BlockInput[] = []; let blobSideCarIndex = 0; @@ -102,7 +102,7 @@ export function matchBlockWithBlobs( block.data, blockSource, blobSidecars, - blobSource, + blobsSource, null, Array.from({length: blobKzgCommitmentsLen}, () => null) ) diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts index f63e68b18896..c5f2e1854de9 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts @@ -9,7 +9,7 @@ import { getBlockInputBlobs, getBlockInput, NullBlockInput, - BlobSource, + BlobsSource, } from "../../chain/blocks/types.js"; import {PeerIdStr} from "../../util/peerId.js"; import {INetwork} from "../interface.js"; @@ -48,7 +48,7 @@ export async function beaconBlocksMaybeBlobsByRoot( // The last arg is to provide slot to which all blobs should be exausted in matching // and here it should be infinity since all bobs should match - return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, Infinity, BlockSource.byRoot, BlobSource.byRoot); + return matchBlockWithBlobs(config, allBlocks, allBlobSidecars, Infinity, BlockSource.byRoot, BlobsSource.byRoot); } export async function unavailableBeaconBlobsByRoot( @@ -99,13 +99,13 @@ export async function unavailableBeaconBlobsByRoot( // check and see if all blobs are now available and in that case resolve availability // if not this will error and the leftover blobs will be tried from another peer - const allBlobs = getBlockInputBlobs(blobsCache); - const {blobs, blobsBytes} = allBlobs; + const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.byRoot); + const {blobs, blobsBytes, blobsSource} = allBlobs; if (blobs.length !== blobKzgCommitmentsLen) { throw Error(`Not all blobs fetched missingBlobs=${blobKzgCommitmentsLen - blobs.length}`); } resolveAvailability(allBlobs); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.UNKNOWN_SYNC}); - return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, BlobSource.byRoot, blockBytes, blobsBytes); + return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, blobsSource, blockBytes, blobsBytes); } diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index 3d0c09b8f687..6e8491138697 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -27,7 +27,7 @@ import { AttestationImportOpt, BlockSource, BlobSidecarValidation, - BlobSource, + BlobsSource, } from "../../../src/chain/blocks/types.js"; import {ZERO_HASH_HEX} from "../../../src/constants/constants.js"; import {PowMergeBlock} from "../../../src/eth1/interface.js"; @@ -215,7 +215,7 @@ const forkChoiceTest = signedBlock, BlockSource.gossip, blobSidecars, - BlobSource.gossip, + BlobsSource.gossip, null, [null] ); diff --git a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts index c4129b29489a..1fdedc1dda28 100644 --- a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts +++ b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts @@ -3,7 +3,7 @@ import {ssz, deneb} from "@lodestar/types"; import {createBeaconConfig, createChainForkConfig, defaultChainConfig} from "@lodestar/config"; import {beaconBlocksMaybeBlobsByRange} from "../../../src/network/reqresp/index.js"; -import {BlockInputType, BlockSource, BlobSource} from "../../../src/chain/blocks/types.js"; +import {BlockInputType, BlockSource, BlobsSource} from "../../../src/chain/blocks/types.js"; import {initCKZG, loadEthereumTrustedSetup} from "../../../src/util/kzg.js"; import {INetwork} from "../../../src/network/interface.js"; import {ZERO_HASH} from "../../../src/constants/constants.js"; @@ -104,7 +104,7 @@ describe("beaconBlocksMaybeBlobsByRange", () => { block, source: BlockSource.byRange, blobs, - blobSource: BlobSource.byRange, + blobsSource: BlobsSource.byRange, blockBytes: null, blobsBytes: blobs.map(() => null), }; From 34fb06eb09077a598606b12c801926d8f9b09397 Mon Sep 17 00:00:00 2001 From: gajinder Date: Wed, 24 Apr 2024 18:11:01 +0530 Subject: [PATCH 3/6] address feedback --- .../src/chain/blocks/importBlock.ts | 6 +-- .../beacon-node/src/chain/blocks/index.ts | 4 +- .../src/chain/blocks/verifyBlock.ts | 5 ++- .../blocks/verifyBlocksDataAvailability.ts | 41 +++++++++++++++---- .../chain/seenCache/seenGossipBlockInput.ts | 4 +- .../reqresp/beaconBlocksMaybeBlobsByRoot.ts | 4 +- 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 9043f7f97dd6..6d2eb608b5bb 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -102,10 +102,8 @@ export async function importBlock( executionOptimistic: blockSummary != null && isOptimisticBlock(blockSummary), }); - if (blockInput.type === BlockInputType.postDeneb || blockInput.type === BlockInputType.blobsPromise) { - const blobsData = - blockInput.type === BlockInputType.postDeneb ? blockInput : await blockInput.availabilityPromise; - const {blobsSource, blobs} = blobsData; + if (blockInput.type === BlockInputType.postDeneb) { + const {blobsSource, blobs} = blockInput; this.metrics?.importBlock.blobBySource.inc({blobsSource}); for (const blobSidecar of blobs) { diff --git a/packages/beacon-node/src/chain/blocks/index.ts b/packages/beacon-node/src/chain/blocks/index.ts index 8f4c7fa5f0f1..12450fe85f94 100644 --- a/packages/beacon-node/src/chain/blocks/index.ts +++ b/packages/beacon-node/src/chain/blocks/index.ts @@ -68,7 +68,7 @@ export async function processBlocks( // Fully verify a block to be imported immediately after. Does not produce any side-effects besides adding intermediate // states in the state cache through regen. - const {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus} = + const {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, availableBlockInputs} = await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, opts); // If segmentExecStatus has lvhForkchoice then, the entire segment should be invalid @@ -81,7 +81,7 @@ export async function processBlocks( } const {executionStatuses} = segmentExecStatus; - const fullyVerifiedBlocks = relevantBlocks.map( + const fullyVerifiedBlocks = availableBlockInputs.map( (block, i): FullyVerifiedBlock => ({ blockInput: block, postState: postStates[i], diff --git a/packages/beacon-node/src/chain/blocks/verifyBlock.ts b/packages/beacon-node/src/chain/blocks/verifyBlock.ts index 658ac05d3908..9bb7192b2820 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlock.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlock.ts @@ -45,6 +45,7 @@ export async function verifyBlocksInEpoch( proposerBalanceDeltas: number[]; segmentExecStatus: SegmentExecStatus; dataAvailabilityStatuses: DataAvailableStatus[]; + availableBlockInputs: BlockInput[]; }> { const blocks = blocksInput.map(({block}) => block); if (blocks.length === 0) { @@ -92,7 +93,7 @@ export async function verifyBlocksInEpoch( // batch all I/O operations to reduce overhead const [ segmentExecStatus, - {dataAvailabilityStatuses, availableTime}, + {dataAvailabilityStatuses, availableTime, availableBlockInputs}, {postStates, proposerBalanceDeltas, verifyStateTime}, {verifySignaturesTime}, ] = await Promise.all([ @@ -190,7 +191,7 @@ export async function verifyBlocksInEpoch( } } - return {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus}; + return {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, availableBlockInputs}; } finally { abortController.abort(); } diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts index de7a9575ce06..69b7dcb72dd9 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts @@ -5,7 +5,14 @@ import {Logger} from "@lodestar/utils"; import {BlockError, BlockErrorCode} from "../errors/index.js"; import {validateBlobSidecars} from "../validation/blobSidecar.js"; import {Metrics} from "../../metrics/metrics.js"; -import {BlockInput, BlockInputType, ImportBlockOpts, BlobSidecarValidation} from "./types.js"; +import { + BlockInput, + BlockInputType, + ImportBlockOpts, + BlobSidecarValidation, + getBlockInput, + BlobsSource, +} from "./types.js"; // we can now wait for full 12 seconds because unavailable block sync will try pulling // the blobs from the network anyway after 500ms of seeing the block @@ -27,7 +34,11 @@ export async function verifyBlocksDataAvailability( chain: {config: ChainForkConfig; genesisTime: UintNum64; logger: Logger; metrics: Metrics | null}, blocks: BlockInput[], opts: ImportBlockOpts -): Promise<{dataAvailabilityStatuses: DataAvailableStatus[]; availableTime: number}> { +): Promise<{ + dataAvailabilityStatuses: DataAvailableStatus[]; + availableTime: number; + availableBlockInputs: BlockInput[]; +}> { if (blocks.length === 0) { throw Error("Empty partiallyVerifiedBlocks"); } @@ -35,11 +46,14 @@ export async function verifyBlocksDataAvailability( const dataAvailabilityStatuses: DataAvailableStatus[] = []; const seenTime = opts.seenTimestampSec !== undefined ? opts.seenTimestampSec * 1000 : Date.now(); + const availableBlockInputs: BlockInput[] = []; + for (const blockInput of blocks) { // Validate status of only not yet finalized blocks, we don't need yet to propogate the status // as it is not used upstream anywhere - const dataAvailabilityStatus = await maybeValidateBlobs(chain, blockInput, opts); + const {dataAvailabilityStatus, availableBlockInput} = await maybeValidateBlobs(chain, blockInput, opts); dataAvailabilityStatuses.push(dataAvailabilityStatus); + availableBlockInputs.push(availableBlockInput); } const availableTime = blocks[blocks.length - 1].type === BlockInputType.blobsPromise ? Date.now() : seenTime; @@ -55,21 +69,21 @@ export async function verifyBlocksDataAvailability( }); } - return {dataAvailabilityStatuses, availableTime}; + return {dataAvailabilityStatuses, availableTime, availableBlockInputs}; } async function maybeValidateBlobs( chain: {config: ChainForkConfig; genesisTime: UintNum64; logger: Logger}, blockInput: BlockInput, opts: ImportBlockOpts -): Promise { +): Promise<{dataAvailabilityStatus: DataAvailableStatus; availableBlockInput: BlockInput}> { switch (blockInput.type) { case BlockInputType.preDeneb: - return DataAvailableStatus.preDeneb; + return {dataAvailabilityStatus: DataAvailableStatus.preDeneb, availableBlockInput: blockInput}; case BlockInputType.postDeneb: if (opts.validBlobSidecars === BlobSidecarValidation.Full) { - return DataAvailableStatus.available; + return {dataAvailabilityStatus: DataAvailableStatus.available, availableBlockInput: blockInput}; } // eslint-disable-next-line no-fallthrough @@ -82,7 +96,7 @@ async function maybeValidateBlobs( blockInput.type === BlockInputType.postDeneb ? blockInput : await raceWithCutoff(chain, blockInput, blockInput.availabilityPromise); - const {blobs} = blobsData; + const {blobs, blobsBytes} = blobsData; const {blobKzgCommitments} = (block as deneb.SignedBeaconBlock).message.body; const beaconBlockRoot = chain.config.getForkTypes(blockSlot).BeaconBlock.hashTreeRoot(block.message); @@ -92,7 +106,16 @@ async function maybeValidateBlobs( const skipProofsCheck = opts.validBlobSidecars === BlobSidecarValidation.Individual; validateBlobSidecars(blockSlot, beaconBlockRoot, blobKzgCommitments, blobs, {skipProofsCheck}); - return DataAvailableStatus.available; + const availableBlockInput = getBlockInput.postDeneb( + chain.config, + blockInput.block, + blockInput.source, + blobs, + BlobsSource.gossip, + blockInput.blockBytes, + blobsBytes + ); + return {dataAvailabilityStatus: DataAvailableStatus.available, availableBlockInput: availableBlockInput}; } } } diff --git a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts index 59caf5632ae4..e1239ac9e882 100644 --- a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts +++ b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts @@ -138,13 +138,13 @@ export class SeenGossipBlockInput { const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.gossip); resolveAvailability(allBlobs); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.GOSSIP}); - const {blobs, blobsBytes, blobsSource} = allBlobs; + const {blobs, blobsBytes} = allBlobs; const blockInput = getBlockInput.postDeneb( config, signedBlock, BlockSource.gossip, blobs, - blobsSource, + BlobsSource.gossip, blockBytes ?? null, blobsBytes ); diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts index c5f2e1854de9..3aea3aa928fd 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts @@ -100,12 +100,12 @@ export async function unavailableBeaconBlobsByRoot( // check and see if all blobs are now available and in that case resolve availability // if not this will error and the leftover blobs will be tried from another peer const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.byRoot); - const {blobs, blobsBytes, blobsSource} = allBlobs; + const {blobs, blobsBytes} = allBlobs; if (blobs.length !== blobKzgCommitmentsLen) { throw Error(`Not all blobs fetched missingBlobs=${blobKzgCommitmentsLen - blobs.length}`); } resolveAvailability(allBlobs); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.UNKNOWN_SYNC}); - return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, blobsSource, blockBytes, blobsBytes); + return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, BlobsSource.byRoot, blockBytes, blobsBytes); } From 55a123265f8da33f7628a4c3b79c765bd7220e25 Mon Sep 17 00:00:00 2001 From: gajinder Date: Wed, 24 Apr 2024 22:43:46 +0530 Subject: [PATCH 4/6] apply feedback --- packages/beacon-node/src/chain/blocks/types.ts | 4 ++-- .../beacon-node/src/chain/seenCache/seenGossipBlockInput.ts | 4 ++-- .../src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/types.ts b/packages/beacon-node/src/chain/blocks/types.ts index 5071f989d8b0..170ebd8a5a0c 100644 --- a/packages/beacon-node/src/chain/blocks/types.ts +++ b/packages/beacon-node/src/chain/blocks/types.ts @@ -120,7 +120,7 @@ export const getBlockInput = { }, }; -export function getBlockInputBlobs(blobsCache: BlobsCache, blobsSource: BlobsSource): BlockInputBlobs { +export function getBlockInputBlobs(blobsCache: BlobsCache): Omit { const blobs = []; const blobsBytes = []; @@ -133,7 +133,7 @@ export function getBlockInputBlobs(blobsCache: BlobsCache, blobsSource: BlobsSou blobs.push(blobSidecar); blobsBytes.push(blobBytes); } - return {blobs, blobsBytes, blobsSource}; + return {blobs, blobsBytes}; } export enum AttestationImportOpt { diff --git a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts index e1239ac9e882..77976b70e6e8 100644 --- a/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts +++ b/packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts @@ -135,8 +135,8 @@ export class SeenGossipBlockInput { } if (blobKzgCommitments.length === blobsCache.size) { - const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.gossip); - resolveAvailability(allBlobs); + const allBlobs = getBlockInputBlobs(blobsCache); + resolveAvailability({...allBlobs, blobsSource: BlobsSource.gossip}); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.GOSSIP}); const {blobs, blobsBytes} = allBlobs; const blockInput = getBlockInput.postDeneb( diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts index 3aea3aa928fd..95d88f39586f 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts @@ -99,13 +99,13 @@ export async function unavailableBeaconBlobsByRoot( // check and see if all blobs are now available and in that case resolve availability // if not this will error and the leftover blobs will be tried from another peer - const allBlobs = getBlockInputBlobs(blobsCache, BlobsSource.byRoot); + const allBlobs = getBlockInputBlobs(blobsCache); const {blobs, blobsBytes} = allBlobs; if (blobs.length !== blobKzgCommitmentsLen) { throw Error(`Not all blobs fetched missingBlobs=${blobKzgCommitmentsLen - blobs.length}`); } - resolveAvailability(allBlobs); + resolveAvailability({...allBlobs, blobsSource: BlobsSource.byRoot}); metrics?.syncUnknownBlock.resolveAvailabilitySource.inc({source: BlockInputAvailabilitySource.UNKNOWN_SYNC}); return getBlockInput.postDeneb(config, block, BlockSource.byRoot, blobs, BlobsSource.byRoot, blockBytes, blobsBytes); } From 5d1f15c31f96f4798bf6a88f60fd357a49294cf8 Mon Sep 17 00:00:00 2001 From: gajinder Date: Thu, 25 Apr 2024 14:29:19 +0530 Subject: [PATCH 5/6] updates --- .../beacon-node/src/chain/blocks/importBlock.ts | 2 +- .../chain/blocks/verifyBlocksDataAvailability.ts | 13 +++---------- .../beacon-node/src/metrics/metrics/lodestar.ts | 4 ++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 6d2eb608b5bb..950ef3264a9e 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -105,7 +105,7 @@ export async function importBlock( if (blockInput.type === BlockInputType.postDeneb) { const {blobsSource, blobs} = blockInput; - this.metrics?.importBlock.blobBySource.inc({blobsSource}); + this.metrics?.importBlock.blobsBySource.inc({blobsSource}); for (const blobSidecar of blobs) { const {index, kzgCommitment} = blobSidecar; this.emitter.emit(routes.events.EventType.blobSidecar, { diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts index 69b7dcb72dd9..f995dde967bd 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts @@ -5,14 +5,7 @@ import {Logger} from "@lodestar/utils"; import {BlockError, BlockErrorCode} from "../errors/index.js"; import {validateBlobSidecars} from "../validation/blobSidecar.js"; import {Metrics} from "../../metrics/metrics.js"; -import { - BlockInput, - BlockInputType, - ImportBlockOpts, - BlobSidecarValidation, - getBlockInput, - BlobsSource, -} from "./types.js"; +import {BlockInput, BlockInputType, ImportBlockOpts, BlobSidecarValidation, getBlockInput} from "./types.js"; // we can now wait for full 12 seconds because unavailable block sync will try pulling // the blobs from the network anyway after 500ms of seeing the block @@ -96,7 +89,7 @@ async function maybeValidateBlobs( blockInput.type === BlockInputType.postDeneb ? blockInput : await raceWithCutoff(chain, blockInput, blockInput.availabilityPromise); - const {blobs, blobsBytes} = blobsData; + const {blobs, blobsBytes, blobsSource} = blobsData; const {blobKzgCommitments} = (block as deneb.SignedBeaconBlock).message.body; const beaconBlockRoot = chain.config.getForkTypes(blockSlot).BeaconBlock.hashTreeRoot(block.message); @@ -111,7 +104,7 @@ async function maybeValidateBlobs( blockInput.block, blockInput.source, blobs, - BlobsSource.gossip, + blobsSource, blockInput.blockBytes, blobsBytes ); diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 636c88a7fe6f..12b7f3538d6e 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -800,8 +800,8 @@ export function createLodestarMetrics( help: "Total number of imported blocks by source", labelNames: ["source"], }), - blobBySource: register.gauge<{blobsSource: BlobsSource}>({ - name: "lodestar_import_blob_by_source_total", + blobsBySource: register.gauge<{blobsSource: BlobsSource}>({ + name: "lodestar_import_blobs_by_source_total", help: "Total number of imported blobs by source", labelNames: ["blobsSource"], }), From 141c553ff1d2fa96f546af047600998e1f45fbb7 Mon Sep 17 00:00:00 2001 From: gajinder Date: Thu, 25 Apr 2024 14:40:39 +0530 Subject: [PATCH 6/6] only allow non blobspromise blocks to be imported --- packages/beacon-node/src/chain/blocks/importBlock.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 950ef3264a9e..5b3d69a0e47e 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -69,6 +69,11 @@ export async function importBlock( const blockDelaySec = (fullyVerifiedBlock.seenTimestampSec - postState.genesisTime) % this.config.SECONDS_PER_SLOT; const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); + // this is just a type assertion since blockinput with blobsPromise type will not end up here + if (blockInput.type === BlockInputType.blobsPromise) { + throw Error("Unavailable block can not be imported in forkchoice"); + } + // 1. Persist block to hot DB (pre-emptively) // If eagerPersistBlock = true we do that in verifyBlocksInEpoch to batch all I/O operations to save block time to head if (!opts.eagerPersistBlock) { @@ -102,6 +107,9 @@ export async function importBlock( executionOptimistic: blockSummary != null && isOptimisticBlock(blockSummary), }); + // blobsPromise will not end up here, but preDeneb could. In future we might also allow syncing + // out of data range blocks and import then in forkchoice although one would not be able to + // attest and propose with such head similar to optimistic sync if (blockInput.type === BlockInputType.postDeneb) { const {blobsSource, blobs} = blockInput;