diff --git a/package-lock.json b/package-lock.json index 8b346f4509..270bd52b21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12436,11 +12436,11 @@ "integrity": "sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA==" }, "node_modules/rustbn-wasm": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn-wasm/-/rustbn-wasm-0.2.0.tgz", - "integrity": "sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/rustbn-wasm/-/rustbn-wasm-0.4.0.tgz", + "integrity": "sha512-C2ujvPv05hXC69MD7YwSsoUEsT/X/dKHkkgwN9B0ZTgb0OXDC9yaHhE6Pq+uaRAzMyW0Y97bwc4JO4cqPDzVuQ==", "dependencies": { - "@scure/base": "^1.1.1" + "@scure/base": "^1.1.5" } }, "node_modules/rxjs": { @@ -16051,7 +16051,7 @@ "@types/debug": "^4.1.9", "debug": "^4.3.3", "ethereum-cryptography": "^2.1.3", - "rustbn-wasm": "^0.2.0" + "rustbn-wasm": "^0.4.0" }, "devDependencies": { "@ethersproject/abi": "^5.0.12", @@ -16118,7 +16118,8 @@ "devDependencies": { "@ethereumjs/block": "^5.1.1", "@ethereumjs/genesis": "^0.2.1", - "@types/debug": "^4.1.9" + "@types/debug": "^4.1.9", + "rustbn-wasm": "^0.4.0" } }, "packages/trie": { @@ -16215,7 +16216,8 @@ "@ethereumjs/tx": "^5.2.1", "@ethereumjs/util": "^9.0.2", "debug": "^4.3.3", - "ethereum-cryptography": "^2.1.3" + "ethereum-cryptography": "^2.1.3", + "rustbn-wasm": "^0.4.0" }, "devDependencies": { "@ethersproject/abi": "^5.0.12", diff --git a/packages/evm/examples/browser.html b/packages/evm/examples/browser.html index 74f74829de..586f5f4561 100644 --- a/packages/evm/examples/browser.html +++ b/packages/evm/examples/browser.html @@ -15,7 +15,7 @@ const stateManager = new DefaultStateManager() const blockchain = await Blockchain.create() - const evm = new EVM({ + const evm = await EVM.create({ common, stateManager, blockchain, diff --git a/packages/evm/examples/eips.ts b/packages/evm/examples/eips.ts index 212609e907..91c15891d0 100644 --- a/packages/evm/examples/eips.ts +++ b/packages/evm/examples/eips.ts @@ -1,6 +1,10 @@ import { Chain, Common } from '@ethereumjs/common' import { EVM } from '@ethereumjs/evm' -const common = new Common({ chain: Chain.Mainnet, eips: [3074] }) -const evm = new EVM({ common }) -console.log(`EIP 3074 is active - ${evm.common.isActivatedEIP(3074)}`) +const main = async () => { + const common = new Common({ chain: Chain.Mainnet, eips: [3074] }) + const evm = await EVM.create({ common }) + console.log(`EIP 3074 is active - ${evm.common.isActivatedEIP(3074)}`) +} + +main() diff --git a/packages/evm/examples/runCode.ts b/packages/evm/examples/runCode.ts index 84dd2bbf38..6cdc1da404 100644 --- a/packages/evm/examples/runCode.ts +++ b/packages/evm/examples/runCode.ts @@ -7,7 +7,7 @@ const main = async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) const blockchain = await Blockchain.create() - const evm = new EVM({ + const evm = await EVM.create({ common, blockchain, }) diff --git a/packages/evm/examples/simple.ts b/packages/evm/examples/simple.ts index 46bdeaa094..59eb453ae1 100644 --- a/packages/evm/examples/simple.ts +++ b/packages/evm/examples/simple.ts @@ -1,8 +1,8 @@ import { hexToBytes } from '@ethereumjs/util' import { EVM } from '@ethereumjs/evm' -const evm = new EVM() const main = async () => { + const evm = await EVM.create({}) const res = await evm.runCode({ code: hexToBytes('0x6001') }) // PUSH1 01 -- simple bytecode to push 1 onto the stack console.log(res.executionGasUsed) // 3n } diff --git a/packages/evm/examples/withBlockchain.ts b/packages/evm/examples/withBlockchain.ts index bba6cca754..de4acf19a6 100644 --- a/packages/evm/examples/withBlockchain.ts +++ b/packages/evm/examples/withBlockchain.ts @@ -9,7 +9,7 @@ const main = async () => { const stateManager = new DefaultStateManager() const blockchain = await Blockchain.create() - const evm = new EVM({ + const evm = await EVM.create({ common, stateManager, blockchain, diff --git a/packages/evm/package.json b/packages/evm/package.json index 856deb0b8c..0d501de348 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -60,7 +60,7 @@ "@types/debug": "^4.1.9", "debug": "^4.3.3", "ethereum-cryptography": "^2.1.3", - "rustbn-wasm": "^0.2.0" + "rustbn-wasm": "^0.4.0" }, "devDependencies": { "@ethersproject/abi": "^5.0.12", diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 9209e5d585..8ebe7ce637 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -17,6 +17,7 @@ import { zeros, } from '@ethereumjs/util' import debugDefault from 'debug' +import { initRustBN } from 'rustbn-wasm' import { EOF, getEOFCode } from './eof.js' import { ERROR, EvmError } from './exceptions.js' @@ -137,7 +138,24 @@ export class EVM implements EVMInterface { protected readonly _emit: (topic: string, data: any) => Promise - constructor(opts: EVMOpts = {}) { + private bn128: { + ec_pairing: (input_str: string) => string + ec_add: (input_str: string) => string + ec_mul: (input_hex: string) => string + } + + static async create(createOpts?: EVMOpts) { + const opts = createOpts ?? ({} as EVMOpts) + if (opts?.bn128 === undefined) { + opts.bn128 = await initRustBN() + } + return new EVM(opts) + } + constructor(opts: EVMOpts) { + if (opts.bn128 === undefined) { + throw new Error('rustbn not provided') + } + this.bn128 = opts.bn128 // Required to instantiate the EVM this.events = new AsyncEventEmitter() this._optsCached = opts @@ -1079,6 +1097,7 @@ export class EVM implements EVMInterface { ...this._optsCached, common, stateManager: this.stateManager.shallowCopy(), + bn128: this.bn128, } ;(opts.stateManager as any).common = common return new EVM(opts) diff --git a/packages/evm/src/index.ts b/packages/evm/src/index.ts index 44307e91b0..500d727b1a 100644 --- a/packages/evm/src/index.ts +++ b/packages/evm/src/index.ts @@ -11,8 +11,10 @@ import { EVMRunCodeOpts, ExecResult, Log, + bn128, } from './types.js' export { + bn128, EOF, EVM, EvmError, diff --git a/packages/evm/src/precompiles/06-ecadd.ts b/packages/evm/src/precompiles/06-ecadd.ts index e32ae9b148..90f79198cc 100644 --- a/packages/evm/src/precompiles/06-ecadd.ts +++ b/packages/evm/src/precompiles/06-ecadd.ts @@ -1,8 +1,8 @@ import { bytesToHex, bytesToUnprefixedHex, hexToBytes, short } from '@ethereumjs/util' -import { ec_add } from 'rustbn-wasm' import { OOGResult } from '../evm.js' +import type { EVM } from '../evm.js' import type { ExecResult } from '../types.js' import type { PrecompileInput } from './types.js' @@ -24,7 +24,7 @@ export function precompile06(opts: PrecompileInput): ExecResult { return OOGResult(opts.gasLimit) } - const returnData = hexToBytes(ec_add(inputData)) + const returnData = hexToBytes((opts._EVM as EVM)['bn128'].ec_add(inputData)) // check ecadd success or failure by comparing the output length if (returnData.length !== 64) { diff --git a/packages/evm/src/precompiles/07-ecmul.ts b/packages/evm/src/precompiles/07-ecmul.ts index f3cce6967f..bfcead0e3c 100644 --- a/packages/evm/src/precompiles/07-ecmul.ts +++ b/packages/evm/src/precompiles/07-ecmul.ts @@ -1,8 +1,8 @@ import { bytesToHex, bytesToUnprefixedHex, hexToBytes, short } from '@ethereumjs/util' -import { ec_mul } from 'rustbn-wasm' import { OOGResult } from '../evm.js' +import type { EVM } from '../evm.js' import type { ExecResult } from '../types.js' import type { PrecompileInput } from './types.js' @@ -24,7 +24,7 @@ export function precompile07(opts: PrecompileInput): ExecResult { return OOGResult(opts.gasLimit) } - const returnData = hexToBytes(ec_mul(inputData)) + const returnData = hexToBytes((opts._EVM as EVM)['bn128'].ec_mul(inputData)) // check ecmul success or failure by comparing the output length if (returnData.length !== 64) { diff --git a/packages/evm/src/precompiles/08-ecpairing.ts b/packages/evm/src/precompiles/08-ecpairing.ts index 391d5759df..ce49470035 100644 --- a/packages/evm/src/precompiles/08-ecpairing.ts +++ b/packages/evm/src/precompiles/08-ecpairing.ts @@ -1,8 +1,8 @@ import { bytesToHex, bytesToUnprefixedHex, hexToBytes, short } from '@ethereumjs/util' -import { ec_pairing } from 'rustbn-wasm' import { OOGResult } from '../evm.js' +import type { EVM } from '../evm.js' import type { ExecResult } from '../types.js' import type { PrecompileInput } from './types.js' @@ -28,7 +28,9 @@ export function precompile08(opts: PrecompileInput): ExecResult { return OOGResult(opts.gasLimit) } - const returnData = hexToBytes(ec_pairing(bytesToUnprefixedHex(inputData))) + const returnData = hexToBytes( + (opts._EVM as EVM)['bn128'].ec_pairing(bytesToUnprefixedHex(inputData)) + ) // check ecpairing success or failure by comparing the output length if (returnData.length !== 32) { diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index a1ded58239..037009b1f1 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -172,6 +172,14 @@ export type EVMProfilerOpts = { * Options for instantiating a {@link EVM}. */ export interface EVMOpts { + /** + * The BN128 curve package (`rustbn-wasm`) + */ + bn128?: { + ec_pairing: (input_str: string) => string + ec_add: (input_str: string) => string + ec_mul: (input_hex: string) => string + } /** * Use a {@link Common} instance for EVM instantiation. * @@ -380,3 +388,12 @@ export class DefaultBlockchain implements Blockchain { return this } } + +/** + * The BN128 curve package (`rustbn-wasm`) + */ +export interface bn128 { + ec_pairing: (input_str: string) => string + ec_add: (input_str: string) => string + ec_mul: (input_hex: string) => string +} diff --git a/packages/evm/test/asyncEvents.spec.ts b/packages/evm/test/asyncEvents.spec.ts index 6b2676e87b..88972a567e 100644 --- a/packages/evm/test/asyncEvents.spec.ts +++ b/packages/evm/test/asyncEvents.spec.ts @@ -7,7 +7,7 @@ describe('async events', () => { it('should work', async () => { const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) evm.events.on('step', async (event, next) => { diff --git a/packages/evm/test/blobVersionedHashes.spec.ts b/packages/evm/test/blobVersionedHashes.spec.ts index dec3f02b92..9ce0731e39 100644 --- a/packages/evm/test/blobVersionedHashes.spec.ts +++ b/packages/evm/test/blobVersionedHashes.spec.ts @@ -14,7 +14,7 @@ describe('BLOBHASH / access blobVersionedHashes in calldata', () => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) @@ -44,7 +44,7 @@ describe(`BLOBHASH: access blobVersionedHashes within contract calls`, () => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) @@ -95,7 +95,7 @@ describe(`BLOBHASH: access blobVersionedHashes in a CREATE/CREATE2 frame`, () => chain: 'custom', hardfork: Hardfork.Cancun, }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) diff --git a/packages/evm/test/customCrypto.spec.ts b/packages/evm/test/customCrypto.spec.ts index 815331039f..43a3a5a5d1 100644 --- a/packages/evm/test/customCrypto.spec.ts +++ b/packages/evm/test/customCrypto.spec.ts @@ -23,7 +23,7 @@ describe('custom crypto', () => { } const msg = Uint8Array.from([0, 1, 2, 3]) const common = new Common({ chain: Chain.Mainnet, customCrypto }) - const evm = new EVM({ common }) + const evm = await EVM.create({ common }) const addressStr = '0000000000000000000000000000000000000002' const SHA256 = getActivePrecompiles(common).get(addressStr)! const result = await SHA256({ @@ -46,7 +46,7 @@ describe('custom crypto', () => { } const msg = concatBytes(randomBytes(32), setLengthLeft(intToBytes(27), 32), randomBytes(32)) const common = new Common({ chain: Chain.Mainnet, customCrypto }) - const evm = new EVM({ common }) + const evm = await EVM.create({ common }) const addressStr = '0000000000000000000000000000000000000001' const ECRECOVER = getActivePrecompiles(common).get(addressStr)! const result = await ECRECOVER({ diff --git a/packages/evm/test/customOpcodes.spec.ts b/packages/evm/test/customOpcodes.spec.ts index 49fb1eacfc..47fadaf36a 100644 --- a/packages/evm/test/customOpcodes.spec.ts +++ b/packages/evm/test/customOpcodes.spec.ts @@ -25,9 +25,7 @@ describe('VM: custom opcodes', () => { } it('should add custom opcodes to the EVM', async () => { - const evm = new EVM({ - customOpcodes: [testOpcode], - }) + const evm = await EVM.create({ customOpcodes: [testOpcode] }) const gas = 123456 let correctOpcodeName = false evm.events.on('step', (e: InterpreterStep) => { @@ -45,7 +43,7 @@ describe('VM: custom opcodes', () => { }) it('should delete opcodes from the EVM', async () => { - const evm = new EVM({ + const evm = await EVM.create({ customOpcodes: [{ opcode: 0x20 }], // deletes KECCAK opcode }) const gas = BigInt(123456) @@ -59,7 +57,7 @@ describe('VM: custom opcodes', () => { it('should not override default opcodes', async () => { // This test ensures that always the original opcode map is used // Thus, each time you recreate a EVM, it is in a clean state - const evm = new EVM({ + const evm = await EVM.create({ customOpcodes: [{ opcode: 0x01 }], // deletes ADD opcode }) const gas = BigInt(123456) @@ -69,7 +67,7 @@ describe('VM: custom opcodes', () => { }) assert.ok(res.executionGasUsed === gas, 'successfully deleted opcode') - const evmDefault = new EVM({}) + const evmDefault = await EVM.create({}) // PUSH 04 // PUSH 01 @@ -88,9 +86,7 @@ describe('VM: custom opcodes', () => { it('should override opcodes in the EVM', async () => { testOpcode.opcode = 0x20 // Overrides KECCAK - const evm = new EVM({ - customOpcodes: [testOpcode], - }) + const evm = await EVM.create({ customOpcodes: [testOpcode] }) const gas = 123456 const res = await evm.runCode({ code: hexToBytes('0x20'), @@ -113,9 +109,7 @@ describe('VM: custom opcodes', () => { }, } - const evm = new EVM({ - customOpcodes: [testOpcode], - }) + const evm = await EVM.create({ customOpcodes: [testOpcode] }) evm.events.on('beforeMessage', () => {}) evm.events.on('beforeMessage', () => {}) const evmCopy = evm.shallowCopy() diff --git a/packages/evm/test/customPrecompiles.spec.ts b/packages/evm/test/customPrecompiles.spec.ts index 9c06d6fa5b..4d92051213 100644 --- a/packages/evm/test/customPrecompiles.spec.ts +++ b/packages/evm/test/customPrecompiles.spec.ts @@ -28,7 +28,7 @@ function customPrecompileNoInput(): ExecResult { describe('EVM -> custom precompiles', () => { it('should work on precompiles without input arguments', async () => { - const EVMOverride = new EVM({ + const EVMOverride = await EVM.create({ customPrecompiles: [ { address: Address.zero(), @@ -47,7 +47,7 @@ describe('EVM -> custom precompiles', () => { assert.equal(result.execResult.executionGasUsed, expectedGas, 'gas used is correct') }) it('should override existing precompiles', async () => { - const EVMOverride = new EVM({ + const EVMOverride = await EVM.create({ customPrecompiles: [ { address: shaAddress, @@ -67,7 +67,7 @@ describe('EVM -> custom precompiles', () => { }) it('should delete existing precompiles', async () => { - const EVMOverride = new EVM({ + const EVMOverride = await EVM.create({ customPrecompiles: [ { address: shaAddress, @@ -85,7 +85,7 @@ describe('EVM -> custom precompiles', () => { }) it('should add precompiles', async () => { - const EVMOverride = new EVM({ + const EVMOverride = await EVM.create({ customPrecompiles: [ { address: newPrecompile, @@ -104,14 +104,14 @@ describe('EVM -> custom precompiles', () => { }) it('should not persist changes to precompiles', async () => { - let EVMSha = new EVM() + let EVMSha = await EVM.create({}) const shaResult = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), data: hexToBytes('0x'), caller: sender, }) - const EVMOverride = new EVM({ + const EVMOverride = await EVM.create({ customPrecompiles: [ { address: shaAddress, @@ -128,7 +128,7 @@ describe('EVM -> custom precompiles', () => { // sanity: check we have overridden assert.deepEqual(result.execResult.returnValue, expectedReturn, 'return value is correct') assert.ok(result.execResult.executionGasUsed === expectedGas, 'gas used is correct') - EVMSha = new EVM() + EVMSha = await EVM.create({}) const shaResult2 = await EVMSha.runCall({ to: shaAddress, gasLimit: BigInt(30000), @@ -147,7 +147,7 @@ describe('EVM -> custom precompiles', () => { ) }) it('shold copy custom precompiles', async () => { - const evm = new EVM({ + const evm = await EVM.create({ customPrecompiles: [ { address: shaAddress, diff --git a/packages/evm/test/eips/eip-3860.spec.ts b/packages/evm/test/eips/eip-3860.spec.ts index 3ef3cc0337..c888a883e2 100644 --- a/packages/evm/test/eips/eip-3860.spec.ts +++ b/packages/evm/test/eips/eip-3860.spec.ts @@ -15,7 +15,7 @@ describe('EIP 3860 tests', () => { hardfork: Hardfork.London, eips: [3860], }) - const evm = new EVM({ + const evm = await EVM.create({ common, stateManager: new DefaultStateManager(), }) @@ -56,11 +56,11 @@ describe('EIP 3860 tests', () => { eips: [], }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const evm = new EVM({ + const evm = await EVM.create({ common: commonWith3860, stateManager: new DefaultStateManager(), }) - const evmWithout3860 = new EVM({ + const evmWithout3860 = await EVM.create({ common: commonWithout3860, stateManager: new DefaultStateManager(), }) @@ -102,11 +102,11 @@ describe('EIP 3860 tests', () => { eips: [], }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') - const evm = new EVM({ + const evm = await EVM.create({ common: commonWith3860, stateManager: new DefaultStateManager(), }) - const evmWithout3860 = new EVM({ + const evmWithout3860 = await EVM.create({ common: commonWithout3860, stateManager: new DefaultStateManager(), }) @@ -141,7 +141,7 @@ describe('EIP 3860 tests', () => { hardfork: Hardfork.London, eips: [3860], }) - const evm = new EVM({ + const evm = await EVM.create({ common, stateManager: new DefaultStateManager(), @@ -177,13 +177,13 @@ describe('EIP 3860 tests', () => { }) const caller = Address.fromString('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b') for (const code of ['F0', 'F5']) { - const evm = new EVM({ + const evm = await EVM.create({ common: commonWith3860, stateManager: new DefaultStateManager(), allowUnlimitedInitCodeSize: true, }) - const evmDisabled = new EVM({ + const evmDisabled = await EVM.create({ common: commonWith3860, stateManager: new DefaultStateManager(), diff --git a/packages/evm/test/eips/eip-5656.spec.ts b/packages/evm/test/eips/eip-5656.spec.ts index 001de857da..e454808507 100644 --- a/packages/evm/test/eips/eip-5656.spec.ts +++ b/packages/evm/test/eips/eip-5656.spec.ts @@ -83,7 +83,7 @@ describe('should test mcopy', () => { eips: [5656], }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) diff --git a/packages/evm/test/opcodes.spec.ts b/packages/evm/test/opcodes.spec.ts index f36d12f78c..b4ff6d3b45 100644 --- a/packages/evm/test/opcodes.spec.ts +++ b/packages/evm/test/opcodes.spec.ts @@ -10,9 +10,7 @@ describe('EVM -> getActiveOpcodes()', () => { it('should not expose opcodes from a follow-up HF (istanbul -> petersburg)', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(CHAINID), undefined, @@ -22,9 +20,7 @@ describe('EVM -> getActiveOpcodes()', () => { it('should expose opcodes when HF is active (>= istanbul)', async () => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - let evm = new EVM({ - common, - }) + let evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -32,9 +28,7 @@ describe('EVM -> getActiveOpcodes()', () => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.MuirGlacier }) - evm = new EVM({ - common, - }) + evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(CHAINID)!.name, 'CHAINID', @@ -44,9 +38,7 @@ describe('EVM -> getActiveOpcodes()', () => { it('should switch DIFFICULTY opcode name to PREVRANDAO when >= Merge HF', async () => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - let evm = new EVM({ - common, - }) + let evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(DIFFICULTY_PREVRANDAO)!.name, 'DIFFICULTY', @@ -54,9 +46,7 @@ describe('EVM -> getActiveOpcodes()', () => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris }) - evm = new EVM({ - common, - }) + evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(DIFFICULTY_PREVRANDAO)!.name, 'PREVRANDAO', @@ -66,9 +56,7 @@ describe('EVM -> getActiveOpcodes()', () => { it('should expose opcodes when EIP is active', async () => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul, eips: [2315] }) - let evm = new EVM({ - common, - }) + let evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(BEGINSUB)!.name, 'BEGINSUB', @@ -76,9 +64,7 @@ describe('EVM -> getActiveOpcodes()', () => { ) common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - evm = new EVM({ - common, - }) + evm = await EVM.create({ common }) assert.equal( evm.getActiveOpcodes().get(BEGINSUB), undefined, @@ -88,9 +74,7 @@ describe('EVM -> getActiveOpcodes()', () => { it('should update opcodes on a hardfork change', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) common.setHardfork(Hardfork.Byzantium) assert.equal( diff --git a/packages/evm/test/precompiles/01-ecrecover.spec.ts b/packages/evm/test/precompiles/01-ecrecover.spec.ts index c72f25e056..977d205ff1 100644 --- a/packages/evm/test/precompiles/01-ecrecover.spec.ts +++ b/packages/evm/test/precompiles/01-ecrecover.spec.ts @@ -17,7 +17,7 @@ describe('Precompiles: ECRECOVER', () => { // Test reference: https://github.com/ethereum/go-ethereum/issues/3731#issuecomment-293866868 const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const addressStr = '0000000000000000000000000000000000000001' diff --git a/packages/evm/test/precompiles/03-ripemd160.spec.ts b/packages/evm/test/precompiles/03-ripemd160.spec.ts index 6c08c98d6e..96859bd65e 100644 --- a/packages/evm/test/precompiles/03-ripemd160.spec.ts +++ b/packages/evm/test/precompiles/03-ripemd160.spec.ts @@ -13,7 +13,7 @@ describe('Precompiles: RIPEMD160', () => { // Test reference: https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/contracts_test.go#L217 const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const addressStr = '0000000000000000000000000000000000000003' diff --git a/packages/evm/test/precompiles/05-modexp.spec.ts b/packages/evm/test/precompiles/05-modexp.spec.ts index 8e63eb044c..967a5f4be3 100644 --- a/packages/evm/test/precompiles/05-modexp.spec.ts +++ b/packages/evm/test/precompiles/05-modexp.spec.ts @@ -1,20 +1,27 @@ import { Chain, Common } from '@ethereumjs/common' import { bytesToHex, hexToBytes } from '@ethereumjs/util' -import { assert, describe, it } from 'vitest' +import { assert, beforeAll, describe, it } from 'vitest' import { EVM, getActivePrecompiles } from '../../src/index.js' import fuzzer from './modexp-testdata.json' +import type { PrecompileFunc } from '../../src/precompiles/types.js' + const fuzzerTests = fuzzer.data describe('Precompiles: MODEXP', () => { - const common = new Common({ chain: Chain.Mainnet }) - const evm = new EVM({ - common, + let common: Common + let evm: EVM + let addressStr: string + let MODEXP: PrecompileFunc + beforeAll(async () => { + common = new Common({ chain: Chain.Mainnet }) + evm = await EVM.create({ + common, + }) + addressStr = '0000000000000000000000000000000000000005' + MODEXP = getActivePrecompiles(common).get(addressStr)! }) - const addressStr = '0000000000000000000000000000000000000005' - const MODEXP = getActivePrecompiles(common).get(addressStr)! - it('should run testdata', async () => { let n = 0 for (const [input, expect] of fuzzerTests) { diff --git a/packages/evm/test/precompiles/06-ecadd.spec.ts b/packages/evm/test/precompiles/06-ecadd.spec.ts index d619ae18e5..0a7b597311 100644 --- a/packages/evm/test/precompiles/06-ecadd.spec.ts +++ b/packages/evm/test/precompiles/06-ecadd.spec.ts @@ -6,7 +6,7 @@ import { EVM, getActivePrecompiles } from '../../src/index.js' describe('Precompiles: ECADD', () => { it('ECADD', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const addressStr = '0000000000000000000000000000000000000006' diff --git a/packages/evm/test/precompiles/07-ecmul.spec.ts b/packages/evm/test/precompiles/07-ecmul.spec.ts index 957c7fe203..4e4f088f5e 100644 --- a/packages/evm/test/precompiles/07-ecmul.spec.ts +++ b/packages/evm/test/precompiles/07-ecmul.spec.ts @@ -6,7 +6,7 @@ import { EVM, getActivePrecompiles } from '../../src/index.js' describe('Precompiles: ECMUL', () => { it('ECMUL', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const ECMUL = getActivePrecompiles(common).get('0000000000000000000000000000000000000007')! diff --git a/packages/evm/test/precompiles/08-ecpairing.spec.ts b/packages/evm/test/precompiles/08-ecpairing.spec.ts index d17aa65495..a5163d0d5f 100644 --- a/packages/evm/test/precompiles/08-ecpairing.spec.ts +++ b/packages/evm/test/precompiles/08-ecpairing.spec.ts @@ -7,7 +7,7 @@ import { EVM, getActivePrecompiles } from '../../src/index.js' describe('Precompiles: ECPAIRING', () => { it('ECPAIRING', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const addressStr = '0000000000000000000000000000000000000008' diff --git a/packages/evm/test/precompiles/09-blake2f.spec.ts b/packages/evm/test/precompiles/09-blake2f.spec.ts index 2cdbb031ff..8a020973f0 100644 --- a/packages/evm/test/precompiles/09-blake2f.spec.ts +++ b/packages/evm/test/precompiles/09-blake2f.spec.ts @@ -1,9 +1,11 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { Address, bytesToHex, hexToBytes } from '@ethereumjs/util' -import { assert, describe, it } from 'vitest' +import { assert, beforeAll, describe, it } from 'vitest' import { EVM, getActivePrecompiles } from '../../src/index.js' +import type { PrecompileFunc } from '../../src/precompiles/types.js' + const validCases = [ { input: @@ -74,15 +76,21 @@ const malformedCases = [ ] describe('Precompiles: BLAKE2F', () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - // Test references: https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/testdata/precompiles/blake2F.json - // https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/contracts_test.go#L73 + let evm: EVM + let common: Common + let addressStr: string + let BLAKE2F: PrecompileFunc + beforeAll(async () => { + common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) + // Test references: https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/testdata/precompiles/blake2F.json + // https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/contracts_test.go#L73 - const evm = new EVM({ - common, + evm = await EVM.create({ + common, + }) + addressStr = '0000000000000000000000000000000000000009' + BLAKE2F = getActivePrecompiles(common).get(addressStr)! }) - const addressStr = '0000000000000000000000000000000000000009' - const BLAKE2F = getActivePrecompiles(common).get(addressStr)! for (const t of validCases) { it(`BLAKE2F valid cases: ${t.name}`, async () => { diff --git a/packages/evm/test/precompiles/0a-pointevaluation.spec.ts b/packages/evm/test/precompiles/0a-pointevaluation.spec.ts index 618990f995..38cac49425 100644 --- a/packages/evm/test/precompiles/0a-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/0a-pointevaluation.spec.ts @@ -31,7 +31,7 @@ describe('Precompiles: point evaluation', () => { customCrypto: { kzg }, }) - const evm = new EVM({ + const evm = await EVM.create({ common, }) const addressStr = '000000000000000000000000000000000000000a' diff --git a/packages/evm/test/precompiles/hardfork.spec.ts b/packages/evm/test/precompiles/hardfork.spec.ts index c2ac81786a..1027fed872 100644 --- a/packages/evm/test/precompiles/hardfork.spec.ts +++ b/packages/evm/test/precompiles/hardfork.spec.ts @@ -20,7 +20,7 @@ describe('Precompiles: hardfork availability', () => { assert.ok(true, 'ECPAIRING available in petersburg') } - let evm = new EVM({ + let evm = await EVM.create({ common: commonByzantium, }) let result = await evm.runCall({ @@ -41,7 +41,7 @@ describe('Precompiles: hardfork availability', () => { assert.ok(true, 'ECPAIRING available in petersburg') } - evm = new EVM({ + evm = await EVM.create({ common: commonPetersburg, }) result = await evm.runCall({ @@ -63,7 +63,7 @@ describe('Precompiles: hardfork availability', () => { assert.ok(true, 'ECPAIRING not available in homestead') } - evm = new EVM({ + evm = await EVM.create({ common: commonHomestead, }) diff --git a/packages/evm/test/runCall.spec.ts b/packages/evm/test/runCall.spec.ts index f2b0554aa6..8a4f659289 100644 --- a/packages/evm/test/runCall.spec.ts +++ b/packages/evm/test/runCall.spec.ts @@ -31,9 +31,7 @@ function create2address(sourceAddress: Address, codeHash: Uint8Array, salt: Uint describe('RunCall tests', () => { it('Create where FROM account nonce is 0', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const res = await evm.runCall({ to: undefined }) assert.equal( res.createdAddress?.toString(), @@ -56,9 +54,7 @@ describe('RunCall tests', () => { const contractAddress = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // contract address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const code = '0x3460008080F560005260206000F3' /* code: remarks: (top of the stack is at the zero index) @@ -112,10 +108,10 @@ describe('RunCall tests', () => { const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) // caller address const contractAddress = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // contract address // setup the evm - const evmByzantium = new EVM({ + const evmByzantium = await EVM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Byzantium }), }) - const evmConstantinople = new EVM({ + const evmConstantinople = await EVM.create({ common: new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Constantinople }), }) const code = '0x600160011B00' @@ -156,9 +152,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const code = '0x61000260005561000160005500' /* idea: store the original value in the storage slot, except it is now a 1-length Uint8Array instead of a 32-length Uint8Array @@ -207,9 +201,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // push 1 push 0 sstore stop const code = '0x600160015500' @@ -234,9 +226,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // code to call 0x00..00dd, which does not exist const code = '0x6000600060006000600060DD61FFFF5A03F100' @@ -263,9 +253,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Homestead }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // code to call back into the calling account (0x00..00EE), // but using too much memory const code = '0x61FFFF60FF60006000600060EE6000F200' @@ -292,9 +280,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.TangerineWhistle }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ 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 @@ -322,9 +308,7 @@ describe('RunCall tests', () => { const address = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ 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 @@ -391,9 +375,7 @@ describe('RunCall tests', () => { const emptyBytes = hexToBytes('0x') // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const code = '0x60008080F060005500' /* This simple code tries to create an empty contract and then stores the address of the contract in the zero slot. @@ -445,9 +427,7 @@ describe('RunCall tests', () => { const caller = new Address(hexToBytes('0x1a02a619e51cc5f8a2a61d2a60f6c80476ee8ead')) // caller address // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const code = '0x3034526020600760203460045afa602034343e604034f3' const account = new Account() @@ -476,9 +456,7 @@ describe('RunCall tests', () => { it('Throws on negative call value', async () => { // setup the vm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // setup the call arguments const runCallArgs = { @@ -499,9 +477,7 @@ describe('RunCall tests', () => { it('runCall() -> skipBalance behavior', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // runCall against a contract to reach `_reduceSenderBalance` const contractCode = hexToBytes('0x00') // 00: STOP @@ -545,9 +521,7 @@ describe('RunCall tests', () => { const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) // caller address // setup the evm const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // setup the call arguments const runCallArgs = { @@ -572,9 +546,7 @@ describe('RunCall tests', () => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // setup the call arguments const runCallArgs: EVMRunCallOpts = { @@ -611,9 +583,7 @@ describe('RunCall tests', () => { chain: 'custom', hardfork: Hardfork.Cancun, }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const BLOBBASEFEE_OPCODE = 0x4a assert.equal( @@ -643,9 +613,7 @@ describe('RunCall tests', () => { it('step event: ensure EVM memory and not internal memory gets reported', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) const contractCode = hexToBytes('0x600060405200') // PUSH 0 PUSH 40 MSTORE STOP const contractAddress = Address.fromString('0x000000000000000000000000636F6E7472616374') @@ -670,9 +638,7 @@ describe('RunCall tests', () => { it('ensure code deposit errors are logged correctly (>= Homestead)', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // Create a contract which is too large const runCallArgs = { @@ -695,9 +661,7 @@ describe('RunCall tests', () => { it('ensure code deposit errors are logged correctly (Frontier)', async () => { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) // Create a contract which cannot pay the code deposit fee const runCallArgs = { @@ -721,9 +685,7 @@ describe('RunCall tests', () => { it('ensure call and callcode handle gas stipend correctly', async () => { // See: https://github.com/ethereumjs/ethereumjs-monorepo/issues/3194 const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }) - const evm = new EVM({ - common, - }) + const evm = await EVM.create({ common }) for (const [opcode, gas, expectedOutput] of [ ['f1', 36600, '0x'], // 36600 is CALL fee diff --git a/packages/evm/test/runCode.spec.ts b/packages/evm/test/runCode.spec.ts index 6c004bfb87..de0f795fb5 100644 --- a/packages/evm/test/runCode.spec.ts +++ b/packages/evm/test/runCode.spec.ts @@ -21,7 +21,7 @@ const testCases = [ describe('VM.runCode: initial program counter', () => { it('should work', async () => { - const evm = new EVM() + const evm = await EVM.create({}) for (const [i, testData] of testCases.entries()) { const runCodeArgs = { @@ -57,7 +57,7 @@ describe('VM.runCode: initial program counter', () => { describe('VM.runCode: interpreter', () => { it('should return a EvmError as an exceptionError on the result', async () => { - const evm = new EVM() + const evm = await EVM.create({}) const INVALID_opcode = 'fe' const runCodeArgs = { @@ -76,7 +76,7 @@ describe('VM.runCode: interpreter', () => { }) it('should throw on non-EvmError', async () => { - const evm = new EVM() + const evm = await EVM.create({}) // NOTE: due to now throwing on `getContractStorage` if account does not exist // this now means that if `runCode` is called and the address it runs on (default: zero address) // does not exist, then if SSTORE/SLOAD is used, the runCode will immediately fail because StateManager now throws @@ -105,7 +105,7 @@ describe('VM.runCode: interpreter', () => { describe('VM.runCode: RunCodeOptions', () => { it('should throw on negative value args', async () => { - const evm = new EVM() + const evm = await EVM.create({}) const runCodeArgs = { value: BigInt(-10), diff --git a/packages/evm/test/stack.spec.ts b/packages/evm/test/stack.spec.ts index 28531329e0..496b6bc413 100644 --- a/packages/evm/test/stack.spec.ts +++ b/packages/evm/test/stack.spec.ts @@ -99,7 +99,7 @@ describe('Stack', () => { it('stack items should not change if they are DUPed', async () => { const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) const addr = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) - const evm = new EVM() + const evm = await EVM.create({}) const account = createAccount(BigInt(0), BigInt(0)) const code = '0x60008080808060013382F15060005260206000F3' const expectedReturnValue = setLengthLeft(bigIntToBytes(BigInt(0)), 32) diff --git a/packages/statemanager/examples/evm.ts b/packages/statemanager/examples/evm.ts index 8028169000..e9f98df61a 100644 --- a/packages/statemanager/examples/evm.ts +++ b/packages/statemanager/examples/evm.ts @@ -7,7 +7,7 @@ const main = async () => { const blockchain = new RPCBlockChain(provider) const blockTag = 1n const state = new RPCStateManager({ provider, blockTag }) - const evm = new EVM({ blockchain, stateManager: state }) // note that evm is ready to run BLOCKHASH opcodes (over RPC) + const evm = await EVM.create({ blockchain, stateManager: state }) // note that evm is ready to run BLOCKHASH opcodes (over RPC) } catch (e) { console.log(e.message) // fetch would fail because provider url is not real. please replace provider with a valid rpc url string. } diff --git a/packages/statemanager/package.json b/packages/statemanager/package.json index d3385cca68..3f473c1994 100644 --- a/packages/statemanager/package.json +++ b/packages/statemanager/package.json @@ -62,6 +62,7 @@ "devDependencies": { "@ethereumjs/block": "^5.1.1", "@ethereumjs/genesis": "^0.2.1", - "@types/debug": "^4.1.9" + "@types/debug": "^4.1.9", + "rustbn-wasm": "^0.4.0" } } diff --git a/packages/statemanager/test/rpcStateManager.spec.ts b/packages/statemanager/test/rpcStateManager.spec.ts index 5ef33aa4a2..69a8bb7c0e 100644 --- a/packages/statemanager/test/rpcStateManager.spec.ts +++ b/packages/statemanager/test/rpcStateManager.spec.ts @@ -315,7 +315,7 @@ describe('blockchain', () => const blockchain = new RPCBlockChain(provider) const blockTag = 1n const state = new RPCStateManager({ provider, blockTag }) - const evm = new EVM({ blockchain, stateManager: state }) + const evm = await EVM.create({ blockchain, stateManager: state }) // Bytecode for returning the blockhash of the block previous to `blockTag` const code = '0x600143034060005260206000F3' const contractAddress = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) diff --git a/packages/vm/package.json b/packages/vm/package.json index 16a54f3e57..63a63201dd 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -73,7 +73,8 @@ "@ethereumjs/tx": "^5.2.1", "@ethereumjs/util": "^9.0.2", "debug": "^4.3.3", - "ethereum-cryptography": "^2.1.3" + "ethereum-cryptography": "^2.1.3", + "rustbn-wasm": "^0.4.0" }, "devDependencies": { "@ethersproject/abi": "^5.0.12", diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 768774abd4..cc8dcb2444 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -153,6 +153,8 @@ export interface VMOpts { evm?: EVMInterface profilerOpts?: VMProfilerOpts + + bn128?: any } /** diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index 24bc48a8a5..c60a2a5b86 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -3,6 +3,7 @@ import { Chain, Common } from '@ethereumjs/common' import { EVM, getActivePrecompiles } from '@ethereumjs/evm' import { DefaultStateManager } from '@ethereumjs/statemanager' import { Account, Address, AsyncEventEmitter, unprefixedHexToBytes } from '@ethereumjs/util' +import { initRustBN } from 'rustbn-wasm' import { buildBlock } from './buildBlock.js' import { runBlock } from './runBlock.js' @@ -77,7 +78,9 @@ export class VM { * @param opts VM engine constructor options */ static async create(opts: VMOpts = {}): Promise { + if (opts.bn128 === undefined) opts.bn128 = await initRustBN() const vm = new this(opts) + const genesisStateOpts = opts.stateManager === undefined && opts.genesisState === undefined ? { genesisState: {} } @@ -141,6 +144,7 @@ export class VM { profiler: { enabled: enableProfiler, }, + bn128: opts.bn128, }) } @@ -260,7 +264,7 @@ export class VM { blockchain, stateManager, } - const evmCopy = new EVM(evmOpts) // TODO fixme (should copy the EVMInterface, not default EVM) + const evmCopy = await EVM.create(evmOpts) // TODO fixme (should copy the EVMInterface, not default EVM) return VM.create({ stateManager, blockchain: this.blockchain, diff --git a/packages/vm/test/api/EIPs/eip-6800-verkle.spec.ts b/packages/vm/test/api/EIPs/eip-6800-verkle.spec.ts index 95ce3c61a7..90bedaf377 100644 --- a/packages/vm/test/api/EIPs/eip-6800-verkle.spec.ts +++ b/packages/vm/test/api/EIPs/eip-6800-verkle.spec.ts @@ -14,7 +14,7 @@ const block = Block.fromBlockData(verkleBlockJSON, { common }) describe('EIP 6800 tests', () => { it('successfully run transactions statelessly using the block witness', async () => { const verkleStateManager = new StatelessVerkleStateManager({ common }) - const evm = new EVM({ common, stateManager: verkleStateManager }) + const evm = await EVM.create({ common, stateManager: verkleStateManager }) const vm = await VM.create({ common, evm, diff --git a/packages/vm/test/api/istanbul/eip-1108.spec.ts b/packages/vm/test/api/istanbul/eip-1108.spec.ts index bf7c4d7272..fbcc13f1be 100644 --- a/packages/vm/test/api/istanbul/eip-1108.spec.ts +++ b/packages/vm/test/api/istanbul/eip-1108.spec.ts @@ -1,14 +1,17 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' import { getActivePrecompiles } from '@ethereumjs/evm' import { hexToBytes } from '@ethereumjs/util' -import { assert, describe, it } from 'vitest' +import { assert, beforeAll, describe, it } from 'vitest' import { VM } from '../../../src/vm' describe('Istanbul: EIP-1108 tests', () => { + let vm: VM + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) + beforeAll(async () => { + vm = await VM.create({ common }) + }) it('ECADD', async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = await VM.create({ common }) const address = '0000000000000000000000000000000000000006' const ECADD = getActivePrecompiles(common).get(address)! @@ -23,8 +26,6 @@ describe('Istanbul: EIP-1108 tests', () => { }) it('ECMUL', async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = await VM.create({ common }) const address = '0000000000000000000000000000000000000007' const ECMUL = getActivePrecompiles(common).get(address)! @@ -39,8 +40,6 @@ describe('Istanbul: EIP-1108 tests', () => { }) it('ECPAIRING', async () => { - const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) - const vm = await VM.create({ common }) const address = '0000000000000000000000000000000000000008' const ECPAIRING = getActivePrecompiles(common).get(address)! diff --git a/packages/vm/test/tester/index.ts b/packages/vm/test/tester/index.ts index f7c8bc1722..d9a36a9262 100755 --- a/packages/vm/test/tester/index.ts +++ b/packages/vm/test/tester/index.ts @@ -3,6 +3,7 @@ import { createKZG } from 'kzg-wasm' import * as minimist from 'minimist' import * as path from 'path' import * as process from 'process' +import { initRustBN } from 'rustbn-wasm' import * as tape from 'tape' import { @@ -19,6 +20,7 @@ import { runStateTest } from './runners/GeneralStateTestsRunner' import { getTestFromSource, getTestsFromArgs } from './testLoader' import type { Common } from '@ethereumjs/common' +import type { bn128 } from '@ethereumjs/evm' /** * Test runner @@ -103,6 +105,7 @@ async function runTests() { */ const kzg = await createKZG() initKZG(kzg) + const bn128 = await initRustBN() const runnerArgs: { forkConfigVM: string forkConfigTestSuite: string @@ -115,6 +118,7 @@ async function runTests() { debug?: boolean reps?: number profile: boolean + bn128: bn128 } = { forkConfigVM: FORK_CONFIG_VM, forkConfigTestSuite: FORK_CONFIG_TEST_SUITE, @@ -127,6 +131,7 @@ async function runTests() { debug: argv.debug, // BlockchainTests reps: argv.reps, // test repetitions profile: RUN_PROFILER, + bn128, } /** diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index a1992100ce..b45b38aa0f 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -92,6 +92,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes profilerOpts: { reportAfterBlock: options.profile, }, + bn128: options.bn128, }) // set up pre-state @@ -221,8 +222,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes throw e } - // await cacheDB._leveldb.close() - if (expectException !== false) { t.fail(`expected exception but test did not throw an exception: ${expectException}`) return @@ -242,7 +241,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const end = Date.now() const timeSpent = `${(end - begin) / 1000} secs` t.comment(`Time: ${timeSpent}`) - // await cacheDB._leveldb.close() // @ts-ignore Explicitly delete objects for memory optimization (early GC) common = blockchain = state = stateManager = vm = cacheDB = null // eslint-disable-line diff --git a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts index c4a0dd48ba..d54a12acd5 100644 --- a/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts +++ b/packages/vm/test/tester/runners/GeneralStateTestsRunner.ts @@ -84,6 +84,7 @@ async function runTestCase(options: any, testData: any, t: tape.Test) { common, blockchain, profilerOpts: { reportAfterTx: options.profile }, + bn128: options.bn128, }) await setupPreConditions(vm.stateManager, testData)