11import Semaphore from 'semaphore-async-await'
22import { Block , BlockData , BlockHeader } from '@ethereumjs/block'
33import Common , { Chain , ConsensusAlgorithm , ConsensusType , Hardfork } from '@ethereumjs/common'
4- import { toBuffer } from 'ethereumjs-util'
54import { DBManager } from './db/manager'
65import { DBOp , DBSetBlockOrHeader , DBSetTD , DBSetHashToNumber , DBSaveLookups } from './db/helpers'
76import { DBTarget } from './db/operation'
@@ -215,12 +214,6 @@ export default class Blockchain implements BlockchainInterface {
215214 * {@link BlockchainOptions}.
216215 */
217216 protected constructor ( opts : BlockchainOptions = { } ) {
218- // Throw on chain or hardfork options removed in latest major release to
219- // prevent implicit chain setup on a wrong chain
220- if ( 'chain' in opts || 'hardfork' in opts ) {
221- throw new Error ( 'Chain/hardfork options are not allowed any more on initialization' )
222- }
223-
224217 if ( opts . common ) {
225218 this . _common = opts . common
226219 } else {
@@ -328,7 +321,7 @@ export default class Blockchain implements BlockchainInterface {
328321 } else {
329322 stateRoot = await genesisStateRoot ( this . genesisState ( ) )
330323 }
331- genesisBlock = this . genesisBlock ( stateRoot )
324+ genesisBlock = this . createGenesisBlock ( stateRoot )
332325 }
333326
334327 // If the DB has a genesis block, then verify that the genesis block in the
@@ -726,11 +719,7 @@ export default class Blockchain implements BlockchainInterface {
726719 async getIteratorHead ( name = 'vm' ) : Promise < Block > {
727720 return await this . runWithLock < Block > ( async ( ) => {
728721 // if the head is not found return the genesis hash
729- const hash = this . _heads [ name ] ?? this . _genesisBlock ?. hash ( )
730- if ( ! hash ) {
731- throw new Error ( 'No head found.' )
732- }
733-
722+ const hash = this . _heads [ name ] ?? this . genesisBlock . hash ( )
734723 const block = await this . _getBlock ( hash )
735724 return block
736725 } )
@@ -750,11 +739,8 @@ export default class Blockchain implements BlockchainInterface {
750739 async getHead ( name = 'vm' ) : Promise < Block > {
751740 return await this . runWithLock < Block > ( async ( ) => {
752741 // if the head is not found return the headHeader
753- const hash = this . _heads [ name ] || this . _headBlockHash
754- if ( ! hash ) {
755- throw new Error ( 'No head found.' )
756- }
757-
742+ const hash = this . _heads [ name ] ?? this . _headBlockHash
743+ if ( ! hash ) throw new Error ( 'No head found.' )
758744 const block = await this . _getBlock ( hash )
759745 return block
760746 } )
@@ -765,9 +751,7 @@ export default class Blockchain implements BlockchainInterface {
765751 */
766752 async getCanonicalHeadHeader ( ) : Promise < BlockHeader > {
767753 return await this . runWithLock < BlockHeader > ( async ( ) => {
768- if ( ! this . _headHeaderHash ) {
769- throw new Error ( 'No head header set' )
770- }
754+ if ( ! this . _headHeaderHash ) throw new Error ( 'No head header set' )
771755 const block = await this . _getBlock ( this . _headHeaderHash )
772756 return block . header
773757 } )
@@ -778,10 +762,7 @@ export default class Blockchain implements BlockchainInterface {
778762 */
779763 async getCanonicalHeadBlock ( ) : Promise < Block > {
780764 return this . runWithLock < Block > ( async ( ) => {
781- if ( ! this . _headBlockHash ) {
782- throw new Error ( 'No head block set' )
783- }
784-
765+ if ( ! this . _headBlockHash ) throw new Error ( 'No head block set' )
785766 const block = this . _getBlock ( this . _headBlockHash )
786767 return block
787768 } )
@@ -1183,12 +1164,7 @@ export default class Blockchain implements BlockchainInterface {
11831164 */
11841165 private async _iterator ( name : string , onBlock : OnBlock , maxBlocks ?: number ) : Promise < number > {
11851166 return await this . runWithLock < number > ( async ( ) : Promise < number > => {
1186- const headHash = this . _heads [ name ] ?? this . _genesisBlock ?. hash ( )
1187- let lastBlock : Block | undefined
1188-
1189- if ( ! headHash ) {
1190- return 0
1191- }
1167+ const headHash = this . _heads [ name ] ?? this . genesisBlock . hash ( )
11921168
11931169 if ( maxBlocks && maxBlocks < 0 ) {
11941170 throw 'If maxBlocks is provided, it has to be a non-negative number'
@@ -1197,6 +1173,7 @@ export default class Blockchain implements BlockchainInterface {
11971173 const headBlockNumber = await this . dbManager . hashToNumber ( headHash )
11981174 let nextBlockNumber = headBlockNumber + BigInt ( 1 )
11991175 let blocksRanCounter = 0
1176+ let lastBlock : Block | undefined
12001177
12011178 while ( maxBlocks !== blocksRanCounter ) {
12021179 try {
@@ -1205,7 +1182,7 @@ export default class Blockchain implements BlockchainInterface {
12051182 const reorg = lastBlock ? lastBlock . hash ( ) . equals ( nextBlock . header . parentHash ) : false
12061183 lastBlock = nextBlock
12071184 await onBlock ( nextBlock , reorg )
1208- nextBlockNumber += BigInt ( 1 )
1185+ nextBlockNumber ++
12091186 blocksRanCounter ++
12101187 } catch ( error : any ) {
12111188 if ( error . type === 'NotFoundError' ) {
@@ -1241,10 +1218,7 @@ export default class Blockchain implements BlockchainInterface {
12411218 * @param newHeader - the new block header
12421219 */
12431220 private async findCommonAncestor ( newHeader : BlockHeader ) {
1244- if ( ! this . _headHeaderHash ) {
1245- throw new Error ( 'No head header set' )
1246- }
1247-
1221+ if ( ! this . _headHeaderHash ) throw new Error ( 'No head header set' )
12481222 const ancestorHeaders = new Set < BlockHeader > ( )
12491223
12501224 let { header } = await this . _getBlock ( this . _headHeaderHash )
@@ -1303,20 +1277,20 @@ export default class Blockchain implements BlockchainInterface {
13031277 // instance, make the VM run "older" (i.e. lower number blocks than last
13041278 // executed block) blocks to verify the chain up to the current, actual,
13051279 // head.
1306- Object . keys ( this . _heads ) . forEach ( ( name ) => {
1280+ for ( const name of Object . keys ( this . _heads ) ) {
13071281 if ( this . _heads [ name ] . equals ( < Buffer > hash ) ) {
13081282 // explicitly cast as Buffer: it is not possible that `hash` is false
13091283 // here, but TypeScript does not understand this.
13101284 this . _heads [ name ] = headHash
13111285 }
1312- } )
1286+ }
13131287
13141288 // reset stale headBlock to current canonical
13151289 if ( this . _headBlockHash ?. equals ( hash ) ) {
13161290 this . _headBlockHash = headHash
13171291 }
13181292
1319- blockNumber += BigInt ( 1 )
1293+ blockNumber ++
13201294
13211295 hash = await this . safeNumberToHash ( blockNumber )
13221296 }
@@ -1368,11 +1342,11 @@ export default class Blockchain implements BlockchainInterface {
13681342
13691343 // mark each key `_heads` which is currently set to the hash in the DB as
13701344 // stale to overwrite this later.
1371- Object . keys ( this . _heads ) . forEach ( ( name ) => {
1345+ for ( const name of Object . keys ( this . _heads ) ) {
13721346 if ( staleHash && this . _heads [ name ] . equals ( staleHash ) ) {
13731347 staleHeads . push ( name )
13741348 }
1375- } )
1349+ }
13761350 // flag stale headBlock for reset
13771351 if ( staleHash && this . _headBlockHash ?. equals ( staleHash ) ) {
13781352 staleHeadBlock = true
@@ -1390,9 +1364,9 @@ export default class Blockchain implements BlockchainInterface {
13901364 }
13911365 // the stale hash is equal to the blockHash set stale heads to last
13921366 // previously valid canonical block
1393- staleHeads . forEach ( ( name : string ) => {
1367+ for ( const name of staleHeads ) {
13941368 this . _heads [ name ] = currentCanonicalHash
1395- } )
1369+ }
13961370 // set stale headBlock to last previously valid canonical block
13971371 if ( staleHeadBlock ) {
13981372 this . _headBlockHash = currentCanonicalHash
@@ -1463,37 +1437,27 @@ export default class Blockchain implements BlockchainInterface {
14631437 }
14641438
14651439 /**
1466- * Returns the genesis {@link Block} for the blockchain.
1467- * @param stateRoot When initializing the block, pass the genesis stateRoot.
1468- * After the blockchain is initialized, this parameter is not used
1469- * as the cached genesis block is returned.
1440+ * The genesis {@link Block} for the blockchain.
14701441 */
1471- genesisBlock ( stateRoot ?: Buffer ) : Block {
1472- if ( this . _genesisBlock ) {
1473- return this . _genesisBlock
1474- }
1475-
1476- if ( ! stateRoot ) throw new Error ( 'stateRoot required for genesis block creation' )
1442+ get genesisBlock ( ) : Block {
1443+ if ( ! this . _genesisBlock ) throw new Error ( 'genesis block not set (init may not be finished)' )
1444+ return this . _genesisBlock
1445+ }
14771446
1447+ /**
1448+ * Creates a genesis {@link Block} for the blockchain with params from {@link Common.genesis}
1449+ * @param stateRoot The genesis stateRoot
1450+ */
1451+ createGenesisBlock ( stateRoot : Buffer ) : Block {
14781452 const common = this . _common . copy ( )
14791453 common . setHardforkByBlockNumber ( 0 )
14801454
1481- const { gasLimit, timestamp, difficulty, extraData, nonce, baseFeePerGas } = common . genesis ( )
1482-
14831455 const header : BlockData [ 'header' ] = {
1456+ ...common . genesis ( ) ,
14841457 number : 0 ,
1485- gasLimit : BigInt ( gasLimit ) ,
1486- timestamp : BigInt ( timestamp ?? 0 ) ,
1487- difficulty : BigInt ( difficulty ) ,
1488- extraData : toBuffer ( extraData ) ,
1489- nonce : toBuffer ( nonce ) ,
14901458 stateRoot,
14911459 }
14921460
1493- if ( baseFeePerGas !== undefined && common . gteHardfork ( Hardfork . London ) ) {
1494- header . baseFeePerGas = BigInt ( baseFeePerGas )
1495- }
1496-
14971461 return Block . fromBlockData ( { header } , { common } )
14981462 }
14991463
0 commit comments