diff --git a/packages/client/src/execution/vmexecution.ts b/packages/client/src/execution/vmexecution.ts index 87e73cd7e3..3b84ac4fef 100644 --- a/packages/client/src/execution/vmexecution.ts +++ b/packages/client/src/execution/vmexecution.ts @@ -296,11 +296,11 @@ export class VMExecution extends Execution { this.chain['_customGenesisState'] ?? getGenesis(Number(blockchain.common.chainId())) if ( !genesisState && - (this.vm instanceof DefaultStateManager || !this.config.statelessVerkle) + (!('generateCanonicalGenesis' in this.vm.stateManager) || !this.config.statelessVerkle) ) { throw new Error('genesisState not available') } else { - await this.vm.stateManager.generateCanonicalGenesis(genesisState) + await this.vm.stateManager.generateCanonicalGenesis!(genesisState) } } diff --git a/packages/client/src/rpc/modules/debug.ts b/packages/client/src/rpc/modules/debug.ts index f5387e5be4..f118b561a9 100644 --- a/packages/client/src/rpc/modules/debug.ts +++ b/packages/client/src/rpc/modules/debug.ts @@ -186,7 +186,13 @@ export class Debug { const memory = [] let storage = {} if (opts.disableStorage === false) { - storage = await vmCopy.stateManager.dumpStorage(step.address) + if (!('dumpStorage' in vmCopy.stateManager)) { + throw { + message: 'stateManager has no dumpStorage implementation', + code: INTERNAL_ERROR, + } + } + storage = await vmCopy.stateManager.dumpStorage!(step.address) } if (opts.enableMemory === true) { for (let x = 0; x < step.memoryWordCount; x++) { @@ -267,7 +273,13 @@ export class Debug { const memory = [] let storage = {} if (opts.disableStorage === false) { - storage = await vm.stateManager.dumpStorage(step.address) + if (!('dumpStorage' in vm.stateManager)) { + throw { + message: 'stateManager has no dumpStorage implementation', + code: INTERNAL_ERROR, + } + } + storage = await vm.stateManager.dumpStorage!(step.address) } if (opts.enableMemory === true) { for (let x = 0; x < step.memoryWordCount; x++) { @@ -354,13 +366,19 @@ export class Debug { const parentBlock = await this.chain.getBlock(block.header.parentHash) // Copy the VM and run transactions including the relevant transaction. const vmCopy = await this.vm.shallowCopy() + if (!('dumpStorageRange' in vmCopy.stateManager)) { + throw { + code: INTERNAL_ERROR, + message: 'stateManager has no dumpStorageRange implementation', + } + } await vmCopy.stateManager.setStateRoot(parentBlock.header.stateRoot) for (let i = 0; i <= txIndex; i++) { await runTx(vmCopy, { tx: block.transactions[i], block }) } // await here so that any error can be handled in the catch below for proper response - return vmCopy.stateManager.dumpStorageRange( + return vmCopy.stateManager.dumpStorageRange!( // Validator already verified that `account` and `startKey` are properly formatted. createAddressFromString(account), BigInt(startKey), diff --git a/packages/client/test/rpc/eth/estimateGas.spec.ts b/packages/client/test/rpc/eth/estimateGas.spec.ts index 507ad3fc5a..c3c7da94c8 100644 --- a/packages/client/test/rpc/eth/estimateGas.spec.ts +++ b/packages/client/test/rpc/eth/estimateGas.spec.ts @@ -39,7 +39,7 @@ describe( const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService assert.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) // genesis address with balance const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getBalance.spec.ts b/packages/client/test/rpc/eth/getBalance.spec.ts index 7796dd820e..8b03a6e546 100644 --- a/packages/client/test/rpc/eth/getBalance.spec.ts +++ b/packages/client/test/rpc/eth/getBalance.spec.ts @@ -32,7 +32,7 @@ describe( // since synchronizer.run() is not executed in the mock setup, // manually run stateManager.generateCanonicalGenesis() - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) // genesis address with balance const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts b/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts index 7848bd03fa..df9b14ceac 100644 --- a/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts +++ b/packages/client/test/rpc/eth/getBlockTransactionCountByNumber.spec.ts @@ -33,7 +33,7 @@ describe(method, () => { assert.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') @@ -80,7 +80,7 @@ describe(method, () => { assert.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getCode.spec.ts b/packages/client/test/rpc/eth/getCode.spec.ts index 4635e04cce..a580abc3c1 100644 --- a/packages/client/test/rpc/eth/getCode.spec.ts +++ b/packages/client/test/rpc/eth/getCode.spec.ts @@ -28,7 +28,7 @@ describe(method, () => { const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService assert.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) // genesis address const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/eth/getTransactionCount.spec.ts b/packages/client/test/rpc/eth/getTransactionCount.spec.ts index 42f68de423..334725ecca 100644 --- a/packages/client/test/rpc/eth/getTransactionCount.spec.ts +++ b/packages/client/test/rpc/eth/getTransactionCount.spec.ts @@ -40,7 +40,7 @@ describe(method, () => { // since synchronizer.run() is not executed in the mock setup, // manually run stateManager.generateCanonicalGenesis() - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) // a genesis address const address = createAddressFromString('0xccfd725760a68823ff1e062f4cc97e1360e8d997') diff --git a/packages/client/test/rpc/txpool/content.spec.ts b/packages/client/test/rpc/txpool/content.spec.ts index bf95e680fa..d62745c125 100644 --- a/packages/client/test/rpc/txpool/content.spec.ts +++ b/packages/client/test/rpc/txpool/content.spec.ts @@ -29,7 +29,7 @@ describe(method, () => { const { execution } = client.services.find((s) => s.name === 'eth') as FullEthereumService assert.notEqual(execution, undefined, 'should have valid execution') const { vm } = execution - await vm.stateManager.generateCanonicalGenesis(getGenesis(1)) + await vm.stateManager.generateCanonicalGenesis!(getGenesis(1)) const gasLimit = 2000000 const parent = await blockchain.getCanonicalHeadHeader() const block = createBlockFromBlockData( diff --git a/packages/common/src/interfaces.ts b/packages/common/src/interfaces.ts index e67fe0da76..1768e417b1 100644 --- a/packages/common/src/interfaces.ts +++ b/packages/common/src/interfaces.ts @@ -148,6 +148,9 @@ export interface AccessWitnessInterface { * */ export interface StateManagerInterface { + /* + * Core Access Functionality + */ // Account methods getAccount(address: Address): Promise putAccount(address: Address, account?: Account): Promise @@ -164,35 +167,46 @@ export interface StateManagerInterface { putStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise clearStorage(address: Address): Promise - // Checkpointing methods + /* + * Checkpointing Functionality + */ checkpoint(): Promise commit(): Promise revert(): Promise - // State root methods + /* + * State Root Functionality + */ getStateRoot(): Promise setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise hasStateRoot(root: Uint8Array): Promise // only used in client - // Other + /* + * Extra Functionality + * + * Optional non-essential methods, these methods should always be guarded + * on usage (check for existance) + */ + // Client RPC getProof?(address: Address, storageSlots: Uint8Array[]): Promise - shallowCopy(downlevelCaches?: boolean): StateManagerInterface - getAppliedKey?(address: Uint8Array): Uint8Array + dumpStorage?(address: Address): Promise + dumpStorageRange?(address: Address, startKey: bigint, limit: number): Promise - // Verkle (experimental) - checkChunkWitnessPresent?(contract: Address, programCounter: number): Promise -} - -export interface EVMStateManagerInterface extends StateManagerInterface { + /* + * EVM/VM Specific Functionality + */ originalStorageCache: { get(address: Address, key: Uint8Array): Promise clear(): void } + generateCanonicalGenesis?(initState: any): Promise // TODO make input more typesafe + // only Verkle/EIP-6800 (experimental) + checkChunkWitnessPresent?(contract: Address, programCounter: number): Promise + getAppliedKey?(address: Uint8Array): Uint8Array // only for preimages - dumpStorage(address: Address): Promise // only used in client - dumpStorageRange(address: Address, startKey: bigint, limit: number): Promise // only used in client - generateCanonicalGenesis(initState: any): Promise // TODO make input more typesafe - getProof(address: Address, storageSlots?: Uint8Array[]): Promise - - shallowCopy(downlevelCaches?: boolean): EVMStateManagerInterface + /* + * Utility + */ + clearCaches(): void + shallowCopy(downlevelCaches?: boolean): StateManagerInterface } diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 0bf58b430a..093339bd10 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -51,7 +51,7 @@ import type { ExecResult, bn128, } from './types.js' -import type { Common, EVMStateManagerInterface } from '@ethereumjs/common' +import type { Common, StateManagerInterface } from '@ethereumjs/common' const debug = debugDefault('evm:evm') const debugGas = debugDefault('evm:gas') @@ -95,7 +95,7 @@ export class EVM implements EVMInterface { public readonly common: Common public readonly events: AsyncEventEmitter - public stateManager: EVMStateManagerInterface + public stateManager: StateManagerInterface public blockchain: Blockchain public journal: Journal diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 55e776f271..ea3332427c 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -27,7 +27,7 @@ import type { EVM } from './evm.js' import type { Journal } from './journal.js' import type { AsyncOpHandler, Opcode, OpcodeMapEntry } from './opcodes/index.js' import type { Block, Blockchain, EOFEnv, EVMProfilerOpts, EVMResult, Log } from './types.js' -import type { AccessWitnessInterface, Common, EVMStateManagerInterface } from '@ethereumjs/common' +import type { AccessWitnessInterface, Common, StateManagerInterface } from '@ethereumjs/common' import type { Address, PrefixedHexString } from '@ethereumjs/util' const debugGas = debugDefault('evm:gas') @@ -86,7 +86,7 @@ export interface RunState { shouldDoJumpAnalysis: boolean validJumps: Uint8Array // array of values where validJumps[index] has value 0 (default), 1 (jumpdest), 2 (beginsub) cachedPushes: { [pc: number]: bigint } - stateManager: EVMStateManagerInterface + stateManager: StateManagerInterface blockchain: Blockchain env: Env messageGasLimit?: bigint // Cache value from `gas.ts` to save gas limit for a message call @@ -105,7 +105,7 @@ export interface InterpreterResult { export interface InterpreterStep { gasLeft: bigint gasRefund: bigint - stateManager: EVMStateManagerInterface + stateManager: StateManagerInterface stack: bigint[] pc: number depth: number @@ -128,7 +128,7 @@ export interface InterpreterStep { export class Interpreter { protected _vm: any protected _runState: RunState - protected _stateManager: EVMStateManagerInterface + protected _stateManager: StateManagerInterface protected common: Common public _evm: EVM public journal: Journal @@ -147,7 +147,7 @@ export class Interpreter { // TODO remove gasLeft as constructor argument constructor( evm: EVM, - stateManager: EVMStateManagerInterface, + stateManager: StateManagerInterface, blockchain: Blockchain, env: Env, gasLeft: bigint, diff --git a/packages/evm/src/journal.ts b/packages/evm/src/journal.ts index 9c17a3e861..c07884f620 100644 --- a/packages/evm/src/journal.ts +++ b/packages/evm/src/journal.ts @@ -10,7 +10,7 @@ import { import debugDefault from 'debug' import { hexToBytes } from 'ethereum-cryptography/utils' -import type { Common, EVMStateManagerInterface } from '@ethereumjs/common' +import type { Common, StateManagerInterface } from '@ethereumjs/common' import type { Account, PrefixedHexString } from '@ethereumjs/util' import type { Debugger } from 'debug' @@ -32,7 +32,7 @@ type JournalDiffItem = [Set, Map>, type JournalHeight = number export class Journal { - private stateManager: EVMStateManagerInterface + private stateManager: StateManagerInterface private common: Common private DEBUG: boolean private _debug: Debugger @@ -47,7 +47,7 @@ export class Journal { public accessList?: Map> public preimages?: Map - constructor(stateManager: EVMStateManagerInterface, common: Common) { + constructor(stateManager: StateManagerInterface, common: Common) { // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables // Additional window check is to prevent vite browser bundling (and potentially other) to break this.DEBUG = diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 4f001da07d..109b79129d 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -11,8 +11,8 @@ import type { PrecompileFunc } from './precompiles/types.js' import type { AccessWitnessInterface, Common, - EVMStateManagerInterface, ParamsDict, + StateManagerInterface, } from '@ethereumjs/common' import type { Account, Address, AsyncEventEmitter, PrefixedHexString } from '@ethereumjs/util' @@ -162,7 +162,7 @@ export interface EVMInterface { startReportingAccessList(): void startReportingPreimages?(): void } - stateManager: EVMStateManagerInterface + stateManager: StateManagerInterface precompiles: Map runCall(opts: EVMRunCallOpts): Promise runCode(opts: EVMRunCodeOpts): Promise @@ -312,7 +312,7 @@ export interface EVMOpts { * implementations for different needs (MPT-tree backed, RPC, experimental verkle) * which can be used by this option as a replacement. */ - stateManager?: EVMStateManagerInterface + stateManager?: StateManagerInterface /** * diff --git a/packages/statemanager/src/rpcStateManager.ts b/packages/statemanager/src/rpcStateManager.ts index 71ef9d06ef..6843ec0d7e 100644 --- a/packages/statemanager/src/rpcStateManager.ts +++ b/packages/statemanager/src/rpcStateManager.ts @@ -19,18 +19,13 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' import { AccountCache, CacheType, OriginalStorageCache, StorageCache } from './cache/index.js' import type { Proof, RPCStateManagerOpts } from './index.js' -import type { - AccountFields, - EVMStateManagerInterface, - StorageDump, - StorageRange, -} from '@ethereumjs/common' +import type { AccountFields, StateManagerInterface, StorageDump } from '@ethereumjs/common' import type { Address, PrefixedHexString } from '@ethereumjs/util' import type { Debugger } from 'debug' const KECCAK256_RLP_EMPTY_ACCOUNT = RLP.encode(new Account().serialize()).slice(2) -export class RPCStateManager implements EVMStateManagerInterface { +export class RPCStateManager implements StateManagerInterface { protected _provider: string protected _contractCache: Map protected _storageCache: StorageCache @@ -213,11 +208,6 @@ export class RPCStateManager implements EVMStateManagerInterface { return Promise.resolve(dump) } - dumpStorageRange(_address: Address, _startKey: bigint, _limit: number): Promise { - // TODO: Implement. - return Promise.reject() - } - /** * Checks if an `account` exists at `address` * @param address - Address of the `account` to check @@ -436,10 +426,6 @@ export class RPCStateManager implements EVMStateManagerInterface { hasStateRoot = () => { throw new Error('function not implemented') } - - generateCanonicalGenesis(_initState: any): Promise { - return Promise.resolve() - } } export class RPCBlockChain { diff --git a/packages/statemanager/src/simpleStateManager.ts b/packages/statemanager/src/simpleStateManager.ts index 8169bbb1b5..8c58c616ba 100644 --- a/packages/statemanager/src/simpleStateManager.ts +++ b/packages/statemanager/src/simpleStateManager.ts @@ -4,14 +4,7 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' import { OriginalStorageCache } from './cache/originalStorageCache.js' import type { SimpleStateManagerOpts } from './index.js' -import type { - AccountFields, - Common, - EVMStateManagerInterface, - Proof, - StorageDump, - StorageRange, -} from '@ethereumjs/common' +import type { AccountFields, Common, StateManagerInterface } from '@ethereumjs/common' import type { Address, PrefixedHexString } from '@ethereumjs/util' /** @@ -29,7 +22,7 @@ import type { Address, PrefixedHexString } from '@ethereumjs/util' * For a more full fledged and MPT-backed state manager implementation * have a look at the `@ethereumjs/statemanager` package. */ -export class SimpleStateManager implements EVMStateManagerInterface { +export class SimpleStateManager implements StateManagerInterface { public accountStack: Map[] = [] public codeStack: Map[] = [] public storageStack: Map[] = [] @@ -125,6 +118,8 @@ export class SimpleStateManager implements EVMStateManagerInterface { this.topStorageStack().set(`${address.toString()}_${bytesToHex(key)}`, value) } + async clearStorage(): Promise {} + async checkpoint(): Promise { this.checkpointSync() } @@ -143,7 +138,7 @@ export class SimpleStateManager implements EVMStateManagerInterface { async flush(): Promise {} clearCaches(): void {} - shallowCopy(): EVMStateManagerInterface { + shallowCopy(): StateManagerInterface { const copy = new SimpleStateManager({ common: this.common }) for (let i = 0; i < this.accountStack.length; i++) { copy.accountStack.push(new Map(this.accountStack[i])) @@ -163,24 +158,4 @@ export class SimpleStateManager implements EVMStateManagerInterface { hasStateRoot(): Promise { throw new Error('Method not implemented.') } - - // Only goes for long term create situations, skip - async clearStorage(): Promise {} - - // Only "core" methods implemented - dumpStorage(): Promise { - throw new Error('Method not implemented.') - } - dumpStorageRange(): Promise { - throw new Error('Method not implemented.') - } - generateCanonicalGenesis(): Promise { - throw new Error('Method not implemented.') - } - getProof(): Promise { - throw new Error('Method not implemented.') - } - getAppliedKey?(): Uint8Array { - throw new Error('Method not implemented.') - } } diff --git a/packages/statemanager/src/stateManager.ts b/packages/statemanager/src/stateManager.ts index 3f4f4feff4..79c75a34f7 100644 --- a/packages/statemanager/src/stateManager.ts +++ b/packages/statemanager/src/stateManager.ts @@ -38,8 +38,8 @@ import { CODEHASH_PREFIX, type CacheSettings, type DefaultStateManagerOpts } fro import type { StorageProof } from './index.js' import type { AccountFields, - EVMStateManagerInterface, Proof, + StateManagerInterface, StorageDump, StorageRange, } from '@ethereumjs/common' @@ -61,7 +61,7 @@ import type { Debugger } from 'debug' * package which might be an alternative to this implementation * for many basic use cases. */ -export class DefaultStateManager implements EVMStateManagerInterface { +export class DefaultStateManager implements StateManagerInterface { protected _debug: Debugger protected _accountCache?: AccountCache protected _storageCache?: StorageCache diff --git a/packages/statemanager/src/statelessVerkleStateManager.ts b/packages/statemanager/src/statelessVerkleStateManager.ts index 589d868505..4fc1d33211 100644 --- a/packages/statemanager/src/statelessVerkleStateManager.ts +++ b/packages/statemanager/src/statelessVerkleStateManager.ts @@ -36,13 +36,7 @@ import { import type { AccessedStateWithAddress } from './accessWitness.js' import type { CacheSettings, StatelessVerkleStateManagerOpts, VerkleState } from './index.js' import type { DefaultStateManager } from './stateManager.js' -import type { - AccountFields, - EVMStateManagerInterface, - Proof, - StorageDump, - StorageRange, -} from '@ethereumjs/common' +import type { AccountFields, Proof, StateManagerInterface } from '@ethereumjs/common' import type { Address, PrefixedHexString, @@ -72,7 +66,7 @@ const ZEROVALUE = '0x00000000000000000000000000000000000000000000000000000000000 * to fetch data requested by the the VM. * */ -export class StatelessVerkleStateManager implements EVMStateManagerInterface { +export class StatelessVerkleStateManager implements StateManagerInterface { _accountCache?: AccountCache _storageCache?: StorageCache _codeCache?: CodeCache @@ -259,7 +253,7 @@ export class StatelessVerkleStateManager implements EVMStateManagerInterface { * at the last fully committed point, i.e. as if all current * checkpoints were reverted. */ - shallowCopy(): EVMStateManagerInterface { + shallowCopy(): StateManagerInterface { const stateManager = new StatelessVerkleStateManager({ verkleCrypto: this.verkleCrypto }) return stateManager } @@ -847,21 +841,6 @@ export class StatelessVerkleStateManager implements EVMStateManagerInterface { this._cachedStateRoot = stateRoot } - /** - * Dumps the RLP-encoded storage values for an `account` specified by `address`. - * @param address - The address of the `account` to return storage for - * @returns {Promise} - The state of the account as an `Object` map. - * Keys are are the storage keys, values are the storage values as strings. - * Both are represented as hex strings without the `0x` prefix. - */ - async dumpStorage(_: Address): Promise { - throw Error('not implemented') - } - - dumpStorageRange(_: Address, __: bigint, ___: number): Promise { - throw Error('not implemented') - } - /** * Clears all underlying caches */ @@ -871,11 +850,11 @@ export class StatelessVerkleStateManager implements EVMStateManagerInterface { this._storageCache?.clear() } + // TODO: Removing this causes a Kaustinen6 test in client to fail + // Seems to point to a more general (non-severe) bug and can likely be fixed + // by having the `statelessVerkle` config option more properly set by the + // test for the check in the VM execution to call into this method generateCanonicalGenesis(_initState: any): Promise { return Promise.resolve() } - - getAppliedKey(_: Uint8Array): Uint8Array { - throw Error('not implemented') - } } diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index c31c17547b..7b35718782 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -1,14 +1,13 @@ import type { Bloom } from './bloom/index.js' import type { Block, BlockOptions, HeaderData } from '@ethereumjs/block' import type { BlockchainInterface } from '@ethereumjs/blockchain' -import type { Common, EVMStateManagerInterface, ParamsDict } from '@ethereumjs/common' +import type { Common, ParamsDict, StateManagerInterface } from '@ethereumjs/common' import type { EVMInterface, EVMOpts, EVMResult, Log } from '@ethereumjs/evm' import type { AccessList, TypedTransaction } from '@ethereumjs/tx' import type { BigIntLike, CLRequest, CLRequestType, - GenesisState, PrefixedHexString, WithdrawalData, } from '@ethereumjs/util' @@ -118,7 +117,7 @@ export interface VMOpts { /** * A {@link StateManager} instance to use as the state store */ - stateManager?: EVMStateManagerInterface + stateManager?: StateManagerInterface /** * A {@link Blockchain} object for storing/retrieving blocks */ @@ -137,11 +136,6 @@ export interface VMOpts { * Default: `false` */ activatePrecompiles?: boolean - /** - * A genesisState to generate canonical genesis for the "in-house" created stateManager if external - * stateManager not provided for the VM, defaults to an empty state - */ - genesisState?: GenesisState /** * Set the hardfork either by timestamp (for HFs from Shanghai onwards) or by block number diff --git a/packages/vm/src/vm.ts b/packages/vm/src/vm.ts index 9050c6050b..7cd54434c3 100644 --- a/packages/vm/src/vm.ts +++ b/packages/vm/src/vm.ts @@ -14,7 +14,7 @@ import { paramsVM } from './params.js' import type { VMEvents, VMOpts } from './types.js' import type { BlockchainInterface } from '@ethereumjs/blockchain' -import type { EVMStateManagerInterface } from '@ethereumjs/common' +import type { StateManagerInterface } from '@ethereumjs/common' import type { EVMInterface } from '@ethereumjs/evm' import type { BigIntLike } from '@ethereumjs/util' @@ -28,7 +28,7 @@ export class VM { /** * The StateManager used by the VM */ - readonly stateManager: EVMStateManagerInterface + readonly stateManager: StateManagerInterface /** * The blockchain the VM operates on @@ -89,11 +89,6 @@ export class VM { opts.blockchain = await createBlockchain({ common: opts.common }) } - const genesisState = opts.genesisState ?? {} - if (opts.genesisState !== undefined) { - await opts.stateManager.generateCanonicalGenesis(genesisState) - } - if (opts.profilerOpts !== undefined) { const profilerOpts = opts.profilerOpts if (profilerOpts.reportAfterBlock === true && profilerOpts.reportAfterTx === true) { diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index 097d4561ca..50a704a2d8 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -130,7 +130,7 @@ describe('EIP4895 tests', () => { it('EIP4895: state updation should exclude 0 amount updates', async () => { const vm = await VM.create({ common }) - await vm.stateManager.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) + await vm.stateManager.generateCanonicalGenesis!(parseGethGenesisState(genesisJSON)) const preState = bytesToHex(await vm.stateManager.getStateRoot()) assert.equal( preState, @@ -208,7 +208,7 @@ describe('EIP4895 tests', () => { 'correct state root should be generated', ) const vm = await VM.create({ common, blockchain }) - await vm.stateManager.generateCanonicalGenesis(parseGethGenesisState(genesisJSON)) + await vm.stateManager.generateCanonicalGenesis!(parseGethGenesisState(genesisJSON)) const vmCopy = await vm.shallowCopy() const gethBlockBufferArray = decode(hexToBytes(gethWithdrawals8BlockRlp)) diff --git a/packages/vm/test/api/customChain.spec.ts b/packages/vm/test/api/customChain.spec.ts index c064d4bf0c..16a68310d2 100644 --- a/packages/vm/test/api/customChain.spec.ts +++ b/packages/vm/test/api/customChain.spec.ts @@ -70,7 +70,8 @@ const privateKey = hexToBytes('0xe331b6d69882b4cb4ea581d88e0b604039a3de5967688d3 describe('VM initialized with custom state', () => { it('should transfer eth from already existent account', async () => { const blockchain = await createBlockchain({ common, genesisState }) - const vm = await VM.create({ blockchain, common, genesisState }) + const vm = await VM.create({ blockchain, common }) + await vm.stateManager.generateCanonicalGenesis!(genesisState) const to = '0x00000000000000000000000000000000000000ff' const tx = createTxFromTxData( @@ -98,7 +99,8 @@ describe('VM initialized with custom state', () => { it('should retrieve value from storage', async () => { const blockchain = await createBlockchain({ common, genesisState }) common.setHardfork(Hardfork.London) - const vm = await VM.create({ blockchain, common, genesisState }) + const vm = await VM.create({ blockchain, common }) + await vm.stateManager.generateCanonicalGenesis!(genesisState) const sigHash = new Interface(['function retrieve()']).getSighash( 'retrieve', ) as PrefixedHexString @@ -119,10 +121,10 @@ describe('VM initialized with custom state', () => { const customChains = [testnetMerge] as ChainConfig[] const common = new Common({ chain: 'testnetMerge', hardfork: Hardfork.Istanbul, customChains }) - let vm = await VM.create({ common, setHardfork: true, genesisState: {} }) + let vm = await VM.create({ common, setHardfork: true }) assert.equal((vm as any)._setHardfork, true, 'should set setHardfork option') - vm = await VM.create({ common, setHardfork: 5001, genesisState: {} }) + vm = await VM.create({ common, setHardfork: 5001 }) assert.equal((vm as any)._setHardfork, BigInt(5001), 'should set setHardfork option') }) }) diff --git a/packages/vm/test/util.ts b/packages/vm/test/util.ts index 98d877ec09..c2ace8fa1e 100644 --- a/packages/vm/test/util.ts +++ b/packages/vm/test/util.ts @@ -26,7 +26,7 @@ import { import { keccak256 } from 'ethereum-cryptography/keccak' import type { BlockOptions } from '@ethereumjs/block' -import type { EVMStateManagerInterface } from '@ethereumjs/common' +import type { StateManagerInterface } from '@ethereumjs/common' import type { AccessListEIP2930Transaction, BlobEIP4844Transaction, @@ -363,7 +363,7 @@ export function makeBlockFromEnv(env: any, opts?: BlockOptions): Block { * @param state - the state DB/trie * @param testData - JSON from tests repo */ -export async function setupPreConditions(state: EVMStateManagerInterface, testData: any) { +export async function setupPreConditions(state: StateManagerInterface, testData: any) { await state.checkpoint() for (const addressStr of Object.keys(testData.pre)) { const { nonce, balance, code, storage } = testData.pre[addressStr]