From ebc4fc2c249d97ab7659d557b3b05208a43bc989 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 18:45:57 -0700 Subject: [PATCH 1/9] blockchain: remove storing unsettled promise --- packages/blockchain/src/index.ts | 89 +++++++++++-------------- packages/blockchain/test/clique.spec.ts | 2 +- packages/blockchain/test/index.spec.ts | 74 ++++++++++---------- packages/blockchain/test/reorg.spec.ts | 4 +- packages/blockchain/test/util.ts | 2 +- 5 files changed, 76 insertions(+), 95 deletions(-) diff --git a/packages/blockchain/src/index.ts b/packages/blockchain/src/index.ts index 4c18d22bb8..b604397d16 100644 --- a/packages/blockchain/src/index.ts +++ b/packages/blockchain/src/index.ts @@ -17,13 +17,12 @@ import { CLIQUE_NONCE_AUTH, CLIQUE_NONCE_DROP, } from './clique' - -const debug = createDebugLogger('blockchain:clique') - // eslint-disable-next-line implicit-dependencies/no-implicit import type { LevelUp } from 'levelup' const level = require('level-mem') +const debug = createDebugLogger('blockchain:clique') + type OnBlock = (block: Block, reorg: boolean) => Promise | void export interface BlockchainInterface { @@ -112,7 +111,7 @@ export interface BlockchainOptions { validateBlocks?: boolean /** - * The blockchain only initializes succesfully if it has a genesis block. If + * The blockchain only initializes successfully if it has a genesis block. If * there is no block available in the DB and a `genesisBlock` is provided, * then the provided `genesisBlock` will be used as genesis. If no block is * present in the DB and no block is provided, then the genesis block as @@ -130,18 +129,25 @@ export default class Blockchain implements BlockchainInterface { private _genesis?: Buffer // the genesis hash of this blockchain - // The following two heads and the heads stored within the `_heads` always point - // to a hash in the canonical chain and never to a stale hash. - // With the exception of `_headHeaderHash` this does not necessarily need to be - // the hash with the highest total difficulty. - private _headBlockHash?: Buffer // the hash of the current head block - private _headHeaderHash?: Buffer // the hash of the current head header - // A Map which stores the head of each key (for instance the "vm" key) which is - // updated along a {@link Blockchain.iterator} method run and can be used to (re)run - // non-verified blocks (for instance in the VM). + /** + * The following two heads and the heads stored within the `_heads` always point + * to a hash in the canonical chain and never to a stale hash. + * With the exception of `_headHeaderHash` this does not necessarily need to be + * the hash with the highest total difficulty. + */ + /** The hash of the current head block */ + private _headBlockHash?: Buffer + /** The hash of the current head header */ + private _headHeaderHash?: Buffer + + /** + * A Map which stores the head of each key (for instance the "vm" key) which is + * updated along a {@link Blockchain.iterator} method run and can be used to (re)run + * non-verified blocks (for instance in the VM). + */ private _heads: { [key: string]: Buffer } - public initPromise: Promise + protected _isInitialized = false private _lock: Semaphore private _common: Common @@ -207,9 +213,7 @@ export default class Blockchain implements BlockchainInterface { public static async create(opts: BlockchainOptions = {}) { const blockchain = new Blockchain(opts) - await blockchain.initPromise!.catch((e) => { - throw e - }) + await blockchain._init(opts.genesisBlock) return blockchain } @@ -233,13 +237,13 @@ export default class Blockchain implements BlockchainInterface { } /** - * Creates new Blockchain object + * Creates new Blockchain object. * - * @deprecated - The direct usage of this constructor is discouraged since + * @deprecated The direct usage of this constructor is discouraged since * non-finalized async initialization might lead to side effects. Please * use the async {@link Blockchain.create} constructor instead (same API). * - * @param opts - An object with the options that this constructor takes. See + * @param opts An object with the options that this constructor takes. See * {@link BlockchainOptions}. */ constructor(opts: BlockchainOptions = {}) { @@ -291,9 +295,6 @@ export default class Blockchain implements BlockchainInterface { if (opts.genesisBlock && !opts.genesisBlock.isGenesis()) { throw 'supplied block is not a genesis block' } - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.initPromise = this._init(opts.genesisBlock) } /** @@ -329,13 +330,14 @@ export default class Blockchain implements BlockchainInterface { } /** - * This method is called in the constructor and either sets up the DB or reads + * This method is called in {@link Blockchain.create} and either sets up the DB or reads * values from the DB and makes these available to the consumers of * Blockchain. * * @hidden */ private async _init(genesisBlock?: Block): Promise { + if (this._isInitialized) return let dbGenesisBlock try { const genesisHash = await this.dbManager.numberToHash(BigInt(0)) @@ -421,23 +423,14 @@ export default class Blockchain implements BlockchainInterface { } this._headBlockHash = genesisHash } + if (this._hardforkByHeadBlockNumber) { const latestHeader = await this._getHeader(this._headHeaderHash) const td = await this.getTotalDifficulty(this._headHeaderHash) this._common.setHardforkByBlockNumber(latestHeader.number, td) } - } - /** - * Perform the `action` function after we have initialized this module and - * have acquired a lock - * @param action - the action function to run after initializing and acquiring - * a lock - * @hidden - */ - private async initAndLock(action: () => Promise): Promise { - await this.initPromise - return await this.runWithLock(action) + this._isInitialized = true } /** @@ -758,7 +751,7 @@ export default class Blockchain implements BlockchainInterface { * @param name - Optional name of the iterator head (default: 'vm') */ async getIteratorHead(name = 'vm'): Promise { - return await this.initAndLock(async () => { + return await this.runWithLock(async () => { // if the head is not found return the genesis hash const hash = this._heads[name] || this._genesis if (!hash) { @@ -782,7 +775,7 @@ export default class Blockchain implements BlockchainInterface { * on a first run) */ async getHead(name = 'vm'): Promise { - return await this.initAndLock(async () => { + return await this.runWithLock(async () => { // if the head is not found return the headHeader const hash = this._heads[name] || this._headBlockHash if (!hash) { @@ -798,7 +791,7 @@ export default class Blockchain implements BlockchainInterface { * Returns the latest header in the canonical chain. */ async getLatestHeader(): Promise { - return await this.initAndLock(async () => { + return await this.runWithLock(async () => { if (!this._headHeaderHash) { throw new Error('No head header set') } @@ -811,7 +804,7 @@ export default class Blockchain implements BlockchainInterface { * Returns the latest full block in the canonical chain. */ async getLatestBlock(): Promise { - return this.initAndLock(async () => { + return this.runWithLock(async () => { if (!this._headBlockHash) { throw new Error('No head block set') } @@ -831,7 +824,6 @@ export default class Blockchain implements BlockchainInterface { * @param blocks - The blocks to be added to the blockchain */ async putBlocks(blocks: Block[]) { - await this.initPromise for (let i = 0; i < blocks.length; i++) { await this.putBlock(blocks[i]) } @@ -846,7 +838,6 @@ export default class Blockchain implements BlockchainInterface { * @param block - The block to be added to the blockchain */ async putBlock(block: Block) { - await this.initPromise await this._putBlockOrHeader(block) } @@ -860,7 +851,6 @@ export default class Blockchain implements BlockchainInterface { * @param headers - The headers to be added to the blockchain */ async putHeaders(headers: Array) { - await this.initPromise for (let i = 0; i < headers.length; i++) { await this.putHeader(headers[i]) } @@ -875,7 +865,6 @@ export default class Blockchain implements BlockchainInterface { * @param header - The header to be added to the blockchain */ async putHeader(header: BlockHeader) { - await this.initPromise await this._putBlockOrHeader(header) } @@ -1056,7 +1045,6 @@ export default class Blockchain implements BlockchainInterface { // in the `VM` if we encounter a `BLOCKHASH` opcode: then a bigint is used we // need to then read the block from the canonical chain Q: is this safe? We // know it is OK if we call it from the iterator... (runBlock) - await this.initPromise return await this._getBlock(blockId) } @@ -1091,7 +1079,7 @@ export default class Blockchain implements BlockchainInterface { skip: number, reverse: boolean ): Promise { - return await this.initAndLock(async () => { + return await this.runWithLock(async () => { const blocks: Block[] = [] let i = -1 @@ -1128,7 +1116,7 @@ export default class Blockchain implements BlockchainInterface { * @param hashes - Ordered array of hashes (ordered on `number`). */ async selectNeededHashes(hashes: Array): Promise { - return await this.initAndLock(async () => { + return await this.runWithLock(async () => { let max: number let mid: number let min: number @@ -1173,7 +1161,6 @@ export default class Blockchain implements BlockchainInterface { // But is this the way to go? If we know this is called from the // iterator/runBlockchain we are safe, but if this is called from anywhere // else then this might lead to a concurrency problem? - await this.initPromise await this._delBlock(blockHash) } @@ -1273,7 +1260,7 @@ export default class Blockchain implements BlockchainInterface { * @hidden */ private async _iterator(name: string, onBlock: OnBlock, maxBlocks?: number): Promise { - return await this.initAndLock(async (): Promise => { + return await this.runWithLock(async (): Promise => { const headHash = this._heads[name] || this._genesis let lastBlock: Block | undefined @@ -1314,7 +1301,7 @@ export default class Blockchain implements BlockchainInterface { /** * Set header hash of a certain `tag`. - * When calling the iterator, the iterator will start running the first child block after the header hash currenntly stored. + * When calling the iterator, the iterator will start running the first child block after the header hash currently stored. * @param tag - The tag to save the headHash to * @param headHash - The head hash to save */ @@ -1324,14 +1311,14 @@ export default class Blockchain implements BlockchainInterface { /** * Set header hash of a certain `tag`. - * When calling the iterator, the iterator will start running the first child block after the header hash currenntly stored. + * When calling the iterator, the iterator will start running the first child block after the header hash currently stored. * @param tag - The tag to save the headHash to * @param headHash - The head hash to save * * @deprecated use {@link Blockchain.setIteratorHead()} instead */ async setHead(tag: string, headHash: Buffer) { - await this.initAndLock(async () => { + await this.runWithLock(async () => { this._heads[tag] = headHash await this._saveHeads() }) diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 2470daf682..45c954d215 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -8,7 +8,7 @@ import { CLIQUE_NONCE_AUTH, CLIQUE_NONCE_DROP } from '../src/clique' tape('Clique: Initialization', (t) => { t.test('should initialize a clique blockchain', async (st) => { const common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - const blockchain = new Blockchain({ common }) + const blockchain = await Blockchain.create({ common }) const head = await blockchain.getHead() st.equal(head.hash().toString('hex'), common.genesis().hash.slice(2), 'correct genesis hash') diff --git a/packages/blockchain/test/index.spec.ts b/packages/blockchain/test/index.spec.ts index ee5e27909d..bd14e98922 100644 --- a/packages/blockchain/test/index.spec.ts +++ b/packages/blockchain/test/index.spec.ts @@ -10,7 +10,7 @@ const level = require('level-mem') tape('blockchain test', (t) => { t.test('should not crash on getting head of a blockchain without a genesis', async (st) => { - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, }) @@ -20,7 +20,7 @@ tape('blockchain test', (t) => { t.test('should initialize correctly', async (st) => { const common = new Common({ chain: Chain.Ropsten }) - let blockchain = new Blockchain({ common }) + let blockchain = await Blockchain.create({ common }) const head = await blockchain.getHead() const iteratorHead = await blockchain.getIteratorHead() @@ -59,33 +59,27 @@ tape('blockchain test', (t) => { st.end() }) - t.test('should only initialize with supported consensus validation options', (st) => { + t.test('should only initialize with supported consensus validation options', async (st) => { let common = new Common({ chain: Chain.Mainnet }) - st.doesNotThrow(() => { - new Blockchain({ common, validateConsensus: true }) - }) - st.doesNotThrow(() => { - new Blockchain({ common, validateBlocks: true }) - }) - - common = new Common({ chain: Chain.Goerli }) - st.doesNotThrow(() => { - new Blockchain({ common, validateConsensus: true }) - }) - st.doesNotThrow(() => { - new Blockchain({ common, validateBlocks: true }) - }) - st.end() + try { + await Blockchain.create({ common, validateConsensus: true }) + await Blockchain.create({ common, validateBlocks: true }) + common = new Common({ chain: Chain.Goerli }) + await Blockchain.create({ common, validateConsensus: true }) + await Blockchain.create({ common, validateBlocks: true }) + st.pass('should not throw') + } catch (error) { + st.fail('show not have thrown') + } }) t.test('should add a genesis block without errors', async (st) => { const genesisBlock = Block.genesis() - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, }) - await blockchain.initPromise st.ok( genesisBlock.hash().equals(blockchain.meta.genesis!), 'genesis block hash should be correct' @@ -108,7 +102,7 @@ tape('blockchain test', (t) => { }) t.test('should initialize with a genesis block', async (st) => { - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, }) @@ -125,7 +119,7 @@ tape('blockchain test', (t) => { const genesisBlock = Block.genesis({ header: { gasLimit } }, { common }) blocks.push(genesisBlock) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -171,7 +165,7 @@ tape('blockchain test', (t) => { const genesisBlock = Block.genesis({ header: { gasLimit } }, { common }) blocks.push(genesisBlock) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -206,7 +200,7 @@ tape('blockchain test', (t) => { const gasLimit = 8000000 const genesisBlock = Block.genesis({ header: { gasLimit } }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -500,7 +494,7 @@ tape('blockchain test', (t) => { }) t.test('should not call iterator function in an empty blockchain', async (st) => { - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, }) @@ -613,7 +607,7 @@ tape('blockchain test', (t) => { t.test('should put one block at a time', async (st) => { const blocks = generateBlocks(15) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock: blocks[0], @@ -628,7 +622,7 @@ tape('blockchain test', (t) => { const blocks: Block[] = [] const genesisBlock = Block.genesis({ header: { gasLimit: 8000000 } }) blocks.push(...generateBlocks(15, [genesisBlock])) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -639,7 +633,7 @@ tape('blockchain test', (t) => { t.test('should get heads', async (st) => { const [db, genesis] = await createTestDB() - const blockchain = new Blockchain({ db: db }) + const blockchain = await Blockchain.create({ db: db }) const head = await blockchain.getHead() if (genesis) { st.ok(head.hash().equals(genesis.hash()), 'should get head') @@ -656,7 +650,7 @@ tape('blockchain test', (t) => { t.test('should validate', async (st) => { const genesisBlock = Block.genesis({ header: { gasLimit: 8000000 } }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -679,7 +673,7 @@ tape('blockchain test', (t) => { initWithGenesisHeader: true, common, }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -696,7 +690,7 @@ tape('blockchain test', (t) => { if (!genesis) { return st.fail('genesis not defined!') } - const blockchain = new Blockchain({ db }) + const blockchain = await Blockchain.create({ db }) const number = await blockchain.dbManager.hashToNumber(genesis?.hash()) st.equal(number, BigInt(0), 'should perform _hashToNumber correctly') @@ -716,7 +710,7 @@ tape('blockchain test', (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) const genesisBlock = Block.genesis({ header: { gasLimit } }, { common }) - let blockchain = new Blockchain({ + let blockchain = await Blockchain.create({ db, validateBlocks: true, validateConsensus: false, @@ -735,7 +729,7 @@ tape('blockchain test', (t) => { }) await blockchain.putHeader(header) - blockchain = new Blockchain({ + blockchain = await Blockchain.create({ db, validateBlocks: true, validateConsensus: false, @@ -756,7 +750,7 @@ tape('blockchain test', (t) => { const opts: BlockOptions = { common } const genesisBlock = Block.genesis({ header: { gasLimit } }, opts) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock, @@ -840,7 +834,7 @@ tape('blockchain test', (t) => { }), ] - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ common, validateBlocks: true, validateConsensus: false, @@ -871,7 +865,7 @@ tape('initialization tests', (t) => { hardfork: Hardfork.Chainstart, }) const genesisHash = Block.genesis({}, { common }).hash() - const blockchain = new Blockchain({ common }) + const blockchain = await Blockchain.create({ common }) st.ok( (await blockchain.getHead()).hash().equals(genesisHash), @@ -880,7 +874,7 @@ tape('initialization tests', (t) => { const db = blockchain.db - const newBlockchain = new Blockchain({ db, common }) + const newBlockchain = await Blockchain.create({ db, common }) st.ok( (await newBlockchain.getHead()).hash().equals(genesisHash), @@ -896,7 +890,7 @@ tape('initialization tests', (t) => { }, }) const hash = genesisBlock.hash() - const blockchain = new Blockchain({ genesisBlock }) + const blockchain = await Blockchain.create({ genesisBlock }) const db = blockchain.db st.ok( @@ -904,7 +898,7 @@ tape('initialization tests', (t) => { 'blockchain should put custom genesis block' ) - const newBlockchain = new Blockchain({ db, genesisBlock }) + const newBlockchain = await Blockchain.create({ db, genesisBlock }) st.ok( (await newBlockchain.getHead()).hash().equals(hash), 'head hash should be read from the provided db' @@ -919,7 +913,7 @@ tape('initialization tests', (t) => { }, }) const hash = genesisBlock.hash() - const blockchain = new Blockchain({ genesisBlock }) + const blockchain = await Blockchain.create({ genesisBlock }) const db = blockchain.db const otherGenesisBlock = Block.genesis({ diff --git a/packages/blockchain/test/reorg.spec.ts b/packages/blockchain/test/reorg.spec.ts index 136276730e..53827f3d53 100644 --- a/packages/blockchain/test/reorg.spec.ts +++ b/packages/blockchain/test/reorg.spec.ts @@ -21,7 +21,7 @@ tape('reorg tests', (t) => { }, { common } ) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, common, @@ -90,7 +90,7 @@ tape('reorg tests', (t) => { async (st) => { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) const genesisBlock = Block.genesis({}, { common }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false, common, diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index 84f1b2ac3b..0a5bfc1aed 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -40,7 +40,7 @@ export const generateBlockchain = async (numberOfBlocks: number, genesis?: Block const existingBlocks: Block[] = genesis ? [genesis] : [] const blocks = generateBlocks(numberOfBlocks, existingBlocks) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: true, validateConsensus: false, genesisBlock: genesis ?? blocks[0], From a803fa578161f9dc665f24985234863b93954ca9 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 19:32:45 -0700 Subject: [PATCH 2/9] vm: remove storing unsettled promises. make copy() async --- packages/vm/benchmarks/mainnetBlocks.ts | 6 +- packages/vm/examples/run-blockchain.ts | 4 +- packages/vm/examples/run-code-browser.js | 34 ++++++----- packages/vm/examples/run-solidity-contract.ts | 2 +- packages/vm/src/index.ts | 23 +++---- .../EIPs/eip-1283-net-gas-metering.spec.ts | 2 +- .../tests/api/EIPs/eip-1559-FeeMarket.spec.ts | 4 +- packages/vm/tests/api/EIPs/eip-2315.spec.ts | 2 +- .../vm/tests/api/EIPs/eip-2537-BLS.spec.ts | 6 +- .../api/EIPs/eip-2565-modexp-gas-cost.spec.ts | 2 +- packages/vm/tests/api/EIPs/eip-2929.spec.ts | 4 +- .../api/EIPs/eip-2930-accesslists.spec.ts | 3 +- .../tests/api/EIPs/eip-3198-BaseFee.spec.ts | 2 +- packages/vm/tests/api/EIPs/eip-3529.spec.ts | 6 +- packages/vm/tests/api/EIPs/eip-3541.spec.ts | 8 +-- packages/vm/tests/api/EIPs/eip-3607.spec.ts | 4 +- packages/vm/tests/api/EIPs/eip-3855.spec.ts | 8 +-- ...t-difficulty-opcode-with-prevrando.spec.ts | 2 +- packages/vm/tests/api/buildBlock.spec.ts | 6 +- packages/vm/tests/api/events.spec.ts | 16 ++--- .../api/evm/precompiles/06-ecadd.spec.ts | 2 +- .../api/evm/precompiles/07-ecmul.spec.ts | 2 +- .../api/evm/precompiles/08-ecpairing.spec.ts | 2 +- .../api/evm/precompiles/hardfork.spec.ts | 6 +- packages/vm/tests/api/evm/stack.spec.ts | 2 +- packages/vm/tests/api/index.spec.ts | 32 +++++----- .../vm/tests/api/istanbul/eip-1108.spec.ts | 6 +- .../vm/tests/api/istanbul/eip-1344.spec.ts | 2 +- .../vm/tests/api/istanbul/eip-152.spec.ts | 4 +- .../vm/tests/api/istanbul/eip-1884.spec.ts | 2 +- .../vm/tests/api/istanbul/eip-2200.spec.ts | 2 +- .../vm/tests/api/muirGlacier/index.spec.ts | 4 +- packages/vm/tests/api/opcodes.spec.ts | 18 +++--- packages/vm/tests/api/runBlock.spec.ts | 34 +++++------ packages/vm/tests/api/runBlockchain.spec.ts | 30 +++++---- packages/vm/tests/api/runCall.spec.ts | 28 ++++----- packages/vm/tests/api/runCode.spec.ts | 61 ++++++++++--------- packages/vm/tests/api/runTx.spec.ts | 42 ++++++------- .../vm/tests/api/state/accountExists.spec.ts | 4 +- packages/vm/tests/api/utils.ts | 7 ++- .../tester/runners/BlockchainTestsRunner.ts | 8 +-- .../tester/runners/GeneralStateTestsRunner.ts | 2 +- 42 files changed, 224 insertions(+), 220 deletions(-) diff --git a/packages/vm/benchmarks/mainnetBlocks.ts b/packages/vm/benchmarks/mainnetBlocks.ts index c660cb87bc..74cf14b317 100644 --- a/packages/vm/benchmarks/mainnetBlocks.ts +++ b/packages/vm/benchmarks/mainnetBlocks.ts @@ -9,7 +9,9 @@ import { getPreState, getBlockchain, verifyResult } from './util' const BLOCK_FIXTURE = 'benchmarks/fixture/blocks-prestate.json' const runBlock = async (vm: VM, block: Block, receipts: any) => { - await vm.copy().runBlock({ + await ( + await vm.copy() + ).runBlock({ block, generate: true, skipBlockValidation: true, @@ -43,7 +45,7 @@ export async function mainnetBlocks(suite?: Benchmark.Suite, numSamples?: number const stateManager = await getPreState(preState, common) const blockchain = getBlockchain(blockhashes) as any - const vm = new VM({ stateManager, common, blockchain }) + const vm = await VM.create({ stateManager, common, blockchain }) if (suite) { suite.add(`Block ${blockNumber}`, async () => { diff --git a/packages/vm/examples/run-blockchain.ts b/packages/vm/examples/run-blockchain.ts index 3cb5c4501d..552165c684 100644 --- a/packages/vm/examples/run-blockchain.ts +++ b/packages/vm/examples/run-blockchain.ts @@ -34,7 +34,7 @@ async function main() { blockchain._ethash!.cacheDB = level('./.cachedb') } - const vm = new VM({ blockchain, common }) + const vm = await VM.create({ blockchain, common }) await setupPreConditions(vm, testData) @@ -42,7 +42,7 @@ async function main() { await vm.runBlockchain(blockchain) - const blockchainHead = await vm.blockchain.getHead() + const blockchainHead = await vm.blockchain.getIteratorHead() console.log('--- Finished processing the BlockChain ---') console.log('New head:', '0x' + blockchainHead.hash().toString('hex')) diff --git a/packages/vm/examples/run-code-browser.js b/packages/vm/examples/run-code-browser.js index 4bffb591e3..3c200ad893 100644 --- a/packages/vm/examples/run-code-browser.js +++ b/packages/vm/examples/run-code-browser.js @@ -8,29 +8,33 @@ * using node-static or `python -mSimpleHTTPServer`). */ const BN = require('bn.js') -const VM = require('../dist').default +const VM = require('../dist.browser').default -// Create a new VM instance -// To explicity set the chain or hardfork use [Common](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common#usage) -const vm = new VM() +const run = async () => { + // Create a new VM instance + // To explicity set the chain or hardfork use [Common](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common#usage) + const vm = await VM.create() -const STOP = '00' -const ADD = '01' -const PUSH1 = '60' + const STOP = '00' + const ADD = '01' + const PUSH1 = '60' -// Note that numbers added are hex values, so '20' would be '32' as decimal e.g. -const code = [PUSH1, '03', PUSH1, '05', ADD, STOP] + // Note that numbers added are hex values, so '20' would be '32' as decimal e.g. + const code = [PUSH1, '03', PUSH1, '05', ADD, STOP] -vm.on('step', function (data) { + vm.on('step', function (data) { console.log(`Opcode: ${data.opcode.name}\tStack: ${data.stack}`) -}) + }) -vm.runCode({ + vm.runCode({ code: Buffer.from(code.join(''), 'hex'), gasLimit: new BN(0xffff), -}) + }) .then((results) => { - console.log(`Returned: ${results.returnValue.toString('hex')}`) - console.log(`gasUsed : ${results.gasUsed.toString()}`) + console.log(`Returned: ${results.returnValue.toString('hex')}`) + console.log(`gasUsed : ${results.gasUsed.toString()}`) }) .catch(console.error) +} + +run() diff --git a/packages/vm/examples/run-solidity-contract.ts b/packages/vm/examples/run-solidity-contract.ts index b9557a05c9..4ef0cb8c63 100644 --- a/packages/vm/examples/run-solidity-contract.ts +++ b/packages/vm/examples/run-solidity-contract.ts @@ -157,7 +157,7 @@ async function main() { 'hex' ) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const accountAddress = Address.fromPrivateKey(accountPk) console.log('Account: ', accountAddress.toString()) diff --git a/packages/vm/src/index.ts b/packages/vm/src/index.ts index 587007f583..5334cdef99 100644 --- a/packages/vm/src/index.ts +++ b/packages/vm/src/index.ts @@ -20,11 +20,9 @@ import { AsyncDynamicGasHandler, SyncDynamicGasHandler } from './evm/opcodes/gas // very ugly way to detect if we are running in a browser const isBrowser = new Function('try {return this===window;}catch(e){ return false;}') let mcl: any -let mclInitPromise: any if (!isBrowser()) { mcl = require('mcl-wasm') - mclInitPromise = mcl.init(mcl.BLS12_381) } /** @@ -78,7 +76,7 @@ export interface VMOpts { stateManager?: StateManager /** * A {@link SecureTrie} instance for the state tree (ignored if stateManager is passed) - * @deprecated - will be removed in next major version release + * @deprecated will be removed in next major version release */ state?: Trie /** @@ -222,6 +220,10 @@ export default class VM extends AsyncEventEmitter { /** * Instantiates a new {@link VM} Object. + * + * @deprecated The direct usage of this constructor is discouraged since + * non-finalized async initialization might lead to side effects. Please + * use the async {@link VM.create} constructor instead (same API). * @param opts */ constructor(opts: VMOpts = {}) { @@ -329,7 +331,7 @@ export default class VM extends AsyncEventEmitter { return } - await this.blockchain.initPromise + await (this.blockchain as any)._init() if (!this._opts.stateManager) { if (this._opts.activateGenesisState) { @@ -356,12 +358,13 @@ export default class VM extends AsyncEventEmitter { throw new Error('EIP-2537 is currently not supported in browsers') } else { const mcl = this._mcl - await mclInitPromise // ensure that mcl is initialized. + await mcl.init(mcl.BLS12_381) // ensure that mcl is initialized. mcl.setMapToMode(mcl.IRTF) // set the right map mode; otherwise mapToG2 will return wrong values. mcl.verifyOrderG1(1) // subgroup checks for G1 mcl.verifyOrderG2(1) // subgroup checks for G2 } } + this._isInitialized = true } @@ -373,7 +376,6 @@ export default class VM extends AsyncEventEmitter { * @param blockchain - A {@link Blockchain} object to process */ async runBlockchain(blockchain?: Blockchain, maxBlocks?: number): Promise { - await this.init() return runBlockchain.bind(this)(blockchain, maxBlocks) } @@ -388,7 +390,6 @@ export default class VM extends AsyncEventEmitter { * - `generate`: false */ async runBlock(opts: RunBlockOpts): Promise { - await this.init() return runBlock.bind(this)(opts) } @@ -402,7 +403,6 @@ export default class VM extends AsyncEventEmitter { * @param {RunTxOpts} opts */ async runTx(opts: RunTxOpts): Promise { - await this.init() return runTx.bind(this)(opts) } @@ -414,7 +414,6 @@ export default class VM extends AsyncEventEmitter { * @param {RunCallOpts} opts */ async runCall(opts: RunCallOpts): Promise { - await this.init() return runCall.bind(this)(opts) } @@ -426,7 +425,6 @@ export default class VM extends AsyncEventEmitter { * @param {RunCodeOpts} opts */ async runCode(opts: RunCodeOpts): Promise { - await this.init() return runCode.bind(this)(opts) } @@ -445,7 +443,6 @@ export default class VM extends AsyncEventEmitter { * - {@link BlockBuilder.revert} */ async buildBlock(opts: BuildBlockOpts): Promise { - await this.init() return buildBlock.bind(this)(opts) } @@ -464,8 +461,8 @@ export default class VM extends AsyncEventEmitter { /** * Returns a copy of the {@link VM} instance. */ - copy(): VM { - return new VM({ + async copy(): Promise { + return VM.create({ stateManager: this.stateManager.copy(), blockchain: this.blockchain.copy(), common: this._common.copy(), diff --git a/packages/vm/tests/api/EIPs/eip-1283-net-gas-metering.spec.ts b/packages/vm/tests/api/EIPs/eip-1283-net-gas-metering.spec.ts index fc062493ae..0af0902196 100644 --- a/packages/vm/tests/api/EIPs/eip-1283-net-gas-metering.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-1283-net-gas-metering.spec.ts @@ -35,7 +35,7 @@ tape('Constantinople: EIP-1283', async (t) => { const key = setLengthLeft(bigIntToBuffer(BigInt(0)), 32) for (const testCase of testCases) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = createAccount(BigInt(0), BigInt(0)) await vm.stateManager.putAccount(addr, account) diff --git a/packages/vm/tests/api/EIPs/eip-1559-FeeMarket.spec.ts b/packages/vm/tests/api/EIPs/eip-1559-FeeMarket.spec.ts index 18b192f1b7..01f40c03c9 100644 --- a/packages/vm/tests/api/EIPs/eip-1559-FeeMarket.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-1559-FeeMarket.spec.ts @@ -73,7 +73,7 @@ tape('EIP1559 tests', (t) => { } ) const block = makeBlock(GWEI, tx, 2) - const vm = new VM({ common }) + const vm = await VM.create({ common }) let account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10) account.balance = balance @@ -173,7 +173,7 @@ tape('EIP1559 tests', (t) => { } ) const block = makeBlock(GWEI, tx, 2) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const balance = GWEI * BigInt(210000) * BigInt(10) await vm.stateManager.modifyAccountFields(sender, { balance }) diff --git a/packages/vm/tests/api/EIPs/eip-2315.spec.ts b/packages/vm/tests/api/EIPs/eip-2315.spec.ts index 670e7d7d91..5a68ed2359 100644 --- a/packages/vm/tests/api/EIPs/eip-2315.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2315.spec.ts @@ -7,7 +7,7 @@ tape('Berlin: EIP 2315 tests', (t) => { const runTest = async function (test: any, st: tape.Test) { let i = 0 - const vm = new VM({ common }) + const vm = await VM.create({ common }) vm.on('step', function (step: any) { if (test.steps.length) { diff --git a/packages/vm/tests/api/EIPs/eip-2537-BLS.spec.ts b/packages/vm/tests/api/EIPs/eip-2537-BLS.spec.ts index d56c9482e8..88abc9fc16 100644 --- a/packages/vm/tests/api/EIPs/eip-2537-BLS.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2537-BLS.spec.ts @@ -21,7 +21,7 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) for (const address of precompiles) { const to = new Address(Buffer.from(address, 'hex')) @@ -52,7 +52,7 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium, eips: [2537] }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) for (const address of precompiles) { const to = new Address(Buffer.from(address, 'hex')) @@ -90,7 +90,7 @@ tape('EIP-2537 BLS tests', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [2537] }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const address = new Address(Buffer.from('000000000000000000000000000000000000000f', 'hex')) const BLS12G2MultiExp = getPrecompile(address, common) diff --git a/packages/vm/tests/api/EIPs/eip-2565-modexp-gas-cost.spec.ts b/packages/vm/tests/api/EIPs/eip-2565-modexp-gas-cost.spec.ts index 4bc87ba72f..9f371f25c8 100644 --- a/packages/vm/tests/api/EIPs/eip-2565-modexp-gas-cost.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2565-modexp-gas-cost.spec.ts @@ -9,7 +9,7 @@ const testData = require('../testdata/eip-2565.json') tape('EIP-2565 ModExp gas cost tests', (t) => { t.test('Test return data, gas cost and execution status against testdata', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium, eips: [2565] }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) for (const test of testData) { const testName = test.Name diff --git a/packages/vm/tests/api/EIPs/eip-2929.spec.ts b/packages/vm/tests/api/EIPs/eip-2929.spec.ts index 1b7f7f53e6..a23aa2e6cf 100644 --- a/packages/vm/tests/api/EIPs/eip-2929.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2929.spec.ts @@ -17,7 +17,7 @@ tape('EIP 2929: gas cost tests', (t) => { const runTest = async function (test: any, st: tape.Test) { let i = 0 let currentGas = initialGas - const vm = new VM({ common }) + const vm = await VM.create({ common }) vm.on('step', function (step: any) { const gasUsed = currentGas - step.gasLeft @@ -75,7 +75,7 @@ tape('EIP 2929: gas cost tests', (t) => { ) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [2929] }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) await vm.stateManager.putContractCode(contractAddress, Buffer.from(code, 'hex')) // setup the contract code diff --git a/packages/vm/tests/api/EIPs/eip-2930-accesslists.spec.ts b/packages/vm/tests/api/EIPs/eip-2930-accesslists.spec.ts index 9646bc15e0..004e3445de 100644 --- a/packages/vm/tests/api/EIPs/eip-2930-accesslists.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-2930-accesslists.spec.ts @@ -46,7 +46,8 @@ tape('EIP-2930 Optional Access Lists tests', (t) => { }, { common } ).sign(privateKey) - const vm = new VM({ common }) + + const vm = await VM.create({ common }) // contract code PUSH1 0x00 SLOAD STOP await vm.stateManager.putContractCode(contractAddress, Buffer.from('60005400', 'hex')) diff --git a/packages/vm/tests/api/EIPs/eip-3198-BaseFee.spec.ts b/packages/vm/tests/api/EIPs/eip-3198-BaseFee.spec.ts index 28e761c731..f724fe6196 100644 --- a/packages/vm/tests/api/EIPs/eip-3198-BaseFee.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3198-BaseFee.spec.ts @@ -73,7 +73,7 @@ tape('EIP3198 tests', (t) => { } ) const block = makeBlock(fee, tx, 2) - const vm = new VM({ common }) + const vm = await VM.create({ common }) await vm.stateManager.modifyAccountFields(sender, { balance: ETHER }) // Track stack diff --git a/packages/vm/tests/api/EIPs/eip-3529.spec.ts b/packages/vm/tests/api/EIPs/eip-3529.spec.ts index 2f9757c0f7..17c45918b3 100644 --- a/packages/vm/tests/api/EIPs/eip-3529.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3529.spec.ts @@ -112,7 +112,7 @@ tape('EIP-3529 tests', (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin, eips: [3529] }) t.test('should verify EIP test cases', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) let gasRefund: bigint let gasLeft: bigint @@ -159,7 +159,7 @@ tape('EIP-3529 tests', (t) => { }) t.test('should not refund selfdestructs', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = Transaction.fromTxData({ data: '0x6000ff', @@ -182,7 +182,7 @@ tape('EIP-3529 tests', (t) => { * Then, it resets all these 100 slots back to 0. This is to check if the * max gas refund is respected. */ - const vm = new VM({ common }) + const vm = await VM.create({ common }) let startGas: bigint let finalGas: bigint diff --git a/packages/vm/tests/api/EIPs/eip-3541.spec.ts b/packages/vm/tests/api/EIPs/eip-3541.spec.ts index 8615f5a978..115be0ffad 100644 --- a/packages/vm/tests/api/EIPs/eip-3541.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3541.spec.ts @@ -18,7 +18,7 @@ tape('EIP 3541 tests', (t) => { gasLimit: 1000000, }).sign(pkey) - let vm = new VM({ common }) + let vm = await VM.create({ common }) let result = await vm.runTx({ tx }) let created = result.createdAddress @@ -45,7 +45,7 @@ tape('EIP 3541 tests', (t) => { // check if we can deposit a contract on non-EIP3541 chains - vm = new VM({ common: commonNoEIP3541 }) + vm = await VM.create({ common: commonNoEIP3541 }) const tx2 = Transaction.fromTxData({ data: '0x7FEF0000000000000000000000000000000000000000000000000000000000000060005260206000F3', gasLimit: 1000000, @@ -68,7 +68,7 @@ tape('EIP 3541 tests', (t) => { gasLimit: 1000000, }).sign(pkey) - const vm = new VM({ common }) + const vm = await VM.create({ common }) let address: Address vm.on('step', (step: InterpreterStep) => { @@ -105,7 +105,7 @@ tape('EIP 3541 tests', (t) => { gasLimit: 1000000, }).sign(pkey) - const vm = new VM({ common }) + const vm = await VM.create({ common }) let address: Address vm.on('step', (step: InterpreterStep) => { diff --git a/packages/vm/tests/api/EIPs/eip-3607.spec.ts b/packages/vm/tests/api/EIPs/eip-3607.spec.ts index de7b56cb5a..ed0520718e 100644 --- a/packages/vm/tests/api/EIPs/eip-3607.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3607.spec.ts @@ -10,7 +10,7 @@ tape('EIP-3607 tests', (t) => { const precompileAddr = Address.fromString('0x0000000000000000000000000000000000000001') t.test('should reject txs from senders with deployed code when EIP is enabled', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) await vm.stateManager.putContractCode(precompileAddr, Buffer.alloc(32, 1)) const tx = Transaction.fromTxData({ gasLimit: 100000 }, { freeze: false }) tx.getSenderAddress = () => precompileAddr @@ -30,7 +30,7 @@ tape('EIP-3607 tests', (t) => { t.test( 'should not reject txs from senders with deployed code when EIP is not enabled', async (st) => { - const vm = new VM({ common: commonNoEIP3607 }) + const vm = await VM.create({ common: commonNoEIP3607 }) await vm.stateManager.putContractCode(precompileAddr, Buffer.alloc(32, 1)) const tx = Transaction.fromTxData({ gasLimit: 100000 }, { freeze: false }) tx.getSenderAddress = () => precompileAddr diff --git a/packages/vm/tests/api/EIPs/eip-3855.spec.ts b/packages/vm/tests/api/EIPs/eip-3855.spec.ts index 85361ebc4e..b493f86a4c 100644 --- a/packages/vm/tests/api/EIPs/eip-3855.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3855.spec.ts @@ -13,7 +13,7 @@ tape('EIP 3541 tests', (t) => { }) t.test('should correctly use push0 opcode', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) let stack: bigint[] vm.on('step', (e: InterpreterStep) => { @@ -35,7 +35,7 @@ tape('EIP 3541 tests', (t) => { }) t.test('should correctly use push0 to create a stack with stack limit length', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) let stack: bigint[] = [] vm.on('step', (e: InterpreterStep) => { @@ -60,7 +60,7 @@ tape('EIP 3541 tests', (t) => { }) t.test('should correctly use push0 to create a stack with stack limit + 1 length', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const depth = common.param('vm', 'stackLimit') + 1 @@ -74,7 +74,7 @@ tape('EIP 3541 tests', (t) => { }) t.test('push0 is not available if EIP3855 is not activated', async (st) => { - const vm = new VM({ common: commonNoEIP3855 }) + const vm = await VM.create({ common: commonNoEIP3855 }) const result = await vm.runCode({ code: Buffer.from('5F', 'hex'), diff --git a/packages/vm/tests/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts b/packages/vm/tests/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts index b4c0f89105..32a10ac890 100644 --- a/packages/vm/tests/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-4399-supplant-difficulty-opcode-with-prevrando.spec.ts @@ -8,7 +8,7 @@ import { bufferToBigInt } from 'ethereumjs-util' tape('EIP-4399 -> 0x44 (DIFFICULTY) should return PREVRANDAO', (t) => { t.test('should return the right values', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const genesis = await vm.blockchain.getLatestBlock() const header = { diff --git a/packages/vm/tests/api/buildBlock.spec.ts b/packages/vm/tests/api/buildBlock.spec.ts index da0fb872b7..820ab2df2d 100644 --- a/packages/vm/tests/api/buildBlock.spec.ts +++ b/packages/vm/tests/api/buildBlock.spec.ts @@ -17,7 +17,7 @@ tape('BlockBuilder', async (t) => { const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') await setBalance(vm, address) - const vmCopy = vm.copy() + const vmCopy = await vm.copy() const blockBuilder = await vm.buildBlock({ parentBlock: genesisBlock, @@ -260,7 +260,7 @@ tape('BlockBuilder', async (t) => { const genesisBlock = Block.genesis({ header: { gasLimit: 50000 } }, { common }) const blockchain = await Blockchain.create({ genesisBlock, common, validateConsensus: false }) const vm = await VM.create({ common, blockchain }) - const vmCopy = vm.copy() + const vmCopy = await vm.copy() const blockBuilder = await vm.buildBlock({ parentBlock: genesisBlock, @@ -290,7 +290,7 @@ tape('BlockBuilder', async (t) => { const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') await setBalance(vm, address) - const vmCopy = vm.copy() + const vmCopy = await vm.copy() const blockBuilder = await vm.buildBlock({ parentBlock: genesisBlock, diff --git a/packages/vm/tests/api/events.spec.ts b/packages/vm/tests/api/events.spec.ts index e7f0725b87..76d9a4150c 100644 --- a/packages/vm/tests/api/events.spec.ts +++ b/packages/vm/tests/api/events.spec.ts @@ -8,7 +8,7 @@ tape('VM events', (t) => { const privKey = toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07') t.test('should emit the Block before running it', async (st) => { - const vm = new VM() + const vm = await VM.create() let emitted vm.on('beforeBlock', (val: any) => { @@ -29,7 +29,7 @@ tape('VM events', (t) => { }) t.test('should emit a RunBlockResult after running a block', async (st) => { - const vm = new VM() + const vm = await VM.create() let emitted vm.on('afterBlock', (val: any) => { @@ -51,7 +51,7 @@ tape('VM events', (t) => { }) t.test('should emit the Transaction before running it', async (st) => { - const vm = new VM() + const vm = await VM.create() let emitted vm.on('beforeTx', (val: any) => { @@ -72,7 +72,7 @@ tape('VM events', (t) => { }) t.test('should emit RunTxResult after running a tx', async (st) => { - const vm = new VM() + const vm = await VM.create() const address = Address.fromPrivateKey(privKey) await vm.stateManager.putAccount(address, new Account(BigInt(0), BigInt(0x11111111))) let emitted: any @@ -95,7 +95,7 @@ tape('VM events', (t) => { }) t.test('should emit the Message before running it', async (st) => { - const vm = new VM() + const vm = await VM.create() const address = Address.fromPrivateKey(privKey) await vm.stateManager.putAccount(address, new Account(BigInt(0), BigInt(0x11111111))) let emitted: any @@ -119,7 +119,7 @@ tape('VM events', (t) => { }) t.test('should emit EVMResult after running a message', async (st) => { - const vm = new VM() + const vm = await VM.create() const address = Address.fromPrivateKey(privKey) await vm.stateManager.putAccount(address, new Account(BigInt(0), BigInt(0x11111111))) let emitted: any @@ -142,7 +142,7 @@ tape('VM events', (t) => { }) t.test('should emit InterpreterStep on each step', async (st) => { - const vm = new VM() + const vm = await VM.create() let lastEmitted: any vm.on('step', (val: any) => { @@ -166,7 +166,7 @@ tape('VM events', (t) => { }) t.test('should emit a NewContractEvent on new contracts', async (st) => { - const vm = new VM() + const vm = await VM.create() let emitted: any vm.on('newContract', (val: any) => { diff --git a/packages/vm/tests/api/evm/precompiles/06-ecadd.spec.ts b/packages/vm/tests/api/evm/precompiles/06-ecadd.spec.ts index 5491e3a1e7..ed2e2c8ff9 100644 --- a/packages/vm/tests/api/evm/precompiles/06-ecadd.spec.ts +++ b/packages/vm/tests/api/evm/precompiles/06-ecadd.spec.ts @@ -7,7 +7,7 @@ import { getPrecompile } from '../../../../src/evm/precompiles' tape('Precompiles: ECADD', (t) => { t.test('ECADD', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000006', 'hex')) const ECADD = getPrecompile(address, common) diff --git a/packages/vm/tests/api/evm/precompiles/07-ecmul.spec.ts b/packages/vm/tests/api/evm/precompiles/07-ecmul.spec.ts index 7982f9a95b..bd5704a262 100644 --- a/packages/vm/tests/api/evm/precompiles/07-ecmul.spec.ts +++ b/packages/vm/tests/api/evm/precompiles/07-ecmul.spec.ts @@ -7,7 +7,7 @@ import { getPrecompile } from '../../../../src/evm/precompiles' tape('Precompiles: ECMUL', (t) => { t.test('ECMUL', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000007', 'hex')) const ECMUL = getPrecompile(address, common) diff --git a/packages/vm/tests/api/evm/precompiles/08-ecpairing.spec.ts b/packages/vm/tests/api/evm/precompiles/08-ecpairing.spec.ts index c97cd3f7d9..ab3df7258b 100644 --- a/packages/vm/tests/api/evm/precompiles/08-ecpairing.spec.ts +++ b/packages/vm/tests/api/evm/precompiles/08-ecpairing.spec.ts @@ -7,7 +7,7 @@ import { getPrecompile } from '../../../../src/evm/precompiles' tape('Precompiles: ECPAIRING', (t) => { t.test('ECPAIRING', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000008', 'hex')) const ECPAIRING = getPrecompile(address, common) diff --git a/packages/vm/tests/api/evm/precompiles/hardfork.spec.ts b/packages/vm/tests/api/evm/precompiles/hardfork.spec.ts index bf7b13cd93..eb3bf1d4f5 100644 --- a/packages/vm/tests/api/evm/precompiles/hardfork.spec.ts +++ b/packages/vm/tests/api/evm/precompiles/hardfork.spec.ts @@ -21,7 +21,7 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING available in petersburg') } - let vm = new VM({ common: commonByzantium }) + let vm = await VM.create({ common: commonByzantium }) let result = await vm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), @@ -41,7 +41,7 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING available in petersburg') } - vm = new VM({ common: commonPetersburg }) + vm = await VM.create({ common: commonPetersburg }) result = await vm.runCall({ caller: Address.zero(), gasLimit: BigInt(0xffffffffff), @@ -61,7 +61,7 @@ tape('Precompiles: hardfork availability', (t) => { st.pass('ECPAIRING not available in homestead') } - vm = new VM({ common: commonHomestead }) + vm = await VM.create({ common: commonHomestead }) result = await vm.runCall({ caller: Address.zero(), diff --git a/packages/vm/tests/api/evm/stack.spec.ts b/packages/vm/tests/api/evm/stack.spec.ts index a1d316cd95..87e2de36d1 100644 --- a/packages/vm/tests/api/evm/stack.spec.ts +++ b/packages/vm/tests/api/evm/stack.spec.ts @@ -126,7 +126,7 @@ tape('Stack', (t) => { t.test('stack items should not change if they are DUPed', async (st) => { const caller = new Address(Buffer.from('00000000000000000000000000000000000000ee', 'hex')) const addr = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) - const vm = new VM() + const vm = await VM.create() const account = createAccount(BigInt(0), BigInt(0)) const code = '60008080808060013382F15060005260206000F3' const expectedReturnValue = setLengthLeft(bigIntToBuffer(BigInt(0)), 32) diff --git a/packages/vm/tests/api/index.spec.ts b/packages/vm/tests/api/index.spec.ts index 76cc37b1a0..70b1a47c94 100644 --- a/packages/vm/tests/api/index.spec.ts +++ b/packages/vm/tests/api/index.spec.ts @@ -32,8 +32,8 @@ import { Buffer } from 'buffer' // eslint-disable-line @typescript-eslint/no-unu */ tape('VM -> basic instantiation / boolean switches', (t) => { - t.test('should instantiate without params', (st) => { - const vm = new VM() + t.test('should instantiate without params', async (st) => { + const vm = await VM.create() st.ok(vm.stateManager) st.deepEqual( (vm.stateManager as DefaultStateManager)._trie.root, @@ -45,8 +45,7 @@ tape('VM -> basic instantiation / boolean switches', (t) => { }) t.test('should be able to activate precompiles', async (st) => { - const vm = new VM({ activatePrecompiles: true }) - await vm.init() + const vm = await VM.create({ activatePrecompiles: true }) st.notDeepEqual( (vm.stateManager as DefaultStateManager)._trie.root, KECCAK256_RLP, @@ -98,13 +97,12 @@ tape('VM -> common (chain, HFs, EIPs)', (t) => { t.test('should only accept valid chain and fork', async (st) => { let common = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Byzantium }) - let vm = new VM({ common }) - await vm.init() + let vm = await VM.create({ common }) st.equal((vm.stateManager as DefaultStateManager)._common.param('gasPrices', 'ecAdd'), 500) try { common = new Common({ chain: 'mainchain', hardfork: Hardfork.Homestead }) - vm = new VM({ common }) + vm = await VM.create({ common }) st.fail('should have failed for invalid chain') } catch (e: any) { st.ok(e.message.includes('not supported')) @@ -119,9 +117,12 @@ tape('VM -> common (chain, HFs, EIPs)', (t) => { return st.end() } const common = new Common({ chain: Chain.Mainnet, eips: [2537] }) - st.doesNotThrow(() => { - new VM({ common }) - }) + try { + await VM.create({ common }) + st.pass('did not throw') + } catch (error) { + st.fail('should not have thrown') + } st.end() }) @@ -180,8 +181,7 @@ tape('VM -> hardforkByBlockNumber, hardforkByTD, state (deprecated), blockchain' t.test('should work with trie (state) provided', async (st) => { const trie = new Trie() - const vm = new VM({ state: trie, activatePrecompiles: true }) - await vm.init() + const vm = await VM.create({ state: trie, activatePrecompiles: true }) st.notDeepEqual( (vm.stateManager as DefaultStateManager)._trie.root, KECCAK256_RLP, @@ -191,8 +191,7 @@ tape('VM -> hardforkByBlockNumber, hardforkByTD, state (deprecated), blockchain' }) t.test('should instantiate', async (st) => { - const vm = setupVM() - await vm.init() + const vm = await setupVM() st.deepEqual( (vm.stateManager as DefaultStateManager)._trie.root, KECCAK256_RLP, @@ -202,15 +201,14 @@ tape('VM -> hardforkByBlockNumber, hardforkByTD, state (deprecated), blockchain' }) t.test('should pass the correct Common object when copying the VM', async (st) => { - const vm = setupVM({ + const vm = await setupVM({ common: new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Byzantium }), }) - await vm.init() st.equal(vm._common.chainName(), 'ropsten') st.equal(vm._common.hardfork(), 'byzantium') - const copiedVM = vm.copy() + const copiedVM = await vm.copy() st.equal(copiedVM._common.chainName(), 'ropsten') st.equal(copiedVM._common.hardfork(), 'byzantium') diff --git a/packages/vm/tests/api/istanbul/eip-1108.spec.ts b/packages/vm/tests/api/istanbul/eip-1108.spec.ts index 0c421e1a29..ebdbb37cdd 100644 --- a/packages/vm/tests/api/istanbul/eip-1108.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-1108.spec.ts @@ -7,7 +7,7 @@ import { getPrecompile } from '../../../src/evm/precompiles' tape('Istanbul: EIP-1108 tests', (t) => { t.test('ECADD', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000006', 'hex')) const ECADD = getPrecompile(address, common) @@ -24,7 +24,7 @@ tape('Istanbul: EIP-1108 tests', (t) => { t.test('ECMUL', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000007', 'hex')) const ECMUL = getPrecompile(address, common) @@ -41,7 +41,7 @@ tape('Istanbul: EIP-1108 tests', (t) => { t.test('ECPAIRING', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const address = new Address(Buffer.from('0000000000000000000000000000000000000008', 'hex')) const ECPAIRING = getPrecompile(address, common) diff --git a/packages/vm/tests/api/istanbul/eip-1344.spec.ts b/packages/vm/tests/api/istanbul/eip-1344.spec.ts index 6b39079c4e..a8a4ca92b9 100644 --- a/packages/vm/tests/api/istanbul/eip-1344.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-1344.spec.ts @@ -23,7 +23,7 @@ tape('Istanbul: EIP-1344', async (t) => { for (const testCase of testCases) { const { chain, hardfork } = testCase const common = new Common({ chain, hardfork }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) try { const res = await vm.runCode(runCodeArgs) if (testCase.err) { diff --git a/packages/vm/tests/api/istanbul/eip-152.spec.ts b/packages/vm/tests/api/istanbul/eip-152.spec.ts index 2174cdaea1..249fd3cbe4 100644 --- a/packages/vm/tests/api/istanbul/eip-152.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-152.spec.ts @@ -78,7 +78,7 @@ const testCases = [ ] tape('Istanbul: EIP-152', (t) => { - t.test('Blake2f', (st) => { + t.test('Blake2f', async (st) => { // eslint-disable-next-line no-undef if ((globalThis).navigator?.userAgent.includes('Firefox')) { // TODO: investigate why this test hangs in karma with firefox @@ -86,7 +86,7 @@ tape('Istanbul: EIP-152', (t) => { } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) for (const testCase of failingTestCases) { st.comment(testCase.name) diff --git a/packages/vm/tests/api/istanbul/eip-1884.spec.ts b/packages/vm/tests/api/istanbul/eip-1884.spec.ts index 88956d1c6f..fefaede2f5 100644 --- a/packages/vm/tests/api/istanbul/eip-1884.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-1884.spec.ts @@ -24,7 +24,7 @@ tape('Istanbul: EIP-1884', async (t) => { for (const testCase of testCases) { const { chain, hardfork } = testCase const common = new Common({ chain, hardfork }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const balance = testCase.selfbalance ? BigInt(testCase.selfbalance) : undefined const account = createAccount(BigInt(0), balance) diff --git a/packages/vm/tests/api/istanbul/eip-2200.spec.ts b/packages/vm/tests/api/istanbul/eip-2200.spec.ts index bea79d4a53..6d47e76a63 100644 --- a/packages/vm/tests/api/istanbul/eip-2200.spec.ts +++ b/packages/vm/tests/api/istanbul/eip-2200.spec.ts @@ -48,7 +48,7 @@ tape('Istanbul: EIP-2200', async (t) => { for (const testCase of testCases) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = createAccount(BigInt(0), BigInt(0)) await vm.stateManager.putAccount(addr, account) diff --git a/packages/vm/tests/api/muirGlacier/index.spec.ts b/packages/vm/tests/api/muirGlacier/index.spec.ts index 99327b14e5..be8f021d1c 100644 --- a/packages/vm/tests/api/muirGlacier/index.spec.ts +++ b/packages/vm/tests/api/muirGlacier/index.spec.ts @@ -4,9 +4,9 @@ import Common, { Chain, Hardfork } from '@ethereumjs/common' import VM from '../../../src' tape('General MuirGlacier VM tests', (t) => { - t.test('should accept muirGlacier harfork option for supported chains', (st) => { + t.test('should accept muirGlacier harfork option for supported chains', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) st.ok(vm.stateManager) st.deepEqual((vm.stateManager)._trie.root, KECCAK256_RLP, 'it has default trie') st.end() diff --git a/packages/vm/tests/api/opcodes.spec.ts b/packages/vm/tests/api/opcodes.spec.ts index 86744fce01..c370e3fb5c 100644 --- a/packages/vm/tests/api/opcodes.spec.ts +++ b/packages/vm/tests/api/opcodes.spec.ts @@ -6,9 +6,9 @@ tape('VM -> getActiveOpcodes()', (t) => { const CHAINID = 0x46 //istanbul opcode const BEGINSUB = 0x5c // EIP-2315 opcode - t.test('should not expose opcodes from a follow-up HF (istanbul -> petersburg)', (st) => { + t.test('should not expose opcodes from a follow-up HF (istanbul -> petersburg)', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) st.equal( vm.getActiveOpcodes().get(CHAINID), undefined, @@ -17,9 +17,9 @@ tape('VM -> getActiveOpcodes()', (t) => { st.end() }) - t.test('should expose opcodes when HF is active (>= istanbul)', (st) => { + t.test('should expose opcodes when HF is active (>= istanbul)', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - let vm = new VM({ common }) + let vm = await VM.create({ common }) st.equal( vm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -27,7 +27,7 @@ tape('VM -> getActiveOpcodes()', (t) => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - vm = new VM({ common }) + vm = await VM.create({ common }) st.equal( vm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -37,9 +37,9 @@ tape('VM -> getActiveOpcodes()', (t) => { st.end() }) - t.test('should expose opcodes when EIP is active', (st) => { + t.test('should expose opcodes when EIP is active', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul, eips: [2315] }) - let vm = new VM({ common }) + let vm = await VM.create({ common }) st.equal( vm.getActiveOpcodes().get(BEGINSUB)!.name, 'BEGINSUB', @@ -47,7 +47,7 @@ tape('VM -> getActiveOpcodes()', (t) => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - vm = new VM({ common }) + vm = await VM.create({ common }) st.equal( vm.getActiveOpcodes().get(BEGINSUB), undefined, @@ -59,7 +59,7 @@ tape('VM -> getActiveOpcodes()', (t) => { t.test('should update opcodes on a hardfork change', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) common.setHardfork(Hardfork.Byzantium) st.equal( diff --git a/packages/vm/tests/api/runBlock.spec.ts b/packages/vm/tests/api/runBlock.spec.ts index 9b20b60b3d..afdc1cd84e 100644 --- a/packages/vm/tests/api/runBlock.spec.ts +++ b/packages/vm/tests/api/runBlock.spec.ts @@ -98,26 +98,26 @@ tape('runBlock() -> successful API parameter usage', async (t) => { } t.test('PoW block, unmodified options', async (st) => { - const vm = setupVM({ common }) + const vm = await setupVM({ common }) await simpleRun(vm, st) }) t.test('Uncle blocks, compute uncle rewards', async (st) => { - const vm = setupVM({ common }) + const vm = await setupVM({ common }) await uncleRun(vm, st) }) t.test('PoW block, Common custom chain (Common.custom() static constructor)', async (st) => { const customChainParams = { name: 'custom', chainId: 123, networkId: 678 } const common = Common.custom(customChainParams, { baseChain: 'mainnet', hardfork: 'berlin' }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) await simpleRun(vm, st) }) t.test('PoW block, Common custom chain (Common customChains constructor option)', async (st) => { const customChains = [testnet] const common = new Common({ chain: 'testnet', hardfork: Hardfork.Berlin, customChains }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) await simpleRun(vm, st) }) @@ -158,8 +158,8 @@ tape('runBlock() -> successful API parameter usage', async (t) => { ) } - const vm = new VM({ common: common1, hardforkByBlockNumber: true }) - const vm_noSelect = new VM({ common: common2 }) + const vm = await VM.create({ common: common1, hardforkByBlockNumber: true }) + const vm_noSelect = await VM.create({ common: common2 }) const txResultMuirGlacier = await vm.runBlock({ block: getBlock(common1), @@ -185,7 +185,7 @@ tape('runBlock() -> successful API parameter usage', async (t) => { }) tape('runBlock() -> API parameter usage/data errors', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) t.test('should fail when runTx fails', async (t) => { const blockRlp = testData.blocks[0].rlp @@ -200,7 +200,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { }) t.test('should fail when block gas limit higher than 2^63-1', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const block = Block.fromBlockData({ header: { @@ -215,7 +215,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { }) t.test('should fail when block validation fails', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const blockRlp = testData.blocks[0].rlp const block = Object.create(Block.fromRLPSerializedBlock(blockRlp)) @@ -230,7 +230,7 @@ tape('runBlock() -> API parameter usage/data errors', async (t) => { }) t.test('should fail when tx gas limit higher than block gas limit', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const blockRlp = testData.blocks[0].rlp const block = Object.create(Block.fromRLPSerializedBlock(blockRlp)) @@ -256,7 +256,7 @@ tape('runBlock() -> runtime behavior', async (t) => { t.test('DAO fork behavior', async (t) => { const common = getDAOCommon(1) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const block1: any = rlp.decode(testData.blocks[0].rlp) // edit extra data of this block to "dao-hard-fork" @@ -307,7 +307,7 @@ tape('runBlock() -> runtime behavior', async (t) => { t.test('should allocate to correct clique beneficiary', async (t) => { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Istanbul }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const signer = { address: new Address(Buffer.from('0b90087d864e82a284dca15923f3776de6bb016f', 'hex')), @@ -374,7 +374,7 @@ async function runBlockAndGetAfterBlockEvent( } tape('should correctly reflect generated fields', async (t) => { - const vm = new VM() + const vm = await VM.create() // We create a block with a receiptTrie and transactionsTrie // filled with 0s and no txs. Once we run it we should @@ -398,7 +398,7 @@ tape('should correctly reflect generated fields', async (t) => { async function runWithHf(hardfork: string) { const common = new Common({ chain: Chain.Mainnet, hardfork }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const blockRlp = testData.blocks[0].rlp const block = Block.fromRLPSerializedBlock(blockRlp, { common }) @@ -471,7 +471,7 @@ tape('runBlock() -> tx types', async (t) => { t.test('legacy tx', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') await setBalance(vm, address) @@ -487,7 +487,7 @@ tape('runBlock() -> tx types', async (t) => { t.test('access list tx', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') await setBalance(vm, address) @@ -506,7 +506,7 @@ tape('runBlock() -> tx types', async (t) => { t.test('fee market tx', async (st) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const vm = setupVM({ common }) + const vm = await setupVM({ common }) const address = Address.fromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') await setBalance(vm, address) diff --git a/packages/vm/tests/api/runBlockchain.spec.ts b/packages/vm/tests/api/runBlockchain.spec.ts index 020d0424bf..68c2d9262d 100644 --- a/packages/vm/tests/api/runBlockchain.spec.ts +++ b/packages/vm/tests/api/runBlockchain.spec.ts @@ -17,17 +17,23 @@ tape('runBlockchain', (t) => { const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart }) t.test('should run without a blockchain parameter', async (st) => { - const vm = setupVM({ common }) - st.doesNotThrow(async function () { + const vm = await setupVM({ common }) + try { await vm.runBlockchain() - }) + st.pass('did not throw') + } catch (error) { + st.fail('should not have thrown') + } }) t.test('should run without blocks', async (st) => { - const vm = setupVM({ common }) - st.doesNotThrow(async function () { + const vm = await setupVM({ common }) + try { await vm.runBlockchain() - }) + st.pass('did not throw') + } catch (error) { + st.fail('should not have thrown') + } }) t.test('should run with genesis block', async (st) => { @@ -41,7 +47,7 @@ tape('runBlockchain', (t) => { validateConsensus: false, genesisBlock, }) - const vm = setupVM({ genesisBlock, blockchain }) + const vm = await setupVM({ genesisBlock, blockchain }) st.ok(blockchain.meta.genesis, 'genesis should be set for blockchain') @@ -62,8 +68,7 @@ tape('runBlockchain', (t) => { const blockRlp = Buffer.from(testData.blocks[0].rlp.slice(2), 'hex') const block = Block.fromRLPSerializedBlock(blockRlp, { common }) - const vm = setupVM({ common, genesisBlock }) - await vm.init() + const vm = await setupVM({ common, genesisBlock }) st.equal(vm.blockchain.meta.genesis?.toString('hex'), testData.genesisBlockHeader.hash.slice(2)) @@ -94,8 +99,7 @@ tape('runBlockchain', (t) => { const blockRlp = toBuffer(testData.blocks[0].rlp) const block = Block.fromRLPSerializedBlock(blockRlp, { common }) - const vm = setupVM({ common, genesisBlock }) - await vm.init() + const vm = await setupVM({ common, genesisBlock }) st.equal(vm.blockchain.meta.genesis?.toString('hex'), testData.genesisBlockHeader.hash.slice(2)) @@ -115,7 +119,7 @@ tape('runBlockchain', (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) const genesisBlock = Block.genesis(undefined, { common }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ db: blockchainDB, common, validateBlocks: false, @@ -123,7 +127,7 @@ tape('runBlockchain', (t) => { genesisBlock, }) - const vm = setupVM({ genesisBlock, blockchain }) + const vm = await setupVM({ genesisBlock, blockchain }) // Produce error on the third time runBlock is called let runBlockInvocations = 0 diff --git a/packages/vm/tests/api/runCall.spec.ts b/packages/vm/tests/api/runCall.spec.ts index 01a7e8db10..3487adebf9 100644 --- a/packages/vm/tests/api/runCall.spec.ts +++ b/packages/vm/tests/api/runCall.spec.ts @@ -27,7 +27,7 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn ) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const code = '3460008080F560005260206000F3' /* code: remarks: (top of the stack is at the zero index) @@ -86,10 +86,10 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { Buffer.from('00000000000000000000000000000000000000ff', 'hex') ) // contract address // setup the vm - const vmByzantium = new VM({ + const vmByzantium = await VM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }), }) - const vmConstantinople = new VM({ + const vmConstantinople = await VM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }), }) const code = '600160011B00' @@ -134,8 +134,8 @@ tape('Ensure that precompile activation creates non-empty accounts', async (t) = ) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vmNotActivated = new VM({ common: common }) - const vmActivated = new VM({ common: common, activatePrecompiles: true }) + const vmNotActivated = await VM.create({ common: common }) + const vmActivated = await VM.create({ common: common, activatePrecompiles: true }) const code = '6000808080347300000000000000000000000000000000000000045AF100' /* idea: call the Identity precompile with nonzero value in order to trigger "callNewAccount" for the non-activated VM and do not deduct this @@ -181,7 +181,7 @@ tape('Ensure that Istanbul sstoreCleanRefundEIP2200 gas is applied correctly', a const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const code = '61000260005561000160005500' /* idea: store the original value in the storage slot, except it is now a 1-length buffer instead of a 32-length buffer @@ -232,7 +232,7 @@ tape('ensure correct gas for pre-constantinople sstore', async (t) => { const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // push 1 push 0 sstore stop const code = '600160015500' @@ -259,7 +259,7 @@ tape('ensure correct gas for calling non-existent accounts in homestead', async const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // code to call 0x00..00dd, which does not exist const code = '6000600060006000600060DD61FFFF5A03F100' @@ -290,7 +290,7 @@ tape( const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // code to call back into the calling account (0x00..00EE), // but using too much memory const code = '61FFFF60FF60006000600060EE6000F200' @@ -320,7 +320,7 @@ tape('ensure selfdestruct pays for creating new accounts', async (t) => { const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.TangerineWhistle }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // code to call 0x00..00fe, with the GAS opcode used as gas // this cannot be paid, since we also have to pay for CALL (40 gas) // this should thus go OOG @@ -350,7 +350,7 @@ tape('ensure that sstores pay for the right gas costs pre-byzantium', async (t) const address = new Address(Buffer.from('00000000000000000000000000000000000000ff', 'hex')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // code to call 0x00..00fe, with the GAS opcode used as gas // this cannot be paid, since we also have to pay for CALL (40 gas) // this should thus go OOG @@ -420,7 +420,7 @@ tape( const emptyBuffer = Buffer.from('') // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const code = '60008080F060005500' /* This simple code tries to create an empty contract and then stores the address of the contract in the zero slot. @@ -474,7 +474,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { const caller = new Address(Buffer.from('1a02a619e51cc5f8a2a61d2a60f6c80476ee8ead', 'hex')) // caller addres // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const code = '3034526020600760203460045afa602034343e604034f3' const account = await vm.stateManager.getAccount(caller) @@ -508,7 +508,7 @@ tape('Ensure that IDENTITY precompile copies the memory', async (t) => { tape('Throws on negative call value', async (t) => { // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) // setup the call arguments const runCallArgs = { diff --git a/packages/vm/tests/api/runCode.spec.ts b/packages/vm/tests/api/runCode.spec.ts index 2fd4bc6c65..0f4543f20d 100644 --- a/packages/vm/tests/api/runCode.spec.ts +++ b/packages/vm/tests/api/runCode.spec.ts @@ -18,42 +18,43 @@ const testCases = [ { code: [STOP], resultPC: 1 }, ] -tape('VM.runCode: initial program counter', (t) => { - const vm = new VM() - - testCases.forEach((testData, i) => { - t.test('should start the execution at the specified pc or 0 #' + i.toString(), async (st) => { - const runCodeArgs = { - code: Buffer.from(testData.code.join(''), 'hex'), - pc: testData.pc, - gasLimit: BigInt(0xffff), - } +tape('VM.runCode: initial program counter', async (t) => { + const vm = await VM.create() - let err - try { - const result = await vm.runCode(runCodeArgs) - if (testData.resultPC !== undefined) { - t.equals(result.runState?.programCounter, testData.resultPC, 'runstate.programCounter') - } - } catch (e: any) { - err = e - } + for (const [i, testData] of testCases.entries()) { + const runCodeArgs = { + code: Buffer.from(testData.code.join(''), 'hex'), + pc: testData.pc, + gasLimit: BigInt(0xffff), + } - if (testData.error) { - err = err ? err.message : 'no error thrown' - st.equal(err, testData.error, 'error message should match') - err = false + let err + try { + const result = await vm.runCode(runCodeArgs) + if (testData.resultPC !== undefined) { + t.equal( + result.runState?.programCounter, + testData.resultPC, + `should start the execution at the specified pc or 0, testCases[${i}]` + ) } + } catch (e: any) { + err = e + } - st.assert(!err) - st.end() - }) - }) + if (testData.error) { + err = err ? err.message : 'no error thrown' + t.equal(err, testData.error, 'error message should match') + err = false + } + + t.assert(!err) + } }) tape('VM.runCode: interpreter', (t) => { t.test('should return a VmError as an exceptionError on the result', async (st) => { - const vm = new VM() + const vm = await VM.create() const INVALID_opcode = 'fe' const runCodeArgs = { @@ -77,7 +78,7 @@ tape('VM.runCode: interpreter', (t) => { stateManager.putContractStorage = (..._args) => { throw new Error('Test') } - const vm = new VM({ stateManager }) + const vm = await VM.create({ stateManager }) const SSTORE = '55' const runCodeArgs = { @@ -97,7 +98,7 @@ tape('VM.runCode: interpreter', (t) => { tape('VM.runCode: RunCodeOptions', (t) => { t.test('should throw on negative value args', async (st) => { - const vm = new VM() + const vm = await VM.create() const runCodeArgs = { value: BigInt(-10), diff --git a/packages/vm/tests/api/runTx.spec.ts b/packages/vm/tests/api/runTx.spec.ts index 16944c1f38..a477da6318 100644 --- a/packages/vm/tests/api/runTx.spec.ts +++ b/packages/vm/tests/api/runTx.spec.ts @@ -45,11 +45,11 @@ tape('runTx() -> successful API parameter usage', async (t) => { t.test('simple run (unmodified options)', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - let vm = new VM({ common }) + let vm = await VM.create({ common }) await simpleRun(vm, 'mainnet (PoW), london HF, default SM - should run without errors', st) common = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.London }) - vm = new VM({ common }) + vm = await VM.create({ common }) await simpleRun(vm, 'rinkeby (PoA), london HF, default SM - should run without errors', st) st.end() @@ -57,7 +57,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { t.test('should use passed in blockGasUsed to generate tx receipt', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, 0, true) @@ -76,7 +76,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { t.test('Legacy Transaction with HF set to pre-Berlin', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, 0, true) @@ -97,7 +97,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { 'custom block (block option), disabled block gas limit validation (skipBlockGasLimitValidation: true)', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const privateKey = Buffer.from( 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', @@ -179,7 +179,7 @@ tape('runTx() -> successful API parameter usage', async (t) => { tape('runTx() -> API parameter usage/data errors', (t) => { t.test('Typed Transaction with HF set to pre-Berlin', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction( new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }), @@ -206,7 +206,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { }) t.test('simple run (reportAccessList option)', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, 0, true) @@ -225,7 +225,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { t.test('run without signature', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, false) try { await vm.runTx({ tx }) @@ -239,7 +239,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { t.test('run with insufficient funds', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true) try { await vm.runTx({ tx }) @@ -250,7 +250,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { // EIP-1559 // Fail if signer.balance < gas_limit * max_fee_per_gas - const vm = new VM({ common }) + const vm = await VM.create({ common }) let tx = getTransaction(vm._common, 2, true) as FeeMarketEIP1559Transaction const address = tx.getSenderAddress() tx = Object.create(tx) @@ -271,7 +271,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { }) t.test('run with insufficient eip1559 funds', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() const account = await vm.stateManager.getAccount(address) @@ -291,7 +291,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { }) t.test('should throw on wrong nonces', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(common, 2, true, '0x0', false) const address = tx.getSenderAddress() const account = await vm.stateManager.getAccount(address) @@ -311,7 +311,7 @@ tape('runTx() -> API parameter usage/data errors', (t) => { // EIP-1559 // Fail if transaction.maxFeePerGas < block.baseFeePerGas for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true) const block = Block.fromBlockData({ header: { baseFeePerGas: 100000 } }, { common }) try { @@ -332,7 +332,7 @@ tape('runTx() -> runtime behavior', async (t) => { t.test('storage cache', async (t) => { for (const txType of TRANSACTION_TYPES) { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const privateKey = Buffer.from( 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex' @@ -381,7 +381,7 @@ tape('runTx() -> runtime behavior', async (t) => { tape('runTx() -> runtime errors', async (t) => { t.test('account balance overflows (call)', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true, '0x01') const caller = tx.getSenderAddress() @@ -409,7 +409,7 @@ tape('runTx() -> runtime errors', async (t) => { t.test('account balance overflows (create)', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true, '0x01', true) const caller = tx.getSenderAddress() @@ -443,7 +443,7 @@ tape('runTx() -> runtime errors', async (t) => { tape('runTx() -> API return values', async (t) => { t.test('simple run, common return values', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true) const caller = tx.getSenderAddress() @@ -475,7 +475,7 @@ tape('runTx() -> API return values', async (t) => { t.test('simple run, runTx default return values', async (t) => { for (const txType of TRANSACTION_TYPES) { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const tx = getTransaction(vm._common, txType.type, true) const caller = tx.getSenderAddress() @@ -558,7 +558,7 @@ tape('runTx() -> consensus bugs', async (t) => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.SpuriousDragon }) common.setHardforkByBlockNumber(2772981) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const addr = Address.fromString('0xd3563d8f19a85c95beab50901fd59ca4de69174c') const acc = await vm.stateManager.getAccount(addr) @@ -596,7 +596,7 @@ tape('runTx() -> consensus bugs', async (t) => { } const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const addr = Address.fromPrivateKey(pkey) const acc = await vm.stateManager.getAccount(addr) @@ -615,7 +615,7 @@ tape('runTx() -> consensus bugs', async (t) => { tape('runTx() -> RunTxOptions', (t) => { t.test('should throw on negative value args', async (t) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) await setBalance(vm, Address.zero(), BigInt(10000000000)) for (const txType of TRANSACTION_TYPES) { const tx = getTransaction(vm._common, txType.type, false) diff --git a/packages/vm/tests/api/state/accountExists.spec.ts b/packages/vm/tests/api/state/accountExists.spec.ts index 388dcbcbb9..538d0932ee 100644 --- a/packages/vm/tests/api/state/accountExists.spec.ts +++ b/packages/vm/tests/api/state/accountExists.spec.ts @@ -15,7 +15,7 @@ tape('correctly apply new account gas fee on pre-Spurious Dragon hardforks', asy ) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const code = '606060405236156101065760e060020a600035046305fefda7811461013d57806306fdde031461016357806318160ddd146101c057806323b872dd146101c95780632e1a7d4d146101fb578063313ce5671461021e5780633177029f1461022a57806347f1d8d7146102d25780634b750334146102db57806370a08231146102e45780638620410b146102fc5780638da5cb5b1461030557806395d89b4114610317578063a6f2ae3a14610372578063a9059cbb146103a2578063b414d4b6146103d1578063c91d956c146103ec578063dc3080f21461040f578063dd62ed3e14610434578063e4849b3214610459578063e724529c1461048f578063f2fde38b146104b5575b6104d860055434111561013b5760055433600160a060020a031660009081526008602052604090208054349290920490910190555b565b6104d8600435602435600054600160a060020a0390811633919091161461084157610002565b60408051600180546020600282841615610100026000190190921691909104601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b61054860065481565b610548600435602435604435600160a060020a038316600090815260086020526040812054829010156106f657610002565b6104d8600435600054600160a060020a0390811633919091161461091957610002565b61055a60035460ff1681565b610548600435602435600160a060020a033381166000818152600a60209081526040808320878616808552925280832086905580517f4889ca880000000000000000000000000000000000000000000000000000000081526004810194909452602484018690523090941660448401529251909285929091634889ca88916064808201928792909190829003018183876161da5a03f115610002575060019695505050505050565b61054860075481565b61054860045481565b61054860043560086020526000908152604090205481565b61054860055481565b610571600054600160a060020a031681565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b60055430600160a060020a03166000908152600860205260409020546104d8913404908190101561084c57610002565b6104d8600435602435600160a060020a033316600090815260086020526040902054819010156105f157610002565b61054860043560096020526000908152604090205460ff1681565b6104d8600435600054600160a060020a039081163391909116146105e357610002565b600b602090815260043560009081526040808220909252602435815220546105489081565b600a602090815260043560009081526040808220909252602435815220546105489081565b6104d86004355b806008600050600033600160a060020a031681526020019081526020016000206000505410156108a657610002565b6104d8600435602435600054600160a060020a039081163391909116146107e157610002565b6104d8600435600054600160a060020a0390811633919091161461058e57610002565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6000805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b820191906000526020600020905b8154815290600101906020018083116105be57829003601f168201915b505050505081565b66038d7ea4c6800002600755565b600160a060020a038216600090815260086020526040902054818101101561061857610002565b600160a060020a03331660009081526009602052604090205460ff161561063e57610002565b600160a060020a0333811660008181526008602090815260408083208054879003905593861680835291849020805486019055835185815293519193600080516020610940833981519152929081900390910190a3600754600160a060020a0383163110156106c4576007546004546106c491600160a060020a03851631900304610460565b604051600454600754600160a060020a038516926000928431909203919091049082818181858883f150505050505050565b600160a060020a038316600090815260086020526040902054808301101561071d57610002565b600160a060020a038481166000818152600a602090815260408083203390951680845294825280832054938352600b825280832094835293905291909120548301111561076957610002565b600160a060020a03848116600081815260086020908152604080832080548890039055878516808452818420805489019055848452600b835281842033909616845294825291829020805487019055815186815291516000805160206109408339815191529281900390910190a35060019392505050565b600160a060020a038216600081815260096020908152604091829020805460ff1916851790558151928352820183905280517f48335238b4855f35377ed80f164e8c6f3c366e54ac00b96a6402d4a9814a03a59281900390910190a15050565b600491909155600555565b600160a060020a03338116600081815260086020908152604080832080548701905530909416808352918490208054869003905583518581529351929391926000805160206109408339815191529281900390910190a350565b30600160a060020a039081166000908152600860205260408082208054850190553390921680825282822080548590039055915160045484029082818181858883f15084815260405130600160a060020a031694935060008051602061094083398151915292509081900360200190a350565b60008054604051600160a060020a03919091169190839082818181858883f150505050505056ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' @@ -56,7 +56,7 @@ tape( ) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const code = '606060405236156101065760e060020a600035046305fefda7811461013d57806306fdde031461016357806318160ddd146101c057806323b872dd146101c95780632e1a7d4d146101fb578063313ce5671461021e5780633177029f1461022a57806347f1d8d7146102d25780634b750334146102db57806370a08231146102e45780638620410b146102fc5780638da5cb5b1461030557806395d89b4114610317578063a6f2ae3a14610372578063a9059cbb146103a2578063b414d4b6146103d1578063c91d956c146103ec578063dc3080f21461040f578063dd62ed3e14610434578063e4849b3214610459578063e724529c1461048f578063f2fde38b146104b5575b6104d860055434111561013b5760055433600160a060020a031660009081526008602052604090208054349290920490910190555b565b6104d8600435602435600054600160a060020a0390811633919091161461084157610002565b60408051600180546020600282841615610100026000190190921691909104601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b61054860065481565b610548600435602435604435600160a060020a038316600090815260086020526040812054829010156106f657610002565b6104d8600435600054600160a060020a0390811633919091161461091957610002565b61055a60035460ff1681565b610548600435602435600160a060020a033381166000818152600a60209081526040808320878616808552925280832086905580517f4889ca880000000000000000000000000000000000000000000000000000000081526004810194909452602484018690523090941660448401529251909285929091634889ca88916064808201928792909190829003018183876161da5a03f115610002575060019695505050505050565b61054860075481565b61054860045481565b61054860043560086020526000908152604090205481565b61054860055481565b610571600054600160a060020a031681565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526104da93908301828280156105db5780601f106105b0576101008083540402835291602001916105db565b60055430600160a060020a03166000908152600860205260409020546104d8913404908190101561084c57610002565b6104d8600435602435600160a060020a033316600090815260086020526040902054819010156105f157610002565b61054860043560096020526000908152604090205460ff1681565b6104d8600435600054600160a060020a039081163391909116146105e357610002565b600b602090815260043560009081526040808220909252602435815220546105489081565b600a602090815260043560009081526040808220909252602435815220546105489081565b6104d86004355b806008600050600033600160a060020a031681526020019081526020016000206000505410156108a657610002565b6104d8600435602435600054600160a060020a039081163391909116146107e157610002565b6104d8600435600054600160a060020a0390811633919091161461058e57610002565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6000805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b820191906000526020600020905b8154815290600101906020018083116105be57829003601f168201915b505050505081565b66038d7ea4c6800002600755565b600160a060020a038216600090815260086020526040902054818101101561061857610002565b600160a060020a03331660009081526009602052604090205460ff161561063e57610002565b600160a060020a0333811660008181526008602090815260408083208054879003905593861680835291849020805486019055835185815293519193600080516020610940833981519152929081900390910190a3600754600160a060020a0383163110156106c4576007546004546106c491600160a060020a03851631900304610460565b604051600454600754600160a060020a038516926000928431909203919091049082818181858883f150505050505050565b600160a060020a038316600090815260086020526040902054808301101561071d57610002565b600160a060020a038481166000818152600a602090815260408083203390951680845294825280832054938352600b825280832094835293905291909120548301111561076957610002565b600160a060020a03848116600081815260086020908152604080832080548890039055878516808452818420805489019055848452600b835281842033909616845294825291829020805487019055815186815291516000805160206109408339815191529281900390910190a35060019392505050565b600160a060020a038216600081815260096020908152604091829020805460ff1916851790558151928352820183905280517f48335238b4855f35377ed80f164e8c6f3c366e54ac00b96a6402d4a9814a03a59281900390910190a15050565b600491909155600555565b600160a060020a03338116600081815260086020908152604080832080548701905530909416808352918490208054869003905583518581529351929391926000805160206109408339815191529281900390910190a350565b30600160a060020a039081166000908152600860205260408082208054850190553390921680825282822080548590039055915160045484029082818181858883f15084815260405130600160a060020a031694935060008051602061094083398151915292509081900360200190a350565b60008054604051600160a060020a03919091169190839082818181858883f150505050505056ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' const existingAddress = caller diff --git a/packages/vm/tests/api/utils.ts b/packages/vm/tests/api/utils.ts index 0026404c0a..36459bd98b 100644 --- a/packages/vm/tests/api/utils.ts +++ b/packages/vm/tests/api/utils.ts @@ -19,11 +19,11 @@ export async function setBalance(vm: VM, address: Address, balance = BigInt(1000 await vm.stateManager.commit() } -export function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { +export async function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { const db = level() const { common, genesisBlock } = opts if (!opts.blockchain) { - opts.blockchain = new Blockchain({ + opts.blockchain = await Blockchain.create({ db, validateBlocks: false, validateConsensus: false, @@ -31,9 +31,10 @@ export function setupVM(opts: VMOpts & { genesisBlock?: Block } = {}) { genesisBlock, }) } - return new VM({ + const vm = await VM.create({ ...opts, }) + return vm } export function getTransaction( diff --git a/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts b/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts index f3cbcc8771..2a845304ec 100644 --- a/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/tests/tester/runners/BlockchainTestsRunner.ts @@ -55,7 +55,7 @@ export default async function runBlockchainTest(options: any, testData: any, t: t.ok(genesisBlock.serialize().equals(rlp), 'correct genesis RLP') } - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ db: blockchainDB, common, validateBlocks: true, @@ -76,16 +76,12 @@ export default async function runBlockchainTest(options: any, testData: any, t: const begin = Date.now() - const vm = new VM({ + const vm = await VM.create({ state, blockchain, common, }) - // Need to await the init promise: in some tests, we do not run the iterator (which awaits the initPromise) - // If the initPromise does not finish, the `rawHead` of `blockchain.meta()` is still `undefined`. - await blockchain.initPromise - // set up pre-state await setupPreConditions(vm.stateManager, testData) diff --git a/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts index 4ae409227e..ea6059963a 100644 --- a/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/tests/tester/runners/GeneralStateTestsRunner.ts @@ -69,7 +69,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { const common = options.common const state = new Trie() - const vm = new VM({ state, common }) + const vm = await VM.create({ state, common }) await setupPreConditions(vm.stateManager, testData) From c9e214d38f12b3bcaede18167b8e97b1c107a7dd Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 19:34:36 -0700 Subject: [PATCH 3/9] client: update to new async changes --- packages/client/lib/blockchain/chain.ts | 2 +- packages/client/lib/client.ts | 2 +- packages/client/lib/execution/vmexecution.ts | 1 + packages/client/lib/miner/miner.ts | 2 +- packages/client/lib/rpc/modules/engine.ts | 4 ++-- packages/client/lib/rpc/modules/eth.ts | 18 ++++++++++-------- packages/client/lib/util/debug.ts | 2 +- packages/client/test/blockchain/chain.spec.ts | 4 ++-- .../client/test/integration/peerpool.spec.ts | 2 +- packages/client/test/rpc/eth/call.spec.ts | 4 +++- .../client/test/rpc/eth/estimateGas.spec.ts | 4 +++- packages/client/test/rpc/helpers.ts | 2 +- .../test/sync/execution/vmexecution.spec.ts | 2 +- 13 files changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/client/lib/blockchain/chain.ts b/packages/client/lib/blockchain/chain.ts index f619473422..25fc0e74f0 100644 --- a/packages/client/lib/blockchain/chain.ts +++ b/packages/client/lib/blockchain/chain.ts @@ -183,7 +183,7 @@ export class Chain { } await this.blockchain.db.open() - await this.blockchain.initPromise + await (this.blockchain as any)._init() this.opened = true await this.update() diff --git a/packages/client/lib/client.ts b/packages/client/lib/client.ts index 4c15aed896..f7ca614e64 100644 --- a/packages/client/lib/client.ts +++ b/packages/client/lib/client.ts @@ -187,7 +187,7 @@ export default class EthereumClient { async executeBlocks(first: number, last: number, txHashes: string[]) { this.config.logger.info('Preparing for block execution (debug mode, no services started)...') if (!this.execution) throw new Error('executeBlocks requires execution') - const vm = this.execution.vm.copy() + const vm = await this.execution.vm.copy() for (let blockNumber = first; blockNumber <= last; blockNumber++) { const block = await vm.blockchain.getBlock(blockNumber) diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 14bb0051af..ac7cd85bf8 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -55,6 +55,7 @@ export class VMExecution extends Execution { * Initializes VM execution. Must be called before run() is called */ async open(): Promise { + await this.vm.init() const headBlock = await this.vm.blockchain.getIteratorHead() const { number } = headBlock.header const td = await this.vm.blockchain.getTotalDifficulty(headBlock.header.hash()) diff --git a/packages/client/lib/miner/miner.ts b/packages/client/lib/miner/miner.ts index 1be58e2b98..85fcd47fc9 100644 --- a/packages/client/lib/miner/miner.ts +++ b/packages/client/lib/miner/miner.ts @@ -203,7 +203,7 @@ export class Miner { // Use a copy of the vm to not modify the existing state. // The state will be updated when the newly assembled block // is inserted into the canonical chain. - const vmCopy = this.execution.vm.copy() + const vmCopy = await this.execution.vm.copy() // Set the state root to ensure the resulting state // is based on the parent block's state diff --git a/packages/client/lib/rpc/modules/engine.ts b/packages/client/lib/rpc/modules/engine.ts index 706dff62bf..f631699928 100644 --- a/packages/client/lib/rpc/modules/engine.ts +++ b/packages/client/lib/rpc/modules/engine.ts @@ -407,7 +407,7 @@ export class Engine { return response } - const vmCopy = this.vm.copy() + const vmCopy = await this.vm.copy() const vmHead = this.chain.headers.latest! let blocks: Block[] try { @@ -604,7 +604,7 @@ export class Engine { if (payloadAttributes) { const { timestamp, prevRandao, suggestedFeeRecipient } = payloadAttributes const parentBlock = this.chain.blocks.latest! - const payloadId = await this.pendingBlock.start(this.vm.copy(), parentBlock, { + const payloadId = await this.pendingBlock.start(await this.vm.copy(), parentBlock, { timestamp, mixHash: prevRandao, coinbase: suggestedFeeRecipient, diff --git a/packages/client/lib/rpc/modules/eth.ts b/packages/client/lib/rpc/modules/eth.ts index c763e19656..4779ed9c51 100644 --- a/packages/client/lib/rpc/modules/eth.ts +++ b/packages/client/lib/rpc/modules/eth.ts @@ -455,7 +455,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) if (!transaction.gas) { @@ -511,7 +511,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) if (!transaction.gas) { @@ -553,7 +553,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) const account = await vm.stateManager.getAccount(address) return bigIntToHex(account.balance) @@ -622,7 +622,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) @@ -645,7 +645,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) @@ -693,7 +693,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() await vm.stateManager.setStateRoot(block.header.stateRoot) const address = Address.fromString(addressHex) @@ -761,7 +761,9 @@ export class Eth { : (tx as Transaction).gasPrice // Run tx through copied vm to get tx gasUsed and createdAddress - const runBlockResult = await this._vm!.copy().runBlock({ + const runBlockResult = await ( + await this._vm!.copy() + ).runBlock({ block, root: parentBlock.header.stateRoot, skipBlockValidation: true, @@ -956,7 +958,7 @@ export class Eth { throw new Error('missing vm') } - const vm = this._vm.copy() + const vm = await this._vm.copy() if (!('getProof' in vm.stateManager)) { throw new Error('getProof RPC method not supported with the StateManager provided') diff --git a/packages/client/lib/util/debug.ts b/packages/client/lib/util/debug.ts index 17edb4304b..d9db31a7b5 100644 --- a/packages/client/lib/util/debug.ts +++ b/packages/client/lib/util/debug.ts @@ -54,7 +54,7 @@ const main = async () => { validateBlocks: true, validateConsensus: false, }) - const vm = new VM({ stateManager, blockchain, common }) + const vm = await VM.create({ stateManager, blockchain, common }) await vm.runBlock({ block }) } diff --git a/packages/client/test/blockchain/chain.spec.ts b/packages/client/test/blockchain/chain.spec.ts index e2956006a6..b0259da405 100644 --- a/packages/client/test/blockchain/chain.spec.ts +++ b/packages/client/test/blockchain/chain.spec.ts @@ -42,7 +42,7 @@ tape('[Chain]', (t) => { }) t.test('should detect unopened chain', async (t) => { - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false, }) @@ -88,7 +88,7 @@ tape('[Chain]', (t) => { t.test('should add block to chain', async (t) => { // TODO: add test cases with activated block validation - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false, }) diff --git a/packages/client/test/integration/peerpool.spec.ts b/packages/client/test/integration/peerpool.spec.ts index 7b9b759e15..b3ddb4b5b9 100644 --- a/packages/client/test/integration/peerpool.spec.ts +++ b/packages/client/test/integration/peerpool.spec.ts @@ -63,7 +63,7 @@ tape('[Integration:PeerPool]', async (t) => { t.test('should handle peer messages', async (t) => { const config = new Config({ transports: [] }) - const blockchain = new Blockchain({ + const blockchain = await Blockchain.create({ validateBlocks: false, validateConsensus: false, }) diff --git a/packages/client/test/rpc/eth/call.spec.ts b/packages/client/test/rpc/eth/call.spec.ts index aaadd950ea..21b6e565f8 100644 --- a/packages/client/test/rpc/eth/call.spec.ts +++ b/packages/client/test/rpc/eth/call.spec.ts @@ -82,7 +82,9 @@ tape(`${method}: call with valid arguments`, async (t) => { estimateTx.getSenderAddress = () => { return address } - const { execResult } = await vm.copy().runTx({ + const { execResult } = await ( + await vm.copy() + ).runTx({ tx: estimateTx, skipNonce: true, skipBalance: true, diff --git a/packages/client/test/rpc/eth/estimateGas.spec.ts b/packages/client/test/rpc/eth/estimateGas.spec.ts index 081977b050..7e3a56d7a1 100644 --- a/packages/client/test/rpc/eth/estimateGas.spec.ts +++ b/packages/client/test/rpc/eth/estimateGas.spec.ts @@ -84,7 +84,9 @@ tape(`${method}: call with valid arguments`, async (t) => { estimateTx.getSenderAddress = () => { return address } - const { gasUsed } = await vm.copy().runTx({ + const { gasUsed } = await ( + await vm.copy() + ).runTx({ tx: estimateTx, skipNonce: true, skipBalance: true, diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 7c8627f3b9..263c3d5527 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -222,7 +222,7 @@ export async function runBlockWithTxs( const { vm } = execution // build block with tx const parentBlock = await chain.getLatestBlock() - const vmCopy = vm.copy() + const vmCopy = await vm.copy() const blockBuilder = await vmCopy.buildBlock({ parentBlock, headerData: { diff --git a/packages/client/test/sync/execution/vmexecution.spec.ts b/packages/client/test/sync/execution/vmexecution.spec.ts index 78c4acc7ed..12cf333af8 100644 --- a/packages/client/test/sync/execution/vmexecution.spec.ts +++ b/packages/client/test/sync/execution/vmexecution.spec.ts @@ -11,7 +11,7 @@ import testnet from './../../testdata/common/testnet.json' tape('[VMExecution]', async (t) => { t.test('Initialization', async (t) => { - const vm = new VM() + const vm = await VM.create() const config = new Config({ vm, transports: [] }) const chain = new Chain({ config }) const exec = new VMExecution({ config, chain }) From bdfd3c5c9f4a561f91a39d3f9d9ff7c2fd339b59 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 19:34:53 -0700 Subject: [PATCH 4/9] block: doc nit --- packages/block/src/header.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 3ca6705da9..6d0467eb0a 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -167,7 +167,7 @@ export class BlockHeader { /** * This constructor takes the values, validates them, assigns them and freezes the object. * - * @deprecated - Use the public static factory methods to assist in creating a Header object from + * @deprecated Use the public static factory methods to assist in creating a Header object from * varying data types. For a default empty header, use {@link BlockHeader.fromHeaderData}. * */ From ae01beb8d0efb3ce97e96ffb8b37db4462526087 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 19:49:00 -0700 Subject: [PATCH 5/9] nits --- packages/client/test/miner/miner.spec.ts | 1 + packages/vm/src/index.ts | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/client/test/miner/miner.spec.ts b/packages/client/test/miner/miner.spec.ts index e215a94f4c..d23b990a0c 100644 --- a/packages/client/test/miner/miner.spec.ts +++ b/packages/client/test/miner/miner.spec.ts @@ -74,6 +74,7 @@ tape('[Miner]', async (t) => { cliqueCheckRecentlySigned: () => false, // eslint-disable-next-line no-invalid-this copy: () => this.blockchain, + _init: async () => undefined, } } diff --git a/packages/vm/src/index.ts b/packages/vm/src/index.ts index 5334cdef99..839571522f 100644 --- a/packages/vm/src/index.ts +++ b/packages/vm/src/index.ts @@ -327,10 +327,7 @@ export default class VM extends AsyncEventEmitter { } async init(): Promise { - if (this._isInitialized) { - return - } - + if (this._isInitialized) return await (this.blockchain as any)._init() if (!this._opts.stateManager) { From 34cbf51f57115fcb01e3e0c9eb8e0be64b53ec77 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Wed, 23 Mar 2022 20:00:42 -0700 Subject: [PATCH 6/9] fix vm benchmarks, add _init to mockchain --- packages/vm/benchmarks/mockchain.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vm/benchmarks/mockchain.ts b/packages/vm/benchmarks/mockchain.ts index d8e46c6a69..c743d78f0f 100644 --- a/packages/vm/benchmarks/mockchain.ts +++ b/packages/vm/benchmarks/mockchain.ts @@ -6,6 +6,8 @@ export default class Mockchain { this._hashes = {} } + async _init() {} + getBlock(num: bigint): any { const bhash = this._hashes[num.toString()] return { From 4d470574d6ee2cad5e722270efd9f3b4e38e5382 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Thu, 24 Mar 2022 13:29:37 -0400 Subject: [PATCH 7/9] Make blockchain and vm constructors protected --- packages/blockchain/src/index.ts | 2 +- packages/client/lib/blockchain/chain.ts | 2 +- packages/client/lib/execution/vmexecution.ts | 7 +++---- packages/vm/src/index.ts | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/blockchain/src/index.ts b/packages/blockchain/src/index.ts index b604397d16..bc0cdf61a1 100644 --- a/packages/blockchain/src/index.ts +++ b/packages/blockchain/src/index.ts @@ -246,7 +246,7 @@ export default class Blockchain implements BlockchainInterface { * @param opts An object with the options that this constructor takes. See * {@link BlockchainOptions}. */ - constructor(opts: BlockchainOptions = {}) { + protected constructor(opts: BlockchainOptions = {}) { // Throw on chain or hardfork options removed in latest major release to // prevent implicit chain setup on a wrong chain if ('chain' in opts || 'hardfork' in opts) { diff --git a/packages/client/lib/blockchain/chain.ts b/packages/client/lib/blockchain/chain.ts index 25fc0e74f0..5be752f6c0 100644 --- a/packages/client/lib/blockchain/chain.ts +++ b/packages/client/lib/blockchain/chain.ts @@ -112,7 +112,7 @@ export class Chain { this.blockchain = options.blockchain ?? - new Blockchain({ + new (Blockchain as any)({ db: options.chainDB, common: this.config.chainCommon, hardforkByHeadBlockNumber: true, diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index ac7cd85bf8..8278fb0545 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -32,14 +32,14 @@ export class VMExecution extends Execution { trie, }) - this.vm = new VM({ + this.vm = new (VM as any)({ common: this.config.execCommon, blockchain: this.chain.blockchain, stateManager, }) } else { this.vm = this.config.vm - ;(this.vm as any).blockchain = this.chain.blockchain + ; (this.vm as any).blockchain = this.chain.blockchain } if (this.metaDB) { @@ -209,8 +209,7 @@ export class VMExecution extends Execution { ) } else { this.config.logger.warn( - `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${ - endHeadBlock.header.number + `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${endHeadBlock.header.number }` ) } diff --git a/packages/vm/src/index.ts b/packages/vm/src/index.ts index 839571522f..482fb9ad3c 100644 --- a/packages/vm/src/index.ts +++ b/packages/vm/src/index.ts @@ -226,7 +226,7 @@ export default class VM extends AsyncEventEmitter { * use the async {@link VM.create} constructor instead (same API). * @param opts */ - constructor(opts: VMOpts = {}) { + protected constructor(opts: VMOpts = {}) { super() this._opts = opts @@ -295,7 +295,7 @@ export default class VM extends AsyncEventEmitter { }) } - this.blockchain = opts.blockchain ?? new Blockchain({ common: this._common }) + this.blockchain = opts.blockchain ?? new (Blockchain as any)({ common: this._common }) this._allowUnlimitedContractSize = opts.allowUnlimitedContractSize ?? false From 563a4a0afe7e848cf1305676c03a15ed183440e9 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Thu, 24 Mar 2022 13:51:32 -0400 Subject: [PATCH 8/9] lint --- packages/client/lib/execution/vmexecution.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/execution/vmexecution.ts b/packages/client/lib/execution/vmexecution.ts index 8278fb0545..67cd1df083 100644 --- a/packages/client/lib/execution/vmexecution.ts +++ b/packages/client/lib/execution/vmexecution.ts @@ -39,7 +39,7 @@ export class VMExecution extends Execution { }) } else { this.vm = this.config.vm - ; (this.vm as any).blockchain = this.chain.blockchain + ;(this.vm as any).blockchain = this.chain.blockchain } if (this.metaDB) { @@ -209,7 +209,8 @@ export class VMExecution extends Execution { ) } else { this.config.logger.warn( - `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${endHeadBlock.header.number + `No blocks executed past chain head hash=${short(endHeadBlock.hash())} number=${ + endHeadBlock.header.number }` ) } From 20134d662a77f79e6d55f3284ccf4ca3dae830e1 Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Fri, 25 Mar 2022 14:40:35 -0700 Subject: [PATCH 9/9] vm: update new tests to await --- .../tests/api/EIPs/eip-3540-evm-object-format.spec.ts | 11 ++++++----- .../api/EIPs/eip-3670-eof-code-validation.spec.ts | 4 ++-- packages/vm/tests/api/EIPs/eip-3860.spec.ts | 2 +- packages/vm/tests/api/evm/customOpcodes.spec.ts | 10 +++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/vm/tests/api/EIPs/eip-3540-evm-object-format.spec.ts b/packages/vm/tests/api/EIPs/eip-3540-evm-object-format.spec.ts index 4b4a34eaa1..03d81b56ac 100644 --- a/packages/vm/tests/api/EIPs/eip-3540-evm-object-format.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3540-evm-object-format.spec.ts @@ -4,6 +4,7 @@ import Common, { Chain, Hardfork } from '@ethereumjs/common' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, privateToAddress } from 'ethereumjs-util' import * as eof from '../../../src/evm/opcodes/eof' + const pkey = Buffer.from('20'.repeat(32), 'hex') const GWEI = BigInt('1000000000') const sender = new Address(privateToAddress(pkey)) @@ -63,7 +64,7 @@ tape('EIP 3540 tests', (t) => { hardfork: Hardfork.London, eips: [3540], }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance @@ -79,7 +80,7 @@ tape('EIP 3540 tests', (t) => { }) t.test('invalid EOF format / contract creation', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance @@ -149,7 +150,7 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => hardfork: Hardfork.London, eips: [3540], }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance @@ -169,7 +170,7 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => hardfork: Hardfork.London, eips: [3540], }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance @@ -190,7 +191,7 @@ tape('ensure invalid EOF initcode in EIP-3540 does not consume all gas', (t) => hardfork: Hardfork.London, eips: [3540], }) - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance diff --git a/packages/vm/tests/api/EIPs/eip-3670-eof-code-validation.spec.ts b/packages/vm/tests/api/EIPs/eip-3670-eof-code-validation.spec.ts index 3c552c48c1..fadfc89e2f 100644 --- a/packages/vm/tests/api/EIPs/eip-3670-eof-code-validation.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3670-eof-code-validation.spec.ts @@ -57,7 +57,7 @@ tape('EIP 3670 tests', (t) => { }) t.test('valid contract code transactions', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance @@ -73,7 +73,7 @@ tape('EIP 3670 tests', (t) => { }) t.test('invalid contract code transactions', async (st) => { - const vm = new VM({ common: common }) + const vm = await VM.create({ common: common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance diff --git a/packages/vm/tests/api/EIPs/eip-3860.spec.ts b/packages/vm/tests/api/EIPs/eip-3860.spec.ts index ab16d859c3..77aec6ceb7 100644 --- a/packages/vm/tests/api/EIPs/eip-3860.spec.ts +++ b/packages/vm/tests/api/EIPs/eip-3860.spec.ts @@ -15,7 +15,7 @@ tape('EIP 3860 tests', (t) => { }) t.test('EIP-3860 tests', async (st) => { - const vm = new VM({ common }) + const vm = await VM.create({ common }) const account = await vm.stateManager.getAccount(sender) const balance = GWEI * BigInt(21000) * BigInt(10000000) account.balance = balance diff --git a/packages/vm/tests/api/evm/customOpcodes.spec.ts b/packages/vm/tests/api/evm/customOpcodes.spec.ts index c9cb035e5b..7414760d70 100644 --- a/packages/vm/tests/api/evm/customOpcodes.spec.ts +++ b/packages/vm/tests/api/evm/customOpcodes.spec.ts @@ -22,7 +22,7 @@ tape('VM: custom opcodes', (t) => { } t.test('should add custom opcodes to the VM', async (st) => { - const vm = new VM({ + const vm = await VM.create({ customOpcodes: [testOpcode], }) const gas = 123456 @@ -42,7 +42,7 @@ tape('VM: custom opcodes', (t) => { }) t.test('should delete opcodes from the VM', async (st) => { - const vm = new VM({ + const vm = await VM.create({ customOpcodes: [{ opcode: 0x20 }], // deletes KECCAK opcode }) const gas = BigInt(123456) @@ -56,7 +56,7 @@ tape('VM: custom opcodes', (t) => { t.test('should not override default opcodes', async (st) => { // This test ensures that always the original opcode map is used // Thus, each time you recreate a VM, it is in a clean state - const vm = new VM({ + const vm = await VM.create({ customOpcodes: [{ opcode: 0x01 }], // deletes ADD opcode }) const gas = BigInt(123456) @@ -66,7 +66,7 @@ tape('VM: custom opcodes', (t) => { }) st.ok(res.gasUsed === gas, 'succesfully deleted opcode') - const vmDefault = new VM() + const vmDefault = await VM.create() // PUSH 04 // PUSH 01 @@ -85,7 +85,7 @@ tape('VM: custom opcodes', (t) => { t.test('should override opcodes in the VM', async (st) => { testOpcode.opcode = 0x20 // Overrides KECCAK - const vm = new VM({ + const vm = await VM.create({ customOpcodes: [testOpcode], }) const gas = 123456