diff --git a/packages/beacon-node/src/chain/archiver/index.ts b/packages/beacon-node/src/chain/archiver/index.ts index 5e9dc314a351..9c0290bfd8c4 100644 --- a/packages/beacon-node/src/chain/archiver/index.ts +++ b/packages/beacon-node/src/chain/archiver/index.ts @@ -106,12 +106,13 @@ export class Archiver { this.chain.regen.pruneOnFinalized(finalizedEpoch); // tasks rely on extended fork choice - this.chain.forkChoice.prune(finalized.rootHex); + const prunedBlocks = this.chain.forkChoice.prune(finalized.rootHex); await this.updateBackfillRange(finalized); this.logger.verbose("Finish processing finalized checkpoint", { epoch: finalizedEpoch, rootHex: finalized.rootHex, + prunedBlocks: prunedBlocks.length, }); } catch (e) { this.logger.error("Error processing finalized checkpoint", {epoch: finalized.epoch}, e as Error); diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index cc3f63614ca4..62a8af368b62 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -555,7 +555,7 @@ export class ForkChoice implements IForkChoice { } return { epoch: vote.nextEpoch, - root: this.protoArray.nodes[vote.nextIndex].blockRoot, + root: vote.nextIndex === null ? HEX_ZERO_HASH : this.protoArray.nodes[vote.nextIndex].blockRoot, }; } @@ -673,9 +673,21 @@ export class ForkChoice implements IForkChoice { const prunedCount = prunedNodes.length; for (const vote of this.votes) { if (vote.currentIndex !== null) { - vote.currentIndex -= prunedCount; + if (vote.currentIndex >= prunedCount) { + vote.currentIndex -= prunedCount; + } else { + // the vote was for a pruned proto node + vote.currentIndex = null; + } + } + if (vote.nextIndex !== null) { + if (vote.nextIndex >= prunedCount) { + vote.nextIndex -= prunedCount; + } else { + // the vote was for a pruned proto node + vote.nextIndex = null; + } } - vote.nextIndex -= prunedCount; } return prunedNodes; } diff --git a/packages/fork-choice/src/protoArray/computeDeltas.ts b/packages/fork-choice/src/protoArray/computeDeltas.ts index ac51b19c22d6..09f2cf05f1f5 100644 --- a/packages/fork-choice/src/protoArray/computeDeltas.ts +++ b/packages/fork-choice/src/protoArray/computeDeltas.ts @@ -22,7 +22,7 @@ export function computeDeltas( const deltas = Array(numProtoNodes).fill(0); // avoid creating new variables in the loop to potentially reduce GC pressure let oldBalance, newBalance: number; - let currentIndex, nextIndex: number; + let currentIndex, nextIndex: number | null; for (let vIndex = 0; vIndex < votes.length; vIndex++) { const vote = votes[vIndex]; @@ -75,13 +75,15 @@ export function computeDeltas( // We ignore the vote if it is not known in `indices . // We assume that it is outside of our tree (ie: pre-finalization) and therefore not interesting - if (nextIndex >= numProtoNodes) { - throw new ProtoArrayError({ - code: ProtoArrayErrorCode.INVALID_NODE_DELTA, - index: nextIndex, - }); + if (nextIndex !== null) { + if (nextIndex >= numProtoNodes) { + throw new ProtoArrayError({ + code: ProtoArrayErrorCode.INVALID_NODE_DELTA, + index: nextIndex, + }); + } + deltas[nextIndex] += newBalance; } - deltas[nextIndex] += newBalance; } vote.currentIndex = nextIndex; } diff --git a/packages/fork-choice/src/protoArray/interface.ts b/packages/fork-choice/src/protoArray/interface.ts index 085714617ebc..1910ad2b4206 100644 --- a/packages/fork-choice/src/protoArray/interface.ts +++ b/packages/fork-choice/src/protoArray/interface.ts @@ -10,7 +10,8 @@ export const HEX_ZERO_HASH = "0x000000000000000000000000000000000000000000000000 */ export type VoteTracker = { currentIndex: number | null; - nextIndex: number; + // if a vode is out of date (the voted index was in the past while proto array is pruned), it will be set to null + nextIndex: number | null; nextEpoch: Epoch; };