diff --git a/packages/client/src/service/skeleton.ts b/packages/client/src/service/skeleton.ts index f6bfdb0bd3..9d547f8166 100644 --- a/packages/client/src/service/skeleton.ts +++ b/packages/client/src/service/skeleton.ts @@ -233,15 +233,6 @@ export class Skeleton extends MetaDBManager { return this.started > 0 } - async isLastAnnouncement(): Promise { - const subchain0 = this.status.progress.subchains[0] - if (subchain0 !== undefined) { - return this.getBlock(subchain0.head + BIGINT_1) !== undefined - } else { - return true - } - } - /** * Try fast forwarding the chain head to the number */ @@ -316,7 +307,7 @@ export class Skeleton extends MetaDBManager { } else if (lastchain.head >= number) { // Check if its duplicate announcement, if not trim the head and let the match run // post this if block - const mayBeDupBlock = await this.getBlock(number) + const mayBeDupBlock = await this.getBlock(number, true) if (mayBeDupBlock !== undefined && equalsBytes(mayBeDupBlock.header.hash(), head.hash())) { this.config.logger.debug( `Skeleton duplicate ${force ? 'setHead' : 'announcement'} tail=${lastchain.tail} head=${ @@ -359,7 +350,7 @@ export class Skeleton extends MetaDBManager { return true } } - const parent = await this.getBlock(number - BIGINT_1) + const parent = await this.getBlock(number - BIGINT_1, true) if (parent === undefined || !equalsBytes(parent.hash(), head.header.parentHash)) { if (force) { this.config.logger.warn( @@ -818,7 +809,7 @@ export class Skeleton extends MetaDBManager { const syncedBlock = await this.getBlock( syncedHeight, // need to debug why this flag causes to return undefined when chain gets synced - //, true + true, ) if ( syncedBlock !== undefined && @@ -859,7 +850,7 @@ export class Skeleton extends MetaDBManager { async headHash(): Promise { const subchain = this.bounds() if (subchain !== undefined) { - const headBlock = await this.getBlock(subchain.head) + const headBlock = await this.getBlock(subchain.head, true) if (headBlock) { return headBlock.hash() } @@ -998,7 +989,7 @@ export class Skeleton extends MetaDBManager { } else { // Critical error, we expect new incoming blocks to extend the canonical // subchain which is the [0]'th - const tailBlock = await this.getBlock(this.status.progress.subchains[0].tail) + const tailBlock = await this.getBlock(this.status.progress.subchains[0].tail, true) this.config.logger.warn( `Blocks don't extend canonical subchain tail=${ this.status.progress.subchains[0].tail @@ -1112,7 +1103,7 @@ export class Skeleton extends MetaDBManager { for (let i = 0; i < maxItems; i++) { const tailBlock = await this.getBlockByHash(next) - if (tailBlock === undefined) { + if (tailBlock === undefined || tailBlock.header.number <= BIGINT_1) { break } else { blocks.push(tailBlock) @@ -1202,7 +1193,7 @@ export class Skeleton extends MetaDBManager { while (!this.status.canonicalHeadReset && canonicalHead < subchain.head) { // Get next block const number = canonicalHead + BIGINT_1 - const block = await this.getBlock(number) + const block = await this.getBlock(number, true) if (block === undefined) { // This can happen @@ -1381,10 +1372,12 @@ export class Skeleton extends MetaDBManager { * Gets a block from the skeleton or canonical db by number. */ async getBlock(number: bigint, onlyCanonical = false): Promise { - return this.chain.blockchain.dbManager.getBlock(number, { - fcUed: onlyCanonical, - linked: this.status.linked, - }) + return this.chain.blockchain.dbManager + .getBlock(number, { + fcUed: onlyCanonical, + linked: this.status.linked, + }) + .catch((_e) => undefined) } /** @@ -1395,7 +1388,7 @@ export class Skeleton extends MetaDBManager { onlyCanonical: boolean = false, ): Promise { return this.chain.blockchain.dbManager.getBlock(hash, { - fcUed: !onlyCanonical, + fcUed: onlyCanonical, linked: this.status.linked, }) } diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index a26853cfa8..64c48c5d08 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -25,14 +25,23 @@ type Subchain = { } const common = new Common({ chain: Mainnet }) -const block49 = createBlock({ header: { number: 49 } }, { common }) -const block49B = createBlock({ header: { number: 49, extraData: utf8ToBytes('B') } }, { common }) -const block50 = createBlock({ header: { number: 50, parentHash: block49.hash() } }, { common }) +const block49 = createBlock({ header: { number: 49 } }, { common, setHardfork: true }) +const block49B = createBlock( + { header: { number: 49, extraData: utf8ToBytes('B') } }, + { common, setHardfork: true }, +) +const block50 = createBlock( + { header: { number: 50, parentHash: block49.hash() } }, + { common, setHardfork: true }, +) const block50B = createBlock( { header: { number: 50, parentHash: block49.hash(), gasLimit: 999 } }, - { common }, + { common, setHardfork: true }, +) +const block51 = createBlock( + { header: { number: 51, parentHash: block50.hash() } }, + { common, setHardfork: true }, ) -const block51 = createBlock({ header: { number: 51, parentHash: block50.hash() } }, { common }) describe('[Skeleton]/ startup scenarios ', () => { it('starts the chain when starting the skeleton', async () => { @@ -594,20 +603,20 @@ describe('[Skeleton] / setHead', async () => { 'canonical height should change when setHead is set with force=true', ) - // unlink the skeleton for the below check to check all blocks cleared + // unlink the skeleton for the below check and still find the blocks in blokchain skeleton['status'].linked = false for (const block of [block1, block2, block3, block4, block5]) { assert.equal( - (await skeleton.getBlock(block.header.number, true))?.hash(), - undefined, - `skeleton block number=${block.header.number} should be cleaned up after filling canonical chain`, + (await skeleton.getBlock(block.header.number, true))?.hash() !== undefined, + true, + `skeleton block number=${block.header.number} should be available even afer filling canonical chain`, ) assert.equal( - (await skeleton.getBlockByHash(block.hash(), true))?.hash(), - undefined, + (await skeleton.getBlockByHash(block.hash(), true))?.hash() !== undefined, + true, `skeleton block hash=${short( block.hash(), - )} should be cleaned up after filling canonical chain`, + )} should be available even after filling canonical chain`, ) } }) @@ -677,16 +686,16 @@ describe('[Skeleton] / setHead', async () => { skeleton['status'].linked = false for (const block of [block3, block4, block5]) { assert.equal( - (await skeleton.getBlock(block.header.number, true))?.hash(), - undefined, - `skeleton block number=${block.header.number} should be cleaned up after filling canonical chain`, + (await skeleton.getBlock(block.header.number, true))?.hash() !== undefined, + true, + `skeleton block number=${block.header.number} should still be available after filling canonical chain`, ) assert.equal( - (await skeleton.getBlockByHash(block.hash(), true))?.hash(), - undefined, + (await skeleton.getBlockByHash(block.hash(), true))?.hash() !== undefined, + true, `skeleton block hash=${short( block.hash(), - )} should be cleaned up after filling canonical chain`, + )} should still be available after filling canonical chain`, ) } // restore linkedStatus @@ -707,9 +716,9 @@ describe('[Skeleton] / setHead', async () => { await skeleton.setHead(block41, false) await skeleton.setHead(block51, false) - // should link the chains including the 41, 51 block backfilled from the unfinalized await skeleton.forkchoiceUpdate(block61) + assert.equal( skeleton['status'].progress.subchains[0]?.head, BigInt(6), @@ -856,7 +865,9 @@ describe('[Skeleton] / setHead', async () => { await skeleton.open() await skeleton.initSync(block4InvalidPoS) + // the following putBlocks will fail ad block3 is pow block await skeleton.putBlocks([block3PoW, block2]) + assert.equal(chain.blocks.height, BigInt(0), 'canonical height should be at genesis') await skeleton.putBlocks([block1]) await wait(200)