diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index f463bbc7d0b6..c2d69458a338 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -140,7 +140,7 @@ export class ForkChoice implements IForkChoice { if (block.slot > ancestorSlot) { // Search for a slot that is lte the target slot. // We check for lower slots to account for skip slots. - for (const node of this.protoArray.iterateNodes(blockRootHex)) { + for (const node of this.protoArray.iterateAncestorNodes(blockRootHex)) { if (node.slot <= ancestorSlot) { return fromHexString(node.blockRoot); } @@ -559,26 +559,40 @@ export class ForkChoice implements IForkChoice { this.protoArray.pruneThreshold = threshold; } + *iterateAncestorBlocks(blockRoot: phase0.Root): IterableIterator { + for (const block of this.protoArray.iterateAncestorNodes(toHexString(blockRoot))) { + yield toBlockSummary(block); + } + } + /** * Iterates backwards through block summaries, starting from a block root. * Return only the non-finalized blocks. */ - iterateBlockSummaries(blockRoot: phase0.Root): IBlockSummary[] { - const blocks = this.protoArray.iterateNodes(toHexString(blockRoot)).map(toBlockSummary); + getAllAncestorBlocks(blockRoot: phase0.Root): IBlockSummary[] { + const blocks = this.protoArray.getAllAncestorNodes(toHexString(blockRoot)).map(toBlockSummary); // the last node is the previous finalized one, it's there to check onBlock finalized checkpoint only. return blocks.slice(0, blocks.length - 1); } /** - * The same to iterateBlockSummaries but this gets non-ancestor nodes instead of ancestor nodes. + * The same to getAllAncestorBlocks but this gets non-ancestor nodes instead of ancestor nodes. */ - iterateNonAncestors(blockRoot: phase0.Root): IBlockSummary[] { - return this.protoArray.iterateNonAncestorNodes(toHexString(blockRoot)).map(toBlockSummary); + getAllNonAncestorBlocks(blockRoot: phase0.Root): IBlockSummary[] { + return this.protoArray.getAllNonAncestorNodes(toHexString(blockRoot)).map(toBlockSummary); } getCanonicalBlockSummaryAtSlot(slot: Slot): IBlockSummary | null { - const head = this.getHeadRoot(); - return this.iterateBlockSummaries(head).find((summary) => summary.slot === slot) || null; + if (slot >= this.head.slot) { + return this.head; + } + + for (const block of this.protoArray.iterateAncestorNodes(toHexString(this.head.blockRoot))) { + if (block.slot === slot) { + return toBlockSummary(block); + } + } + return null; } forwardIterateBlockSummaries(): IBlockSummary[] { @@ -591,7 +605,33 @@ export class ForkChoice implements IForkChoice { } getBlockSummariesAtSlot(slot: Slot): IBlockSummary[] { - return this.protoArray.nodes.filter((node) => node.slot === slot).map(toBlockSummary); + const nodes = this.protoArray.nodes; + const blocksAtSlot: IBlockSummary[] = []; + for (let i = 0, len = nodes.length; i < len; i++) { + const node = nodes[i]; + if (node.slot === slot) { + blocksAtSlot.push(toBlockSummary(node)); + } + } + return blocksAtSlot; + } + + getCommonAncestorDistance(prevBlock: IBlockSummary, newBlock: IBlockSummary): number | null { + const prevNode = this.protoArray.getNode(toHexString(prevBlock.blockRoot)); + const newNode = this.protoArray.getNode(toHexString(newBlock.blockRoot)); + if (!prevNode) throw Error(`No node if forkChoice for blockRoot ${prevBlock.blockRoot}`); + if (!newNode) throw Error(`No node if forkChoice for blockRoot ${newBlock.blockRoot}`); + + const commonAncestor = this.protoArray.getCommonAncestor(prevNode, newNode); + // No common ancestor, should never happen. Return null to not throw + if (!commonAncestor) return null; + + // If common node is one of both nodes, then they are direct descendants, return null + if (commonAncestor.blockRoot === prevNode.blockRoot || commonAncestor.blockRoot === newNode.blockRoot) { + return null; + } + + return newNode.slot - commonAncestor.slot; } private updateJustified(justifiedCheckpoint: phase0.Checkpoint, justifiedBalances: number[]): void { diff --git a/packages/fork-choice/src/forkChoice/interface.ts b/packages/fork-choice/src/forkChoice/interface.ts index 25644270c050..cfa13399e88d 100644 --- a/packages/fork-choice/src/forkChoice/interface.ts +++ b/packages/fork-choice/src/forkChoice/interface.ts @@ -107,13 +107,17 @@ export interface IForkChoice { prune(finalizedRoot: phase0.Root): IBlockSummary[]; setPruneThreshold(threshold: number): void; /** - * Iterates backwards through block summaries, starting from a block root + * Iterates backwards through ancestor block summaries, starting from a block root */ - iterateBlockSummaries(blockRoot: phase0.Root): IBlockSummary[]; + iterateAncestorBlocks(blockRoot: phase0.Root): IterableIterator; /** - * The same to iterateBlockSummaries but this gets non-ancestor nodes instead of ancestor nodes. + * Returns all ancestor blocks backwards, starting from a block root */ - iterateNonAncestors(blockRoot: phase0.Root): IBlockSummary[]; + getAllAncestorBlocks(blockRoot: phase0.Root): IBlockSummary[]; + /** + * The same to getAllAncestorBlocks but this gets non-ancestor nodes instead of ancestor nodes. + */ + getAllNonAncestorBlocks(blockRoot: phase0.Root): IBlockSummary[]; getCanonicalBlockSummaryAtSlot(slot: Slot): IBlockSummary | null; /** * Iterates forwards through block summaries, exact order is not guaranteed @@ -121,6 +125,8 @@ export interface IForkChoice { forwardIterateBlockSummaries(): IBlockSummary[]; getBlockSummariesByParentRoot(parentRoot: phase0.Root): IBlockSummary[]; getBlockSummariesAtSlot(slot: Slot): IBlockSummary[]; + /** Returns the distance of common ancestor of nodes to newNode. Returns null if newNode is descendant of prevNode */ + getCommonAncestorDistance(prevBlock: IBlockSummary, newBlock: IBlockSummary): number | null; } export interface ILatestMessage { diff --git a/packages/fork-choice/src/protoArray/protoArray.ts b/packages/fork-choice/src/protoArray/protoArray.ts index 8a0341b52101..7ed47c075965 100644 --- a/packages/fork-choice/src/protoArray/protoArray.ts +++ b/packages/fork-choice/src/protoArray/protoArray.ts @@ -291,7 +291,7 @@ export class ProtoArray { } // Remove the this.indices key/values for all the to-be-deleted nodes - for (const nodeIndex of Array.from({length: finalizedIndex}, (_, i) => i)) { + for (let nodeIndex = 0; nodeIndex < finalizedIndex; nodeIndex++) { const node = this.nodes[nodeIndex]; if (node === undefined) { throw new ProtoArrayError({ @@ -319,7 +319,8 @@ export class ProtoArray { } // Iterate through all the existing nodes and adjust their indices to match the new layout of this.nodes - for (const node of this.nodes) { + for (let i = 0, len = this.nodes.length; i < len; i++) { + const node = this.nodes[i]; const parentIndex = node.parent; if (parentIndex !== undefined) { // If node.parent is less than finalizedIndex, set it to undefined @@ -491,7 +492,37 @@ export class ProtoArray { /** * Iterate from a block root backwards over nodes */ - iterateNodes(blockRoot: RootHex): IProtoNode[] { + *iterateAncestorNodes(blockRoot: RootHex): IterableIterator { + const startIndex = this.indices.get(blockRoot); + if (startIndex === undefined) { + return; + } + + const node = this.nodes[startIndex]; + if (node === undefined) { + throw new ProtoArrayError({ + code: ProtoArrayErrorCode.INVALID_NODE_INDEX, + index: startIndex, + }); + } + + yield* this.iterateAncestorNodesFromNode(node); + } + + /** + * Iterate from a block root backwards over nodes + */ + *iterateAncestorNodesFromNode(node: IProtoNode): IterableIterator { + while (node.parent !== undefined) { + node = this.getNodeFromIndex(node.parent); + yield node; + } + } + + /** + * get all nodes from a block root backwards + */ + getAllAncestorNodes(blockRoot: RootHex): IProtoNode[] { const startIndex = this.indices.get(blockRoot); if (startIndex === undefined) { return []; @@ -506,14 +537,7 @@ export class ProtoArray { } const result: IProtoNode[] = [node]; while (node.parent !== undefined) { - const nodeParent = node.parent; - node = this.nodes[nodeParent]; - if (node === undefined) { - throw new ProtoArrayError({ - code: ProtoArrayErrorCode.INVALID_NODE_INDEX, - index: nodeParent, - }); - } + node = this.getNodeFromIndex(node.parent); result.push(node); } return result; @@ -524,7 +548,7 @@ export class ProtoArray { * iterateNodes is to find ancestor nodes of a blockRoot. * this is to find non-ancestor nodes of a blockRoot. */ - iterateNonAncestorNodes(blockRoot: RootHex): IProtoNode[] { + getAllNonAncestorNodes(blockRoot: RootHex): IProtoNode[] { const startIndex = this.indices.get(blockRoot); if (startIndex === undefined) { return []; @@ -541,13 +565,7 @@ export class ProtoArray { let nodeIndex = startIndex; while (node.parent !== undefined) { const parentIndex = node.parent; - node = this.nodes[parentIndex]; - if (node === undefined) { - throw new ProtoArrayError({ - code: ProtoArrayErrorCode.INVALID_NODE_INDEX, - index: parentIndex, - }); - } + node = this.getNodeFromIndex(parentIndex); // nodes between nodeIndex and parentIndex means non-ancestor nodes result.push(...this.getNodesBetween(nodeIndex, parentIndex)); nodeIndex = parentIndex; @@ -556,44 +574,10 @@ export class ProtoArray { return result; } - nodesAtSlot(slot: Slot): IProtoNode[] { - const result: IProtoNode[] = []; - for (const node of this.nodes) { - if (node.slot === slot) { - result.push(node); - } - } - return result; - } - hasBlock(blockRoot: RootHex): boolean { return this.indices.has(blockRoot); } - getNodeByIndex(blockIndex: number): IProtoNode | undefined { - const node = this.nodes[blockIndex]; - if (!node) { - return undefined; - } - - return node; - } - - getNodesBetween(upperIndex: number, lowerIndex: number): IProtoNode[] { - const result = []; - for (let index = upperIndex - 1; index > lowerIndex; index--) { - const node = this.nodes[index]; - if (node === undefined) { - throw new ProtoArrayError({ - code: ProtoArrayErrorCode.INVALID_NODE_INDEX, - index, - }); - } - result.push(node); - } - return result; - } - getNode(blockRoot: RootHex): IProtoNode | undefined { const blockIndex = this.indices.get(blockRoot); if (blockIndex === undefined) { @@ -622,7 +606,12 @@ export class ProtoArray { if (!ancestorNode) { return false; } - for (const node of this.iterateNodes(descendantRoot)) { + + if (ancestorRoot === descendantRoot) { + return true; + } + + for (const node of this.iterateAncestorNodes(descendantRoot)) { if (node.slot < ancestorNode.slot) { return false; } @@ -633,7 +622,68 @@ export class ProtoArray { return false; } + getCommonAncestor(prevNode: IProtoNode, newNode: IProtoNode): IProtoNode | null { + const isPrevNodeLower = prevNode.slot <= newNode.slot; + let lowNode = isPrevNodeLower ? prevNode : newNode; + let highNode = isPrevNodeLower ? newNode : prevNode; + + highNode = this.getAncestorAtSlot(highNode, lowNode.slot); + + // Now lowNode and highNode are at the same slot + while (lowNode.parent !== undefined && highNode.parent !== undefined) { + if (lowNode.blockRoot === highNode.blockRoot) { + return lowNode; + } + + lowNode = this.getNodeFromIndex(lowNode.parent); + highNode = this.getNodeFromIndex(highNode.parent); + } + + return null; + } + length(): number { return this.indices.size; } + + private getAncestorAtSlot(node: IProtoNode, slot: number): IProtoNode { + for (const parentNode of this.iterateAncestorNodesFromNode(node)) { + if (parentNode.slot === slot) { + return parentNode; + } + } + throw Error("slot less than finalized block"); + } + + private getNodeFromIndex(index: number): IProtoNode { + const node = this.nodes[index]; + if (node === undefined) { + throw new ProtoArrayError({code: ProtoArrayErrorCode.INVALID_NODE_INDEX, index}); + } + return node; + } + + private getNodeByIndex(blockIndex: number): IProtoNode | undefined { + const node = this.nodes[blockIndex]; + if (!node) { + return undefined; + } + + return node; + } + + private getNodesBetween(upperIndex: number, lowerIndex: number): IProtoNode[] { + const result = []; + for (let index = upperIndex - 1; index > lowerIndex; index--) { + const node = this.nodes[index]; + if (node === undefined) { + throw new ProtoArrayError({ + code: ProtoArrayErrorCode.INVALID_NODE_INDEX, + index, + }); + } + result.push(node); + } + return result; + } } diff --git a/packages/fork-choice/test/unit/forkChoice/forkChoice.test.ts b/packages/fork-choice/test/unit/forkChoice/forkChoice.test.ts index 4256360f6b5b..37de7de02190 100644 --- a/packages/fork-choice/test/unit/forkChoice/forkChoice.test.ts +++ b/packages/fork-choice/test/unit/forkChoice/forkChoice.test.ts @@ -44,7 +44,7 @@ describe("Forkchoice", function () { bestJustifiedCheckpoint: {root: fromHexString(finalizedRoot), epoch: genesisEpoch}, }; - it("iterateBlockSummaries", function () { + it("getAllAncestorBlocks", function () { protoArr.onBlock(block); const forkchoice = new ForkChoice({ config, @@ -53,8 +53,8 @@ describe("Forkchoice", function () { queuedAttestations: new Set(), justifiedBalances: [], }); - const summaries = forkchoice.iterateBlockSummaries(fromHexString(finalizedDesc)); - // there are 2 blocks in protoArray but iterateBlockSummaries should only return non-finalized blocks + const summaries = forkchoice.getAllAncestorBlocks(fromHexString(finalizedDesc)); + // there are 2 blocks in protoArray but getAllAncestorBlocks should only return non-finalized blocks expect(summaries.length).to.be.equals(1, "should not return the finalized block"); expect(summaries[0]).to.be.deep.equals(toBlockSummary(block), "the block summary is not correct"); }); diff --git a/packages/lodestar/src/chain/archiver/archiveBlocks.ts b/packages/lodestar/src/chain/archiver/archiveBlocks.ts index d3a6b8054117..1681a1dd3c48 100644 --- a/packages/lodestar/src/chain/archiver/archiveBlocks.ts +++ b/packages/lodestar/src/chain/archiver/archiveBlocks.ts @@ -20,10 +20,10 @@ export async function archiveBlocks( finalized: phase0.Checkpoint ): Promise { // Use fork choice to determine the blocks to archive and delete - const allCanonicalSummaries = forkChoice.iterateBlockSummaries(finalized.root); - // 1st block in iterateBlockSummaries() is the finalized block itself + const allCanonicalSummaries = forkChoice.getAllAncestorBlocks(finalized.root); + // 1st block in getAllAncestorBlocks() is the finalized block itself // we move it to blockArchive but forkchoice still have it to check next onBlock calls - // the next iterateBlockSummaries call does not return this block + // the next getAllAncestorBlocks call does not return this block let i = 0; // this number of blocks per chunk is tested in e2e test blockArchive.test.ts const BATCH_SIZE = 1000; @@ -65,7 +65,7 @@ export async function archiveBlocks( // deleteNonCanonicalBlocks // loop through forkchoice single time - const nonCanonicalSummaries = forkChoice.iterateNonAncestors(finalized.root); + const nonCanonicalSummaries = forkChoice.getAllNonAncestorBlocks(finalized.root); if (nonCanonicalSummaries && nonCanonicalSummaries.length > 0) { await db.block.batchDelete(nonCanonicalSummaries.map((summary) => summary.blockRoot)); logger.verbose("deleteNonCanonicalBlocks", { diff --git a/packages/lodestar/src/chain/blocks/stateTransition.ts b/packages/lodestar/src/chain/blocks/stateTransition.ts index d423a9f26246..16ecb1e30f59 100644 --- a/packages/lodestar/src/chain/blocks/stateTransition.ts +++ b/packages/lodestar/src/chain/blocks/stateTransition.ts @@ -120,7 +120,7 @@ export async function runStateTransition( emitBlockEvent(emitter, job, postState); forkChoice.updateHead(); - emitForkChoiceHeadEvents(emitter, forkChoice, forkChoice.getHead(), oldHead, metrics); + emitForkChoiceHeadEvents(emitter, forkChoice, oldHead, metrics); } return postState; @@ -155,25 +155,20 @@ function emitCheckpointEvent( function emitForkChoiceHeadEvents( emitter: ChainEventEmitter, forkChoice: IForkChoice, - head: IBlockSummary, oldHead: IBlockSummary, metrics: IMetrics | null ): void { - const headRoot = head.blockRoot; - const oldHeadRoot = oldHead.blockRoot; - if (!byteArrayEquals(headRoot, oldHeadRoot)) { + const newHead = forkChoice.getHead(); + if (!byteArrayEquals(newHead.blockRoot, oldHead.blockRoot)) { // new head - if (!forkChoice.isDescendant(oldHeadRoot, headRoot)) { - // chain reorg - const oldHeadHistory = forkChoice.iterateBlockSummaries(oldHeadRoot); - const headHistory = forkChoice.iterateBlockSummaries(headRoot); - const firstAncestor = headHistory.find((summary) => oldHeadHistory.includes(summary)); - const distance = oldHead.slot - (firstAncestor?.slot ?? oldHead.slot); - emitter.emit(ChainEvent.forkChoiceReorg, head, oldHead, distance); + emitter.emit(ChainEvent.forkChoiceHead, newHead); + metrics?.forkChoiceChangedHead.inc(); + + const distance = forkChoice.getCommonAncestorDistance(oldHead, newHead); + if (distance !== null) { + emitter.emit(ChainEvent.forkChoiceReorg, newHead, oldHead, distance); metrics?.forkChoiceReorg.inc(); } - emitter.emit(ChainEvent.forkChoiceHead, head); - metrics?.forkChoiceChangedHead.inc(); } } diff --git a/packages/lodestar/src/chain/chain.ts b/packages/lodestar/src/chain/chain.ts index f770fe2eda13..4d5c0f86a8b4 100644 --- a/packages/lodestar/src/chain/chain.ts +++ b/packages/lodestar/src/chain/chain.ts @@ -220,7 +220,7 @@ export class BeaconChain implements IBeaconChain { const blockRootsPerSlot = new Map>(); // these blocks are on the same chain to head - for (const summary of this.forkChoice.iterateBlockSummaries(this.forkChoice.getHeadRoot())) { + for (const summary of this.forkChoice.getAllAncestorBlocks(this.forkChoice.getHeadRoot())) { if (slotsSet.has(summary.slot)) { blockRootsPerSlot.set(summary.slot, this.db.block.get(summary.blockRoot)); } diff --git a/packages/lodestar/src/chain/regen/regen.ts b/packages/lodestar/src/chain/regen/regen.ts index 2757ca9ef98a..12cc64130d9e 100644 --- a/packages/lodestar/src/chain/regen/regen.ts +++ b/packages/lodestar/src/chain/regen/regen.ts @@ -162,7 +162,7 @@ export class StateRegenerator implements IStateRegenerator { // gets reversed when replayed const blocksToReplay = [block]; let state: CachedBeaconState | null = null; - for (const b of this.forkChoice.iterateBlockSummaries(block.parentRoot)) { + for (const b of this.forkChoice.iterateAncestorBlocks(block.parentRoot)) { state = this.stateCache.get(b.stateRoot); if (state) { break; diff --git a/packages/lodestar/test/unit/chain/archive/blockArchiver.test.ts b/packages/lodestar/test/unit/chain/archive/blockArchiver.test.ts index b2d6ca9f2d1e..ffec15ec077a 100644 --- a/packages/lodestar/test/unit/chain/archive/blockArchiver.test.ts +++ b/packages/lodestar/test/unit/chain/archive/blockArchiver.test.ts @@ -29,8 +29,8 @@ describe("block archiver task", function () { ); const canonicalBlocks = [blocks[4], blocks[3], blocks[1], blocks[0]]; const nonCanonicalBlocks = [blocks[2]]; - forkChoiceStub.iterateBlockSummaries.returns(canonicalBlocks); - forkChoiceStub.iterateNonAncestors.returns(nonCanonicalBlocks); + forkChoiceStub.getAllAncestorBlocks.returns(canonicalBlocks); + forkChoiceStub.getAllNonAncestorBlocks.returns(nonCanonicalBlocks); await archiveBlocks(dbStub, forkChoiceStub, logger, {epoch: 5, root: ZERO_HASH}); expect( dbStub.blockArchive.batchPutBinary.calledWith( diff --git a/packages/lodestar/test/unit/chain/forkChoice/forkChoice.test.ts b/packages/lodestar/test/unit/chain/forkChoice/forkChoice.test.ts index 166fa8549a30..5cf43cdadfc5 100644 --- a/packages/lodestar/test/unit/chain/forkChoice/forkChoice.test.ts +++ b/packages/lodestar/test/unit/chain/forkChoice/forkChoice.test.ts @@ -142,13 +142,13 @@ describe("LodestarForkChoice", function () { forkChoice.onBlock(block20.message, state20, justifiedBalances); forkChoice.onBlock(block24.message, state24, justifiedBalances); forkChoice.onBlock(block28.message, state28, justifiedBalances); - expect(forkChoice.iterateBlockSummaries(ssz.phase0.BeaconBlock.hashTreeRoot(block16.message)).length).to.be.equal( + expect(forkChoice.getAllAncestorBlocks(ssz.phase0.BeaconBlock.hashTreeRoot(block16.message)).length).to.be.equal( 3, - "iterateBlockSummaries should return 3 blocks" + "getAllAncestorBlocks should return 3 blocks" ); - expect(forkChoice.iterateBlockSummaries(ssz.phase0.BeaconBlock.hashTreeRoot(block24.message)).length).to.be.equal( + expect(forkChoice.getAllAncestorBlocks(ssz.phase0.BeaconBlock.hashTreeRoot(block24.message)).length).to.be.equal( 5, - "iterateBlockSummaries should return 5 blocks" + "getAllAncestorBlocks should return 5 blocks" ); expect(forkChoice.getBlock(ssz.phase0.BeaconBlock.hashTreeRoot(block08.message))).to.be.not.null; expect(forkChoice.getBlock(ssz.phase0.BeaconBlock.hashTreeRoot(block12.message))).to.be.not.null; @@ -156,13 +156,13 @@ describe("LodestarForkChoice", function () { expect(forkChoice.hasBlock(ssz.phase0.BeaconBlock.hashTreeRoot(block12.message))).to.be.true; forkChoice.onBlock(block32.message, state32, justifiedBalances); forkChoice.prune(ssz.phase0.BeaconBlock.hashTreeRoot(block16.message)); - expect(forkChoice.iterateBlockSummaries(ssz.phase0.BeaconBlock.hashTreeRoot(block16.message)).length).to.be.equal( + expect(forkChoice.getAllAncestorBlocks(ssz.phase0.BeaconBlock.hashTreeRoot(block16.message)).length).to.be.equal( 0, - "iterateBlockSummaries should not return finalized block" + "getAllAncestorBlocks should not return finalized block" ); - expect(forkChoice.iterateBlockSummaries(ssz.phase0.BeaconBlock.hashTreeRoot(block24.message)).length).to.be.equal( + expect(forkChoice.getAllAncestorBlocks(ssz.phase0.BeaconBlock.hashTreeRoot(block24.message)).length).to.be.equal( 2, - "iterateBlockSummaries should return 2 blocks" + "getAllAncestorBlocks should return 2 blocks" ); expect(forkChoice.getBlock(ssz.phase0.BeaconBlock.hashTreeRoot(block08.message))).to.be.null; expect(forkChoice.getBlock(ssz.phase0.BeaconBlock.hashTreeRoot(block12.message))).to.be.null; @@ -175,7 +175,7 @@ describe("LodestarForkChoice", function () { * \ * parent (34) - child (35) */ - it("iterateNonAncestors - should get non ancestor nodes", () => { + it("getAllNonAncestorBlocks - should get non ancestor nodes", () => { const {blockHeader} = computeAnchorCheckpoint(config, anchorState); const finalizedRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader); const targetBlock = generateSignedBlock({message: {slot: 32}}); @@ -200,8 +200,8 @@ describe("LodestarForkChoice", function () { (summary) => summary.slot < childBlock.message.slot && !forkChoice.isDescendant(summary.blockRoot, childBlockRoot) ); - // compare to iterateNonAncestors api - expect(forkChoice.iterateNonAncestors(childBlockRoot)).to.be.deep.equal(nonCanonicalSummaries); + // compare to getAllNonAncestorBlocks api + expect(forkChoice.getAllNonAncestorBlocks(childBlockRoot)).to.be.deep.equal(nonCanonicalSummaries); }); }); }); diff --git a/packages/lodestar/test/utils/mocks/chain/chain.ts b/packages/lodestar/test/utils/mocks/chain/chain.ts index f0f31ef10a1d..3120af205972 100644 --- a/packages/lodestar/test/utils/mocks/chain/chain.ts +++ b/packages/lodestar/test/utils/mocks/chain/chain.ts @@ -219,11 +219,13 @@ function mockForkChoice(): IForkChoice { isDescendant: () => true, prune: () => [blockSummary], setPruneThreshold: () => {}, - iterateBlockSummaries: () => [blockSummary], - iterateNonAncestors: () => [blockSummary], + iterateAncestorBlocks: function* () {}, + getAllAncestorBlocks: () => [blockSummary], + getAllNonAncestorBlocks: () => [blockSummary], getCanonicalBlockSummaryAtSlot: () => blockSummary, forwardIterateBlockSummaries: () => [blockSummary], getBlockSummariesByParentRoot: () => [blockSummary], getBlockSummariesAtSlot: () => [blockSummary], + getCommonAncestorDistance: () => null, }; }