diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index 8710123e89a..95b16d096a6 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -362,13 +362,13 @@ export class Blockchain implements BlockchainInterface { if (isGenesis) { if (equalsBytes(this.genesisBlock.hash(), block.hash())) { // Try to re-put the existing genesis block, accept this + optimistic = false return } throw new Error( 'Cannot put a different genesis block than current blockchain genesis: create a new Blockchain', ) // genesis block is not optimistic - optimistic = false } if (block.common.chainId() !== this.common.chainId()) { @@ -410,10 +410,10 @@ export class Blockchain implements BlockchainInterface { if (optimistic) { dbOps = dbOps.concat(DBSetBlockOrHeader(item)) dbOps.push(DBSetHashToNumber(blockHash, blockNumber)) + dbOps.push(DBOp.set(DBTarget.OptimisticNumberToHash, blockHash, { blockNumber })) await this.dbManager.batch(dbOps) } else { const currentTd = { header: BIGINT_0, block: BIGINT_0 } - // set total difficulty in the current context scope if (this._headHeaderHash) { currentTd.header = await this.getTotalDifficulty(this._headHeaderHash) diff --git a/packages/blockchain/src/db/constants.ts b/packages/blockchain/src/db/constants.ts index 5b365937acc..dbe6990fccf 100644 --- a/packages/blockchain/src/db/constants.ts +++ b/packages/blockchain/src/db/constants.ts @@ -28,6 +28,7 @@ const TD_SUFFIX = utf8ToBytes('t') * headerPrefix + number + numSuffix -> hash */ const NUM_SUFFIX = utf8ToBytes('n') +const OPTIMISTIC_NUM_SUFFIX = utf8ToBytes('o') /** * blockHashPrefix + hash -> number @@ -55,6 +56,9 @@ const bodyKey = (n: bigint, hash: Uint8Array) => concatBytes(BODY_PREFIX, bytesB const numberToHashKey = (n: bigint) => concatBytes(HEADER_PREFIX, bytesBE8(n), NUM_SUFFIX) +const optimisticNumberToHashKey = (n: bigint) => + concatBytes(HEADER_PREFIX, bytesBE8(n), OPTIMISTIC_NUM_SUFFIX) + const hashToNumberKey = (hash: Uint8Array) => concatBytes(BLOCK_HASH_PREFIX, hash) /** @@ -69,5 +73,6 @@ export { headerKey, HEADS_KEY, numberToHashKey, + optimisticNumberToHashKey, tdKey, } diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index c0864c1cd07..f0b1c202af0 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -84,7 +84,10 @@ export class DBManager { * Fetches a block (header and body) given a block id, * which can be either its hash or its number. */ - async getBlock(blockId: Uint8Array | bigint | number): Promise { + async getBlock( + blockId: Uint8Array | bigint | number, + optimistic: boolean = false, + ): Promise { if (typeof blockId === 'number' && Number.isInteger(blockId)) { blockId = BigInt(blockId) } @@ -97,7 +100,13 @@ export class DBManager { number = await this.hashToNumber(blockId) } else if (typeof blockId === 'bigint') { number = blockId - hash = await this.numberToHash(blockId) + if (optimistic) { + hash = await this.optimisticNumberToHash(blockId) + } + // hash will be undefined if it no optimistic lookup was done or if that was not successful + if (hash === undefined) { + hash = await this.numberToHash(blockId) + } } else { throw new Error('Unknown blockId type') } @@ -190,6 +199,11 @@ export class DBManager { return value } + async optimisticNumberToHash(blockNumber: bigint): Promise { + const value = await this.get(DBTarget.OptimisticNumberToHash, { blockNumber }) + return value + } + /** * Fetches a key from the db. If `opts.cache` is specified * it first tries to load from cache, and on cache miss will diff --git a/packages/blockchain/src/db/operation.ts b/packages/blockchain/src/db/operation.ts index a861b9605fc..5358d4c3bf9 100644 --- a/packages/blockchain/src/db/operation.ts +++ b/packages/blockchain/src/db/operation.ts @@ -8,6 +8,7 @@ import { hashToNumberKey, headerKey, numberToHashKey, + optimisticNumberToHashKey, tdKey, } from './constants.js' @@ -25,6 +26,7 @@ export enum DBTarget { CliqueSignerStates, CliqueVotes, CliqueBlockSigners, + OptimisticNumberToHash, } /** @@ -88,6 +90,11 @@ export class DBOp { this.cacheString = 'numberToHash' break } + case DBTarget.OptimisticNumberToHash: { + this.baseDBOp.key = optimisticNumberToHashKey(key!.blockNumber!) + this.cacheString = 'optimisticNumberToHash' + break + } case DBTarget.TotalDifficulty: { this.baseDBOp.key = tdKey(key!.blockNumber!, key!.blockHash!) this.cacheString = 'td'