diff --git a/packages/api/src/beacon/routes/lodestar.ts b/packages/api/src/beacon/routes/lodestar.ts index 6d43994797ba..7f19edf22fc6 100644 --- a/packages/api/src/beacon/routes/lodestar.ts +++ b/packages/api/src/beacon/routes/lodestar.ts @@ -40,7 +40,7 @@ export type RegenQueueItem = { export type BlockProcessorQueueItem = { blockSlots: Slot[]; - jobOpts: Record; + jobOpts: Record; addedTimeMs: number; }; diff --git a/packages/beacon-node/src/api/impl/lodestar/index.ts b/packages/beacon-node/src/api/impl/lodestar/index.ts index 5e2679d877ca..532ecbee8b69 100644 --- a/packages/beacon-node/src/api/impl/lodestar/index.ts +++ b/packages/beacon-node/src/api/impl/lodestar/index.ts @@ -86,15 +86,10 @@ export function getLodestarApi({ async getBlockProcessorQueueItems() { return (chain as BeaconChain)["blockProcessor"].jobQueue.getItems().map((item) => { - const [job] = item.args; - const jobs = Array.isArray(job) ? job : [job]; + const [blocks, opts] = item.args; return { - blockSlots: jobs.map((j) => j.block.message.slot), - jobOpts: { - skipImportingAttestations: jobs[0].skipImportingAttestations, - validProposerSignature: jobs[0].validProposerSignature, - validSignatures: jobs[0].validSignatures, - }, + blockSlots: blocks.map((block) => block.message.slot), + jobOpts: opts, addedTimeMs: item.addedTimeMs, }; }); diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 93eb8b3e8fb3..8d57d3e893f1 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -20,7 +20,7 @@ import {BeaconProposerCache} from "../beaconProposerCache.js"; import {IBeaconClock} from "../clock/index.js"; import {ReprocessController, REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js"; import {CheckpointBalancesCache} from "../balancesCache.js"; -import {FullyVerifiedBlock} from "./types.js"; +import {FullyVerifiedBlock, ImportBlockOpts} from "./types.js"; import {PendingEvents} from "./utils/pendingEvents.js"; import {getCheckpointFromState} from "./utils/checkpoint.js"; @@ -68,8 +68,12 @@ export type ImportBlockModules = { * - head_tracker.register_block(block_root, parent_root, slot) * - Send events after everything is done */ -export async function importBlock(chain: ImportBlockModules, fullyVerifiedBlock: FullyVerifiedBlock): Promise { - const {block, postState, parentBlockSlot, skipImportingAttestations, executionStatus} = fullyVerifiedBlock; +export async function importBlock( + chain: ImportBlockModules, + fullyVerifiedBlock: FullyVerifiedBlock, + opts: ImportBlockOpts +): Promise { + const {block, postState, parentBlockSlot, executionStatus} = fullyVerifiedBlock; const pendingEvents = new PendingEvents(chain.emitter); // - Observe attestations @@ -108,7 +112,7 @@ export async function importBlock(chain: ImportBlockModules, fullyVerifiedBlock: // Only process attestations of blocks with relevant attestations for the fork-choice: // If current epoch is N, and block is epoch X, block may include attestations for epoch X or X - 1. // The latest block that is useful is at epoch N - 1 which may include attestations for epoch N - 1 or N - 2. - if (!skipImportingAttestations && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT) { + if (!opts.skipImportingAttestations && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT) { const attestations = block.message.body.attestations; const rootCache = new RootCache(postState); const parentSlot = chain.forkChoice.getBlock(block.message.parentRoot)?.slot; diff --git a/packages/beacon-node/src/chain/blocks/index.ts b/packages/beacon-node/src/chain/blocks/index.ts index b0fda903b39c..ace502b72512 100644 --- a/packages/beacon-node/src/chain/blocks/index.ts +++ b/packages/beacon-node/src/chain/blocks/index.ts @@ -1,15 +1,15 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */ import {allForks} from "@lodestar/types"; -import {sleep, toHex} from "@lodestar/utils"; +import {toHex} from "@lodestar/utils"; import {JobItemQueue} from "../../util/queue/index.js"; -import {BlockError, BlockErrorCode, ChainSegmentError} from "../errors/index.js"; +import {BlockError, BlockErrorCode} from "../errors/index.js"; import {BlockProcessOpts} from "../options.js"; import {IBeaconChain} from "../interface.js"; import {verifyBlock, VerifyBlockModules} from "./verifyBlock.js"; import {importBlock, ImportBlockModules} from "./importBlock.js"; import {assertLinearChainSegment} from "./utils/chainSegment.js"; -import {PartiallyVerifiedBlock} from "./types.js"; -export {PartiallyVerifiedBlockFlags} from "./types.js"; +import {ImportBlockOpts} from "./types.js"; +export {ImportBlockOpts} from "./types.js"; const QUEUE_MAX_LENGHT = 256; @@ -23,28 +23,20 @@ export type ProcessBlockModules = VerifyBlockModules & * BlockProcessor processes block jobs in a queued fashion, one after the other. */ export class BlockProcessor { - readonly jobQueue: JobItemQueue<[PartiallyVerifiedBlock[] | PartiallyVerifiedBlock], void>; + readonly jobQueue: JobItemQueue<[allForks.SignedBeaconBlock[], ImportBlockOpts], void>; constructor(modules: ProcessBlockModules, opts: BlockProcessOpts, signal: AbortSignal) { - this.jobQueue = new JobItemQueue( - (job) => { - if (!Array.isArray(job)) { - return processBlock(modules, job, opts); - } else { - return processChainSegment(modules, job, opts); - } + this.jobQueue = new JobItemQueue<[allForks.SignedBeaconBlock[], ImportBlockOpts], void>( + (job, importOpts) => { + return processBlocks(modules, job, {...opts, ...importOpts}); }, {maxLength: QUEUE_MAX_LENGHT, signal}, modules.metrics ? modules.metrics.blockProcessorQueue : undefined ); } - async processBlockJob(job: PartiallyVerifiedBlock): Promise { - await this.jobQueue.push(job); - } - - async processChainSegment(job: PartiallyVerifiedBlock[]): Promise { - await this.jobQueue.push(job); + async processBlocksJob(job: allForks.SignedBeaconBlock[], opts: ImportBlockOpts = {}): Promise { + await this.jobQueue.push(job, opts); } } @@ -58,33 +50,34 @@ export class BlockProcessor { * * All other effects are provided by downstream event handlers */ -export async function processBlock( +export async function processBlocks( chain: ProcessBlockModules, - partiallyVerifiedBlock: PartiallyVerifiedBlock, - opts: BlockProcessOpts + blocks: allForks.SignedBeaconBlock[], + opts: BlockProcessOpts & ImportBlockOpts ): Promise { + if (blocks.length === 0) { + return; // TODO: or throw? + } else if (blocks.length > 1) { + assertLinearChainSegment(chain.config, blocks); + } + try { - const fullyVerifiedBlock = await verifyBlock(chain, partiallyVerifiedBlock, opts); - await importBlock(chain, fullyVerifiedBlock); - } catch (e) { - // above functions should only throw BlockError - const err = getBlockError(e, partiallyVerifiedBlock.block); + for (const block of blocks) { + const fullyVerifiedBlock = await verifyBlock(chain, block, opts); - if ( - partiallyVerifiedBlock.ignoreIfKnown && - (err.type.code === BlockErrorCode.ALREADY_KNOWN || err.type.code === BlockErrorCode.GENESIS_BLOCK) - ) { - // Flag ignoreIfKnown causes BlockErrorCodes ALREADY_KNOWN, GENESIS_BLOCK to resolve. - // Return before emitting to not cause loud logging. - return; + // No need to sleep(0) here since `importBlock` includes a disk write + // TODO: Consider batching importBlock too if it takes significant time + await importBlock(chain, fullyVerifiedBlock, opts); } + } catch (e) { + // above functions should only throw BlockError + const err = getBlockError(e, blocks[0]); + // TODO: De-duplicate with logic above + // ChainEvent.errorBlock if (!(err instanceof BlockError)) { chain.logger.error("Non BlockError received", {}, err); - return; - } - - if (!opts.disableOnBlockError) { + } else if (!opts.disableOnBlockError) { onBlockError(chain, err); } @@ -92,58 +85,6 @@ export async function processBlock( } } -/** - * Similar to processBlockJob but this process a chain segment - */ -export async function processChainSegment( - chain: ProcessBlockModules, - partiallyVerifiedBlocks: PartiallyVerifiedBlock[], - opts: BlockProcessOpts -): Promise { - const blocks = partiallyVerifiedBlocks.map((b) => b.block); - assertLinearChainSegment(chain.config, blocks); - - let importedBlocks = 0; - - for (const partiallyVerifiedBlock of partiallyVerifiedBlocks) { - try { - // TODO: Re-use preState - const fullyVerifiedBlock = await verifyBlock(chain, partiallyVerifiedBlock, opts); - await importBlock(chain, fullyVerifiedBlock); - importedBlocks++; - - // this avoids keeping our node busy processing blocks - await sleep(0); - } catch (e) { - // above functions should only throw BlockError - const err = getBlockError(e, partiallyVerifiedBlock.block); - - if ( - partiallyVerifiedBlock.ignoreIfKnown && - (err.type.code === BlockErrorCode.ALREADY_KNOWN || err.type.code === BlockErrorCode.GENESIS_BLOCK) - ) { - continue; - } - if (partiallyVerifiedBlock.ignoreIfFinalized && err.type.code == BlockErrorCode.WOULD_REVERT_FINALIZED_SLOT) { - continue; - } - - // TODO: De-duplicate with logic above - // ChainEvent.errorBlock - if (!(err instanceof BlockError)) { - chain.logger.error("Non BlockError received", {}, err); - } else if (!opts.disableOnBlockError) { - onBlockError(chain, err); - } - - // Convert to ChainSegmentError to append `importedBlocks` data - const chainSegmentError = new ChainSegmentError(partiallyVerifiedBlock.block, err.type, importedBlocks); - chainSegmentError.stack = err.stack; - throw chainSegmentError; - } - } -} - function getBlockError(e: unknown, block: allForks.SignedBeaconBlock): BlockError { if (e instanceof BlockError) { return e; diff --git a/packages/beacon-node/src/chain/blocks/types.ts b/packages/beacon-node/src/chain/blocks/types.ts index ffea13613b92..b85a7d4e46b9 100644 --- a/packages/beacon-node/src/chain/blocks/types.ts +++ b/packages/beacon-node/src/chain/blocks/types.ts @@ -2,7 +2,7 @@ import {CachedBeaconStateAllForks} from "@lodestar/state-transition"; import {ExecutionStatus} from "@lodestar/fork-choice"; import {allForks, Slot} from "@lodestar/types"; -export type FullyVerifiedBlockFlags = { +export type ImportBlockOpts = { /** * TEMP: Review if this is safe, Lighthouse always imports attestations even in finalized sync. */ @@ -19,17 +19,6 @@ export type FullyVerifiedBlockFlags = { * Used by range sync. */ ignoreIfFinalized?: boolean; -}; - -export type PartiallyVerifiedBlockFlags = FullyVerifiedBlockFlags & { - /** - * Metadata: `true` if only the block proposer signature has been verified - */ - validProposerSignature?: boolean; - /** - * Metadata: `true` if all the signatures including the proposer signature have been verified - */ - validSignatures?: boolean; /** * From RangeSync module, we won't attest to this block so it's okay to ignore a SYNCING message from execution layer */ @@ -38,6 +27,14 @@ export type PartiallyVerifiedBlockFlags = FullyVerifiedBlockFlags & { * Verify signatures on main thread or not. */ blsVerifyOnMainThread?: boolean; + /** + * Metadata: `true` if only the block proposer signature has been verified + */ + validProposerSignature?: boolean; + /** + * Metadata: `true` if all the signatures including the proposer signature have been verified + */ + validSignatures?: boolean; /** Seen timestamp seconds */ seenTimestampSec?: number; }; @@ -45,7 +42,7 @@ export type PartiallyVerifiedBlockFlags = FullyVerifiedBlockFlags & { /** * A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import */ -export type FullyVerifiedBlock = FullyVerifiedBlockFlags & { +export type FullyVerifiedBlock = { block: allForks.SignedBeaconBlock; postState: CachedBeaconStateAllForks; parentBlockSlot: Slot; @@ -57,10 +54,3 @@ export type FullyVerifiedBlock = FullyVerifiedBlockFlags & { /** Seen timestamp seconds */ seenTimestampSec: number; }; - -/** - * A wrapper around a block that's partially verified: after gossip validation `validProposerSignature = true` - */ -export type PartiallyVerifiedBlock = PartiallyVerifiedBlockFlags & { - block: allForks.SignedBeaconBlock; -}; diff --git a/packages/beacon-node/src/chain/blocks/verifyBlock.ts b/packages/beacon-node/src/chain/blocks/verifyBlock.ts index 4f426d3f2adc..df4d65498902 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlock.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlock.ts @@ -8,7 +8,7 @@ import { getBlockSignatureSets, stateTransition, } from "@lodestar/state-transition"; -import {bellatrix} from "@lodestar/types"; +import {allForks, bellatrix} from "@lodestar/types"; import {toHexString} from "@chainsafe/ssz"; import {IForkChoice, ProtoBlock, ExecutionStatus, assertValidTerminalPowBlock} from "@lodestar/fork-choice"; import {IChainForkConfig} from "@lodestar/config"; @@ -23,7 +23,7 @@ import {IBlsVerifier} from "../bls/index.js"; import {ExecutePayloadStatus} from "../../execution/engine/interface.js"; import {byteArrayEquals} from "../../util/bytes.js"; import {IEth1ForBlockProduction} from "../../eth1/index.js"; -import {FullyVerifiedBlock, PartiallyVerifiedBlock} from "./types.js"; +import {FullyVerifiedBlock, ImportBlockOpts} from "./types.js"; import {POS_PANDA_MERGE_TRANSITION_BANNER} from "./utils/pandaMergeTransitionBanner.js"; export type VerifyBlockModules = { @@ -44,26 +44,21 @@ export type VerifyBlockModules = { */ export async function verifyBlock( chain: VerifyBlockModules, - partiallyVerifiedBlock: PartiallyVerifiedBlock, - opts: BlockProcessOpts + block: allForks.SignedBeaconBlock, + opts: ImportBlockOpts & BlockProcessOpts ): Promise { - const parentBlock = verifyBlockSanityChecks(chain, partiallyVerifiedBlock); + const parentBlock = verifyBlockSanityChecks(chain, block); - const {postState, executionStatus, proposerBalanceDiff} = await verifyBlockStateTransition( - chain, - partiallyVerifiedBlock, - opts - ); + const {postState, executionStatus, proposerBalanceDiff} = await verifyBlockStateTransition(chain, block, opts); return { - block: partiallyVerifiedBlock.block, + block, postState, parentBlockSlot: parentBlock.slot, - skipImportingAttestations: partiallyVerifiedBlock.skipImportingAttestations, executionStatus, proposerBalanceDiff, // TODO: Make this param mandatory and capture in gossip - seenTimestampSec: partiallyVerifiedBlock.seenTimestampSec ?? Math.floor(Date.now() / 1000), + seenTimestampSec: opts.seenTimestampSec ?? Math.floor(Date.now() / 1000), }; } @@ -79,11 +74,7 @@ export async function verifyBlock( * - Not finalized slot * - Not already known */ -export function verifyBlockSanityChecks( - chain: VerifyBlockModules, - partiallyVerifiedBlock: PartiallyVerifiedBlock -): ProtoBlock { - const {block} = partiallyVerifiedBlock; +export function verifyBlockSanityChecks(chain: VerifyBlockModules, block: allForks.SignedBeaconBlock): ProtoBlock { const blockSlot = block.message.slot; // Not genesis block @@ -132,10 +123,10 @@ export function verifyBlockSanityChecks( */ export async function verifyBlockStateTransition( chain: VerifyBlockModules, - partiallyVerifiedBlock: PartiallyVerifiedBlock, - opts: BlockProcessOpts + block: allForks.SignedBeaconBlock, + opts: ImportBlockOpts & BlockProcessOpts ): Promise<{postState: CachedBeaconStateAllForks; executionStatus: ExecutionStatus; proposerBalanceDiff: number}> { - const {block, validProposerSignature, validSignatures} = partiallyVerifiedBlock; + const {validProposerSignature, validSignatures} = opts; // TODO: Skip in process chain segment // Retrieve preState from cache (regen) @@ -185,7 +176,7 @@ export async function verifyBlockStateTransition( if ( signatureSets.length > 0 && !(await chain.bls.verifySignatureSets(signatureSets, { - verifyOnMainThread: partiallyVerifiedBlock?.blsVerifyOnMainThread, + verifyOnMainThread: opts?.blsVerifyOnMainThread, })) ) { throw new BlockError(block, {code: BlockErrorCode.INVALID_SIGNATURE, state: postState}); diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 71dc3f62ea24..97001b94945d 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -26,7 +26,7 @@ import {IEth1ForBlockProduction} from "../eth1/index.js"; import {IExecutionEngine, IExecutionBuilder} from "../execution/index.js"; import {ensureDir, writeIfNotExist} from "../util/file.js"; import {CheckpointStateCache, StateContextCache} from "./stateCache/index.js"; -import {BlockProcessor, PartiallyVerifiedBlockFlags} from "./blocks/index.js"; +import {BlockProcessor, ImportBlockOpts} from "./blocks/index.js"; import {IBeaconClock, LocalClock} from "./clock/index.js"; import {ChainEventEmitter} from "./emitter.js"; import {IBeaconChain, ProposerPreparationData} from "./interface.js"; @@ -318,12 +318,12 @@ export class BeaconChain implements IBeaconChain { return await this.db.block.get(fromHexString(block.blockRoot)); } - async processBlock(block: allForks.SignedBeaconBlock, flags?: PartiallyVerifiedBlockFlags): Promise { - return await this.blockProcessor.processBlockJob({...flags, block}); + async processBlock(block: allForks.SignedBeaconBlock, opts?: ImportBlockOpts): Promise { + return await this.blockProcessor.processBlocksJob([block], opts); } - async processChainSegment(blocks: allForks.SignedBeaconBlock[], flags?: PartiallyVerifiedBlockFlags): Promise { - return await this.blockProcessor.processChainSegment(blocks.map((block) => ({...flags, block}))); + async processChainSegment(blocks: allForks.SignedBeaconBlock[], opts?: ImportBlockOpts): Promise { + return await this.blockProcessor.processBlocksJob(blocks, opts); } getStatus(): phase0.Status { diff --git a/packages/beacon-node/src/chain/errors/blockError.ts b/packages/beacon-node/src/chain/errors/blockError.ts index 0e8b06e6900a..863c649b51a0 100644 --- a/packages/beacon-node/src/chain/errors/blockError.ts +++ b/packages/beacon-node/src/chain/errors/blockError.ts @@ -112,22 +112,6 @@ export class BlockError extends LodestarError { } } -export class ChainSegmentError extends LodestarError { - /** - * Number of blocks successfully imported before the error - */ - importedBlocks: number; - - constructor(readonly signedBlock: allForks.SignedBeaconBlock, type: BlockErrorType, importedBlocks: number) { - super(type); - this.importedBlocks = importedBlocks; - } - - getMetadata(): Record { - return renderBlockErrorType(this.type); - } -} - export function renderBlockErrorType(type: BlockErrorType): Record { switch (type.code) { case BlockErrorCode.PRESTATE_MISSING: diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index 60da8d828fe7..30ff54cd106a 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -21,7 +21,7 @@ import { import {AttestationPool, OpPool, SyncCommitteeMessagePool, SyncContributionAndProofPool} from "./opPools/index.js"; import {LightClientServer} from "./lightClient/index.js"; import {AggregatedAttestationPool} from "./opPools/aggregatedAttestationPool.js"; -import {PartiallyVerifiedBlockFlags} from "./blocks/types.js"; +import {ImportBlockOpts} from "./blocks/types.js"; import {ReprocessController} from "./reprocess.js"; import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js"; import {BeaconProposerCache, ProposerPreparationData} from "./beaconProposerCache.js"; @@ -103,9 +103,9 @@ export interface IBeaconChain { getCanonicalBlockAtSlot(slot: Slot): Promise; /** Process a block until complete */ - processBlock(signedBlock: allForks.SignedBeaconBlock, flags?: PartiallyVerifiedBlockFlags): Promise; + processBlock(block: allForks.SignedBeaconBlock, opts?: ImportBlockOpts): Promise; /** Process a chain of blocks until complete */ - processChainSegment(signedBlocks: allForks.SignedBeaconBlock[], flags?: PartiallyVerifiedBlockFlags): Promise; + processChainSegment(blocks: allForks.SignedBeaconBlock[], opts?: ImportBlockOpts): Promise; getStatus(): phase0.Status; diff --git a/packages/beacon-node/src/sync/range/batch.ts b/packages/beacon-node/src/sync/range/batch.ts index f998c67d6c81..e615d62f9960 100644 --- a/packages/beacon-node/src/sync/range/batch.ts +++ b/packages/beacon-node/src/sync/range/batch.ts @@ -5,7 +5,7 @@ import {IChainForkConfig} from "@lodestar/config"; import {LodestarError} from "@lodestar/utils"; import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {BATCH_SLOT_OFFSET, MAX_BATCH_DOWNLOAD_ATTEMPTS, MAX_BATCH_PROCESSING_ATTEMPTS} from "../constants.js"; -import {ChainSegmentError, BlockErrorCode} from "../../chain/errors/index.js"; +import {BlockError, BlockErrorCode} from "../../chain/errors/index.js"; import {hashBlocks} from "./utils/index.js"; export type BatchOpts = { @@ -172,7 +172,7 @@ export class Batch { throw new BatchError(this.wrongStatusErrorType(BatchStatus.Processing)); } - if (err instanceof ChainSegmentError && err.type.code === BlockErrorCode.EXECUTION_ENGINE_ERROR) { + if (err instanceof BlockError && err.type.code === BlockErrorCode.EXECUTION_ENGINE_ERROR) { this.onExecutionEngineError(this.state.attempt); } else { this.onProcessingError(this.state.attempt); @@ -187,7 +187,7 @@ export class Batch { throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingValidation)); } - if (err instanceof ChainSegmentError && err.type.code === BlockErrorCode.EXECUTION_ENGINE_ERROR) { + if (err instanceof BlockError && err.type.code === BlockErrorCode.EXECUTION_ENGINE_ERROR) { this.onExecutionEngineError(this.state.attempt); } else { this.onProcessingError(this.state.attempt); diff --git a/packages/beacon-node/src/sync/range/chain.ts b/packages/beacon-node/src/sync/range/chain.ts index e33ff4ec7bb1..ee4a59350b4a 100644 --- a/packages/beacon-node/src/sync/range/chain.ts +++ b/packages/beacon-node/src/sync/range/chain.ts @@ -5,7 +5,6 @@ import {ErrorAborted, ILogger} from "@lodestar/utils"; import {IChainForkConfig} from "@lodestar/config"; import {toHexString} from "@chainsafe/ssz"; import {PeerAction} from "../../network/index.js"; -import {ChainSegmentError} from "../../chain/errors/index.js"; import {ItTrigger} from "../../util/itTrigger.js"; import {byteArrayEquals} from "../../util/bytes.js"; import {PeerMap} from "../../util/peerMap.js"; @@ -439,9 +438,10 @@ export class SyncChain { // At least one block was successfully verified and imported, so we can be sure all // previous batches are valid and we only need to download the current failed batch. - if (res.err instanceof ChainSegmentError && res.err.importedBlocks > 0) { - this.advanceChain(batch.startEpoch); - } + // TODO: Disabled for now + // if (res.err instanceof ChainSegmentError && res.err.importedBlocks > 0) { + // this.advanceChain(batch.startEpoch); + // } // The current batch could not be processed, so either this or previous batches are invalid. // All previous batches (AwaitingValidation) are potentially faulty and marked for retry. diff --git a/packages/beacon-node/src/sync/range/range.ts b/packages/beacon-node/src/sync/range/range.ts index 90fc597d94a3..272bd1918a24 100644 --- a/packages/beacon-node/src/sync/range/range.ts +++ b/packages/beacon-node/src/sync/range/range.ts @@ -9,7 +9,7 @@ import {IBeaconChain} from "../../chain/index.js"; import {INetwork} from "../../network/index.js"; import {IMetrics} from "../../metrics/index.js"; import {RangeSyncType, getRangeSyncType, rangeSyncTypes} from "../utils/remoteSyncType.js"; -import {PartiallyVerifiedBlockFlags} from "../../chain/blocks/index.js"; +import {ImportBlockOpts} from "../../chain/blocks/index.js"; import {updateChains} from "./utils/index.js"; import {ChainTarget, SyncChainFns, SyncChain, SyncChainOpts, SyncChainDebugState} from "./chain.js"; @@ -190,7 +190,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) { /** Convenience method for `SyncChain` */ private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, syncType) => { // Not trusted, verify signatures - const flags: PartiallyVerifiedBlockFlags = { + const flags: ImportBlockOpts = { // Only skip importing attestations for finalized sync. For head sync attestation are valuable. // Importing attestations also triggers a head update, see https://github.com/ChainSafe/lodestar/issues/3804 // TODO: Review if this is okay, can we prevent some attacks by importing attestations? diff --git a/packages/beacon-node/test/unit/chain/blocks/verifyBlock.test.ts b/packages/beacon-node/test/unit/chain/blocks/verifyBlock.test.ts index 3769ad8ec112..85155329a1c0 100644 --- a/packages/beacon-node/test/unit/chain/blocks/verifyBlock.test.ts +++ b/packages/beacon-node/test/unit/chain/blocks/verifyBlock.test.ts @@ -30,29 +30,29 @@ describe("chain / blocks / verifyBlock", function () { it("PARENT_UNKNOWN", function () { forkChoice.getBlockHex.returns(null); - expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, {block}), BlockErrorCode.PARENT_UNKNOWN); + expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, block), BlockErrorCode.PARENT_UNKNOWN); }); it("GENESIS_BLOCK", function () { block.message.slot = 0; - expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, {block}), BlockErrorCode.GENESIS_BLOCK); + expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, block), BlockErrorCode.GENESIS_BLOCK); }); it("ALREADY_KNOWN", function () { forkChoice.hasBlockHex.returns(true); - expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, {block}), BlockErrorCode.ALREADY_KNOWN); + expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, block), BlockErrorCode.ALREADY_KNOWN); }); it("WOULD_REVERT_FINALIZED_SLOT", function () { forkChoice.getFinalizedCheckpoint.returns({epoch: 5, root: Buffer.alloc(32), rootHex: ""}); expectThrowsLodestarError( - () => verifyBlockSanityChecks(modules, {block}), + () => verifyBlockSanityChecks(modules, block), BlockErrorCode.WOULD_REVERT_FINALIZED_SLOT ); }); it("FUTURE_SLOT", function () { block.message.slot = currentSlot + 1; - expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, {block}), BlockErrorCode.FUTURE_SLOT); + expectThrowsLodestarError(() => verifyBlockSanityChecks(modules, block), BlockErrorCode.FUTURE_SLOT); }); });