UNPKG

@ethereumjs/blockchain

Version:
76 lines 3.91 kB
import { createBlock } from '@ethereumjs/block'; import { BIGINT_0, EthereumJSErrorWithoutCode, bytesToHex, equalsBytes } from '@ethereumjs/util'; import debugDefault from 'debug'; import { Blockchain, DBSaveLookups, DBSetBlockOrHeader, DBSetTD, genGenesisStateRoot, getGenesisStateRoot, } from "./index.js"; const DEBUG = typeof window === 'undefined' ? (process?.env?.DEBUG?.includes('ethjs') ?? false) : false; const debug = debugDefault('blockchain:#'); export async function createBlockchain(opts = {}) { const blockchain = new Blockchain(opts); await blockchain.consensus?.setup({ blockchain }); let stateRoot = opts.genesisBlock?.header.stateRoot ?? opts.genesisStateRoot; if (stateRoot === undefined) { if (blockchain['_customGenesisState'] !== undefined) { stateRoot = await genGenesisStateRoot(blockchain['_customGenesisState'], blockchain.common); } else { stateRoot = await getGenesisStateRoot(Number(blockchain.common.chainId()), blockchain.common); } } const genesisBlock = opts.genesisBlock ?? blockchain.createGenesisBlock(stateRoot); let genesisHash = await blockchain.dbManager.numberToHash(BIGINT_0); const dbGenesisBlock = genesisHash !== undefined ? await blockchain.dbManager.getBlock(genesisHash) : undefined; // If the DB has a genesis block, then verify that the genesis block in the // DB is indeed the Genesis block generated or assigned. if (dbGenesisBlock !== undefined && !equalsBytes(genesisBlock.hash(), dbGenesisBlock.hash())) { throw EthereumJSErrorWithoutCode('The genesis block in the DB has a different hash than the provided genesis block.'); } genesisHash = genesisBlock.hash(); if (!dbGenesisBlock) { // If there is no genesis block put the genesis block in the DB. // For that TD, the BlockOrHeader, and the Lookups have to be saved. const dbOps = []; dbOps.push(DBSetTD(genesisBlock.header.difficulty, BIGINT_0, genesisHash)); DBSetBlockOrHeader(genesisBlock).map((op) => dbOps.push(op)); DBSaveLookups(genesisHash, BIGINT_0).map((op) => dbOps.push(op)); await blockchain.dbManager.batch(dbOps); await blockchain.consensus?.genesisInit(genesisBlock); } // At this point, we can safely set the genesis: // it is either the one we put in the DB, or it is equal to the one // which we read from the DB. blockchain['_genesisBlock'] = genesisBlock; // load verified iterator heads const heads = await blockchain.dbManager.getHeads(); blockchain['_heads'] = heads ?? {}; // load headerchain head let hash = await blockchain.dbManager.getHeadHeader(); blockchain['_headHeaderHash'] = hash ?? genesisHash; // load blockchain head hash = await blockchain.dbManager.getHeadBlock(); blockchain['_headBlockHash'] = hash ?? genesisHash; if (blockchain['_hardforkByHeadBlockNumber']) { const latestHeader = await blockchain['_getHeader'](blockchain['_headHeaderHash']); await blockchain.checkAndTransitionHardForkByNumber(latestHeader.number, latestHeader.timestamp); } DEBUG && debug(`genesis block initialized with hash ${bytesToHex(genesisHash)}`); return blockchain; } /** * Creates a blockchain from a list of block objects, * objects must be readable by {@link createBlock} * * @param blockData List of block objects * @param opts Constructor options, see {@link BlockchainOptions} */ export async function createBlockchainFromBlocksData(blocksData, opts = {}) { const blockchain = await createBlockchain(opts); for (const blockData of blocksData) { const block = createBlock(blockData, { common: blockchain.common, setHardfork: true, }); await blockchain.putBlock(block); } return blockchain; } //# sourceMappingURL=constructors.js.map