From ce100c1ff63402d6a1a8db7c2a88e053e5b7434d Mon Sep 17 00:00:00 2001 From: holgerd77 Date: Wed, 5 Jun 2019 14:53:06 +0200 Subject: [PATCH 1/4] Bumped ethereumjs-common from 1.1.0 to 1.2.1, fix dependency for more reliable Istanbul development --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b234e8d8c..7d1f112c32 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "ethereumjs-account": "^3.0.0", "ethereumjs-block": "~2.2.0", "ethereumjs-blockchain": "^3.4.0", - "ethereumjs-common": "^1.1.0", + "ethereumjs-common": "1.2.1", "ethereumjs-util": "^6.1.0", "fake-merkle-patricia-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1", From 39bcf57666cd6b5224816dc594b0b24a7a3ee756 Mon Sep 17 00:00:00 2001 From: holgerd77 Date: Wed, 5 Jun 2019 15:15:13 +0200 Subject: [PATCH 2/4] Added istanbul HF to supportedHardforks, new Istanbul README section --- README.md | 22 ++++++++++++++++++++++ lib/index.ts | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba3d57c3c3..b8605f7b46 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,31 @@ The VM currently supports the following hardfork rules: - `Byzantium` - `Constantinople` - `Petersburg` (default) +- `Istanbul` (`DRAFT`) If you are still looking for a [Spurious Dragon](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md) compatible version of this library install the latest of the `2.2.x` series (see [Changelog](./CHANGELOG.md)). +##### Istanbul Harfork Support + +With the `v4.0.0` release we are starting to add implementations of EIPs being +candidates or accepted for inclusion within the `Istanbul` hardfork. You can +activate a preliminary `Istanbul` VM by using the `istanbul` `hardfork` option +flag. + +Currently supported `Istanbul` EIPs: + +- [EIP-1108](https://eips.ethereum.org/EIPS/eip-1803) (Candidate): `alt_bn128` Gas Cost Reductions, see PR [#540](https://github.com/ethereumjs/ethereumjs-vm/pull/540) + +Note that this is highly experimental and solely meant for experimental purposes, +since `Istanbul` scope is not yet finalized and most EIPs are still in a `DRAFT` +state and likely subject to updates and changes. + +A final `Istanbul` VM will be released along a major version bump to likely +`v5.0.0` or `v6.0.0`. + +Have a look at the corresponding issue to follow the discussion and current state on +[Istanbul planning](https://github.com/ethereumjs/ethereumjs-vm/issues/501). + # INSTALL `npm install ethereumjs-vm` diff --git a/lib/index.ts b/lib/index.ts index 92e5c4fcfb..ab7d000e9b 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -63,7 +63,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' (will throw on unsupported)] + * - `hardfork`: 'petersburg' [supported: 'byzantium', 'constantinople', 'petersburg', 'istanbul' (DRAFT) (will throw on unsupported)] * - `activatePrecompiles`: false * - `allowUnlimitedContractSize`: false [ONLY set to `true` during debugging] */ @@ -83,7 +83,7 @@ export default class VM extends AsyncEventEmitter { } else { const chain = opts.chain ? opts.chain : 'mainnet' const hardfork = opts.hardfork ? opts.hardfork : 'petersburg' - const supportedHardforks = ['byzantium', 'constantinople', 'petersburg'] + const supportedHardforks = ['byzantium', 'constantinople', 'petersburg', 'istanbul'] this._common = new Common(chain, hardfork, supportedHardforks) } From 748cd1bac2140bcc1ac330b6e36b044431533c3d Mon Sep 17 00:00:00 2001 From: holgerd77 Date: Wed, 5 Jun 2019 15:26:01 +0200 Subject: [PATCH 3/4] Added Istanbul general and EIP-1108 specific test cases --- tests/api/istanbul/eip-1108.js | 50 ++++++++++++++++++++++++++++++++++ tests/api/istanbul/index.js | 12 ++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/api/istanbul/eip-1108.js create mode 100644 tests/api/istanbul/index.js diff --git a/tests/api/istanbul/eip-1108.js b/tests/api/istanbul/eip-1108.js new file mode 100644 index 0000000000..48751e4301 --- /dev/null +++ b/tests/api/istanbul/eip-1108.js @@ -0,0 +1,50 @@ +const BN = require('bn.js') +const tape = require('tape') +const Common = require('ethereumjs-common').default +const util = require('ethereumjs-util') +const VM = require('../../../dist/index').default +const { getPrecompile } = require('../../../dist/evm/precompiles') + +tape('Istanbul: EIP-1108 tests', (t) => { + t.test('ECADD', (st) => { + const common = new Common('mainnet', 'istanbul') + let vm = new VM({ common: common }) + let ECADD = getPrecompile('0000000000000000000000000000000000000006') + + let result = ECADD({ + data: Buffer.alloc(0), + gasLimit: new BN(0xffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 150, 'should use istanbul gas costs') + st.end() + }) + + t.test('ECMUL', (st) => { + const common = new Common('mainnet', 'istanbul') + let vm = new VM({ common: common }) + let ECMUL = getPrecompile('0000000000000000000000000000000000000007') + + let result = ECMUL({ + data: Buffer.alloc(0), + gasLimit: new BN(0xffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 6000, 'should use istanbul gas costs') + st.end() + }) + + t.test('ECPAIRING', (st) => { + const common = new Common('mainnet', 'istanbul') + let vm = new VM({ common: common }) + let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008') + + let result = ECPAIRING({ + data: Buffer.from('00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', 'hex'), + gasLimit: new BN(0xffffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 113000, 'should use petersburg gas costs (k ^= 2 pairings)') + st.end() + }) +}) diff --git a/tests/api/istanbul/index.js b/tests/api/istanbul/index.js new file mode 100644 index 0000000000..b839e01cd9 --- /dev/null +++ b/tests/api/istanbul/index.js @@ -0,0 +1,12 @@ +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 From adcfc76341030c8bdc06bebc1f0bbdbb691e4b18 Mon Sep 17 00:00:00 2001 From: holgerd77 Date: Wed, 5 Jun 2019 23:02:04 +0200 Subject: [PATCH 4/4] Added standard reference API tests for ECADD, ECMUL and ECPAIRING evm precompiles for Istanbul comparison --- tests/api/evm/precompiles/06-ecadd.js | 22 ++++++++++++++++++++++ tests/api/evm/precompiles/07-ecmul.js | 22 ++++++++++++++++++++++ tests/api/evm/precompiles/08-ecpairing.js | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 tests/api/evm/precompiles/06-ecadd.js create mode 100644 tests/api/evm/precompiles/07-ecmul.js create mode 100644 tests/api/evm/precompiles/08-ecpairing.js diff --git a/tests/api/evm/precompiles/06-ecadd.js b/tests/api/evm/precompiles/06-ecadd.js new file mode 100644 index 0000000000..a99cd65c2d --- /dev/null +++ b/tests/api/evm/precompiles/06-ecadd.js @@ -0,0 +1,22 @@ +const BN = require('bn.js') +const tape = require('tape') +const Common = require('ethereumjs-common').default +const util = require('ethereumjs-util') +const VM = require('../../../../dist/index').default +const { getPrecompile } = require('../../../../dist/evm/precompiles') + +tape('Precompiles: ECADD', (t) => { + t.test('ECADD', (st) => { + const common = new Common('mainnet', 'petersburg') + let vm = new VM({ common: common }) + let ECADD = getPrecompile('0000000000000000000000000000000000000006') + + let result = ECADD({ + data: Buffer.alloc(0), + gasLimit: new BN(0xffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 500, 'should use petersburg gas costs') + st.end() + }) +}) \ No newline at end of file diff --git a/tests/api/evm/precompiles/07-ecmul.js b/tests/api/evm/precompiles/07-ecmul.js new file mode 100644 index 0000000000..16cfc54587 --- /dev/null +++ b/tests/api/evm/precompiles/07-ecmul.js @@ -0,0 +1,22 @@ +const BN = require('bn.js') +const tape = require('tape') +const Common = require('ethereumjs-common').default +const util = require('ethereumjs-util') +const VM = require('../../../../dist/index').default +const { getPrecompile } = require('../../../../dist/evm/precompiles') + +tape('Precompiles: ECMUL', (t) => { + t.test('ECMUL', (st) => { + const common = new Common('mainnet', 'petersburg') + let vm = new VM({ common: common }) + let ECMUL = getPrecompile('0000000000000000000000000000000000000007') + + let result = ECMUL({ + data: Buffer.alloc(0), + gasLimit: new BN(0xffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 40000, 'should use petersburg gas costs') + st.end() + }) +}) \ No newline at end of file diff --git a/tests/api/evm/precompiles/08-ecpairing.js b/tests/api/evm/precompiles/08-ecpairing.js new file mode 100644 index 0000000000..71b8ee7490 --- /dev/null +++ b/tests/api/evm/precompiles/08-ecpairing.js @@ -0,0 +1,22 @@ +const BN = require('bn.js') +const tape = require('tape') +const Common = require('ethereumjs-common').default +const util = require('ethereumjs-util') +const VM = require('../../../../dist/index').default +const { getPrecompile } = require('../../../../dist/evm/precompiles') + +tape('Precompiles: ECPAIRING', (t) => { + t.test('ECPAIRING', (st) => { + const common = new Common('mainnet', 'petersburg') + let vm = new VM({ common: common }) + let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008') + + let result = ECPAIRING({ + data: Buffer.from('00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', 'hex'), + gasLimit: new BN(0xffffff), + _common: common + }) + st.deepEqual(result.gasUsed.toNumber(), 260000, 'should use petersburg gas costs (k ^= 2 pairings)') + st.end() + }) +}) \ No newline at end of file