diff --git a/packages/vm/CHANGELOG.md b/packages/vm/CHANGELOG.md index 805a9f11aac..e7b0e363a9c 100644 --- a/packages/vm/CHANGELOG.md +++ b/packages/vm/CHANGELOG.md @@ -20,7 +20,7 @@ Please update your library references accordingly or install with: npm i @ethereumjs/vm ``` -### Support for all current Hardforks +### Support for all current Hardforks / HF API Changes This is the first release of the VM which supports all hardforks currently applied on mainnet starting with the support of the @@ -40,13 +40,21 @@ The following HFs have been added: PR [#828](https://github.com/ethereumjs/ethereumjs-vm/pull/828) A VM with the specific HF rules (on the chain provided) can be instantiated -by passing in a `Common` instance or by setting HF and chain directly with: +by passing in a `Common` instance: ```typescript -import VM from 'ethereumjs-vm' -const vm = new VM({ chain: 'mainnet', hardfork: 'spuriousDragon' }) +import VM from '@ethereumjs/vm' +import Common from '@ethereumjs/common' + +const common = new Common({ chain: 'mainnet', hardfork: 'spuriousDragon' }) +const vm = new VM({ common }) ``` +**Breaking**: Please note that the options to directly pass in +`chain` and `hardfork` strings have been removed to simpify the API. +Providing a `Common` instance is now the only way to change +the chain setup, see PR [#863](https://github.com/ethereumjs/ethereumjs-vm/pull/863) + ### Berlin HF Support / HF-independent EIPs This releases adds support for subroutines (`EIP-2315`) which gets diff --git a/packages/vm/lib/index.ts b/packages/vm/lib/index.ts index d3c157b4708..b11e463969f 100644 --- a/packages/vm/lib/index.ts +++ b/packages/vm/lib/index.ts @@ -20,13 +20,17 @@ const promisify = require('util.promisify') */ export interface VMOpts { /** - * The chain the VM operates on - */ - chain?: string - /** - * Hardfork rules to be used + * Use a [common](https://github.com/ethereumjs/ethereumjs-vm/packages/common) instance + * if you want to change the network setup + * + * If no common instance is provided the VM defaults to the following chain setup: + * + * Chain: `mainnet` + * Hardfork: `petersburg` + * + * Hardfork rules are implemented up to the 'muirGlacier' hardfork. */ - hardfork?: string + common?: Common /** * A [[StateManager]] instance to use as the state store (Beta API) */ @@ -49,17 +53,17 @@ export interface VMOpts { * * Setting this to true has the effect of precompiled contracts' gas costs matching mainnet's from * the very first call, which is intended for testing networks. + * + * Default: `false` */ activatePrecompiles?: boolean /** - * Allows unlimited contract sizes while debugging. By setting this to `true`, the check for contract size limit of 24KB (see [EIP-170](https://git.io/vxZkK)) is bypassed + * Allows unlimited contract sizes while debugging. By setting this to `true`, the check for + * contract size limit of 24KB (see [EIP-170](https://git.io/vxZkK)) is bypassed. + * + * Default: `false` [ONLY set to `true` during debugging] */ allowUnlimitedContractSize?: boolean - /** - * Use a [common](https://github.com/ethereumjs/ethereumjs-vm/packages/common) instance or a combination - * on the `chain` and `hardfork` options if you want to change the network setup - */ - common?: Common /** * Selected EIPs which can be activated on the VM, please use an array for instantiation * (e.g. `eips: [ 'EIP2537', ]) @@ -102,11 +106,7 @@ export default class VM extends AsyncEventEmitter { /** * Instantiates a new [[VM]] Object. - * @param opts - Default values for the options are: - * - `chain`: 'mainnet' - * - `hardfork`: 'petersburg' [supported: 'byzantium', 'constantinople', 'petersburg', 'istanbul' (DRAFT) (will throw on unsupported)] - * - `activatePrecompiles`: false - * - `allowUnlimitedContractSize`: false [ONLY set to `true` during debugging] + * @param opts */ constructor(opts: VMOpts = {}) { super() @@ -114,16 +114,10 @@ export default class VM extends AsyncEventEmitter { this.opts = opts if (opts.common) { - if (opts.chain || opts.hardfork) { - throw new Error( - 'You can only instantiate the VM class with one of: opts.common, or opts.chain and opts.hardfork', - ) - } - this._common = opts.common } else { - const chain = opts.chain ? opts.chain : 'mainnet' - const hardfork = opts.hardfork ? opts.hardfork : 'petersburg' + const DEFAULT_CHAIN = 'mainnet' + const DEFAULT_HARDFORK = 'petersburg' const supportedHardforks = [ 'chainstart', 'homestead', @@ -138,7 +132,11 @@ export default class VM extends AsyncEventEmitter { 'berlin', ] - this._common = new Common({ chain, hardfork, supportedHardforks }) + this._common = new Common({ + chain: DEFAULT_CHAIN, + hardfork: DEFAULT_HARDFORK, + supportedHardforks, + }) } // EIPs diff --git a/packages/vm/tests/GeneralStateTestsRunner.js b/packages/vm/tests/GeneralStateTestsRunner.js index 3391729f69a..f03153ed198 100644 --- a/packages/vm/tests/GeneralStateTestsRunner.js +++ b/packages/vm/tests/GeneralStateTestsRunner.js @@ -1,6 +1,7 @@ const { setupPreConditions, makeTx, makeBlockFromEnv } = require('./util') const Trie = require('merkle-patricia-tree').SecureTrie const { BN } = require('ethereumjs-util') +const { default: Common } = require('@ethereumjs/common') const Account = require('@ethereumjs/account').default function parseTestCases(forkConfigTestSuite, testData, data, gasLimit, value) { @@ -49,9 +50,10 @@ async function runTestCase(options, testData, t) { } else { VM = require('../lib/index').default } + const common = new Common({ chain: 'mainnet', hardfork: options.forkConfigVM }) vm = new VM({ state, - hardfork: options.forkConfigVM, + common: common, }) await setupPreConditions(vm.stateManager._trie, testData) diff --git a/packages/vm/tests/api/index.js b/packages/vm/tests/api/index.js index 31a4979332b..be37976c188 100644 --- a/packages/vm/tests/api/index.js +++ b/packages/vm/tests/api/index.js @@ -39,16 +39,6 @@ tape('VM with default blockchain', (t) => { st.end() }) - t.test('should only accept common or chain and fork', (st) => { - const common = new Common({ chain: 'mainnet' }) - - st.throws(() => new VM({ chain: 'a', common })) - st.throws(() => new VM({ hardfork: 'a', common })) - st.throws(() => new VM({ chain: 'a', hardfork: 'a', common })) - - st.end() - }) - t.test('should accept a common object as option', async (st) => { const common = new Common({ chain: 'mainnet', hardfork: 'istanbul' }) @@ -60,12 +50,14 @@ tape('VM with default blockchain', (t) => { }) t.test('should only accept valid chain and fork', async (st) => { - let vm = new VM({ chain: 'ropsten', hardfork: 'byzantium' }) + let common = new Common({ chain: 'ropsten', hardfork: 'byzantium' }) + let vm = new VM({ common }) await vm.init() st.equal(vm.stateManager._common.param('gasPrices', 'ecAdd'), 500) try { - vm = new VM({ chain: 'mainchain', hardfork: 'homestead' }) + common = new Common({ chain: 'mainchain', hardfork: 'homestead' }) + vm = new VM({ common }) st.fail('should have failed for invalid chain') } catch (e) { st.ok(e.message.includes('not supported')) diff --git a/packages/vm/tests/api/istanbul/index.js b/packages/vm/tests/api/istanbul/index.js deleted file mode 100644 index b839e01cd93..00000000000 --- a/packages/vm/tests/api/istanbul/index.js +++ /dev/null @@ -1,12 +0,0 @@ -const tape = require('tape') -const util = require('ethereumjs-util') -const VM = require('../../../dist/index').default - -tape('General Istanbul VM tests', (t) => { - t.test('should accept istanbul harfork option', (st) => { - const vm = new VM({ hardfork: 'istanbul' }) - st.ok(vm.stateManager) - st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') - st.end() - }) -}) \ No newline at end of file diff --git a/packages/vm/tests/api/muirGlacier/index.js b/packages/vm/tests/api/muirGlacier/index.js index b142be57f18..22a6e328df8 100644 --- a/packages/vm/tests/api/muirGlacier/index.js +++ b/packages/vm/tests/api/muirGlacier/index.js @@ -1,10 +1,11 @@ const tape = require('tape') const util = require('ethereumjs-util') +const { default: Common } = require('@ethereumjs/common') const VM = require('../../../dist/index').default tape('General MuirGlacier VM tests', (t) => { t.test('should accept muirGlacier harfork option for supported chains', (st) => { - let vm = new VM({ hardfork: 'muirGlacier' }) + let vm = new VM(new Common({ chain: 'mainnet', hardfork: 'muirGlacier' })) st.ok(vm.stateManager) st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') st.end() diff --git a/packages/vm/tests/api/runCall.js b/packages/vm/tests/api/runCall.js index 5f007480701..440bdc82028 100644 --- a/packages/vm/tests/api/runCall.js +++ b/packages/vm/tests/api/runCall.js @@ -25,7 +25,8 @@ tape('Constantinople: EIP-1014 CREATE2 creates the right contract address', asyn const caller = Buffer.from('00000000000000000000000000000000000000ee', 'hex') // caller addres const contractAddress = Buffer.from('00000000000000000000000000000000000000ff', 'hex') // contract address // setup the vm - const vm = new VM({ chain: 'mainnet', hardfork: 'constantinople'}) + const common = new Common({ chain: 'mainnet', hardfork: 'constantinople'}) + const vm = new VM({ common }) const code = "3460008080F560005260206000F3" /* code: remarks: (top of the stack is at the zero index) @@ -83,8 +84,8 @@ tape('Byzantium cannot access Constantinople opcodes', async (t) => { const caller = Buffer.from('00000000000000000000000000000000000000ee', 'hex') // caller addres const contractAddress = Buffer.from('00000000000000000000000000000000000000ff', 'hex') // contract address // setup the vm - const vmByzantium = new VM({ chain: 'mainnet', hardfork: 'byzantium'}) - const vmConstantinople = new VM({ chain: 'mainnet', hardfork: 'constantinople'}) + const vmByzantium = new VM(new Common({ chain: 'mainnet', hardfork: 'byzantium'})) + const vmConstantinople = new VM(new Common({ chain: 'mainnet', hardfork: 'constantinople'})) const code = "600160011B00" /* code: remarks: (top of the stack is at the zero index)