From 189d0689454427d2dfe1753493da3f47fac9f807 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 11:43:48 +0200 Subject: [PATCH 01/10] Drop babel deps, add initial typescript config --- lib/state/stateManager.js | 4 ++-- package.json | 11 ++++------- tsconfig.json | 11 +++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 tsconfig.json diff --git a/lib/state/stateManager.js b/lib/state/stateManager.js index a2752f47a1..c7c1c1e8fa 100644 --- a/lib/state/stateManager.js +++ b/lib/state/stateManager.js @@ -1,4 +1,4 @@ -const Buffer = require('safe-buffer').Buffer +const Set = require('core-js-pure/es/set') const Trie = require('merkle-patricia-tree/secure.js') const Common = require('ethereumjs-common').default const { genesisStateByName } = require('ethereumjs-common/dist/genesisStates') @@ -281,7 +281,7 @@ module.exports = class StateManager { checkpoint (cb) { this._trie.checkpoint() this._cache.checkpoint() - this._touchedStack.push(new Set([...this._touched])) + this._touchedStack.push(new Set(Array.from(this._touched))) this._checkpointCount++ cb() } diff --git a/package.json b/package.json index 39c12814b1..6323086946 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "test": "echo \"[INFO] Generic test cmd not used. See package.json for more specific test run cmds.\"", "lint": "standard", "prepublishOnly": "npm run lint && npm run build:dist && npm run testBuildIntegrity", - "build:dist": "babel lib/ -d dist/", + "build:dist": "tsc", "build:docs": "documentation build ./lib/index.js ./lib/runBlockchain.js ./lib/runBlock.js ./lib/runTx.js ./lib/runCode.js ./lib/runCall.js --format md --shallow > ./docs/index.md", "formatTest": "node ./scripts/formatTest" }, @@ -35,9 +35,9 @@ "VM" ], "dependencies": { - "@babel/runtime": "^7.4.0", "async": "^2.1.2", "async-eventemitter": "^0.2.2", + "core-js-pure": "^3.0.1", "ethereumjs-account": "^2.0.3", "ethereumjs-block": "~2.2.0", "ethereumjs-blockchain": "^3.4.0", @@ -51,10 +51,6 @@ "util.promisify": "^1.0.0" }, "devDependencies": { - "@babel/cli": "^7.2.3", - "@babel/core": "^7.4.0", - "@babel/plugin-transform-runtime": "^7.4.0", - "@babel/preset-env": "^7.4.1", "browserify": "^16.2.3", "coveralls": "^3.0.0", "documentation": "^8.1.2", @@ -72,7 +68,8 @@ "nyc": "^12.0.2", "standard": "^10.0.0", "tap-spec": "^5.0.0", - "tape": "4.6.3" + "tape": "4.6.3", + "typescript": "^3.4.3" }, "author": "mjbecze ", "contributors": [ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..adbb5263eb --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "allowJs": true, + "target": "es5", + "lib": ["es2018"] + }, + "include": [ + "./lib/**/*" + ] +} From 1ec05bae47aa5c54f7eb4b105e6a6eb8741f8131 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 12:04:24 +0200 Subject: [PATCH 02/10] Add prettier as dep, add format scripts --- .prettierignore | 6 ++++++ package.json | 4 ++++ tsconfig.json | 16 +++++++--------- 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..95b8087d17 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +.vscode +package.json +dist +.nyc_output +*.json diff --git a/package.json b/package.json index 6323086946..f0581b2d3f 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "testAPI:browser": "karma start karma.conf.js", "test": "echo \"[INFO] Generic test cmd not used. See package.json for more specific test run cmds.\"", "lint": "standard", + "format": "ethereumjs-config-format", + "format-fix": "ethereumjs-config-format-fix", "prepublishOnly": "npm run lint && npm run build:dist && npm run testBuildIntegrity", "build:dist": "tsc", "build:docs": "documentation build ./lib/index.js ./lib/runBlockchain.js ./lib/runBlock.js ./lib/runTx.js ./lib/runCode.js ./lib/runCall.js --format md --shallow > ./docs/index.md", @@ -51,6 +53,7 @@ "util.promisify": "^1.0.0" }, "devDependencies": { + "@ethereumjs/config-prettier": "^1.1.1", "browserify": "^16.2.3", "coveralls": "^3.0.0", "documentation": "^8.1.2", @@ -66,6 +69,7 @@ "level-mem": "^3.0.1", "minimist": "^1.1.1", "nyc": "^12.0.2", + "prettier": "^1.16.4", "standard": "^10.0.0", "tap-spec": "^5.0.0", "tape": "4.6.3", diff --git a/tsconfig.json b/tsconfig.json index adbb5263eb..ed46006aaa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,9 @@ { - "compilerOptions": { - "outDir": "./dist", - "allowJs": true, - "target": "es5", - "lib": ["es2018"] - }, - "include": [ - "./lib/**/*" - ] + "compilerOptions": { + "outDir": "./dist", + "allowJs": true, + "target": "es5", + "lib": ["es2018"] + }, + "include": ["./lib/**/*"] } From 0272139d144fae879d9692c81bc93f15f7bb41f9 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 12:17:21 +0200 Subject: [PATCH 03/10] Mv bloom/index.js to bloom/index.ts --- lib/bloom/{index.js => index.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/bloom/{index.js => index.ts} (100%) diff --git a/lib/bloom/index.js b/lib/bloom/index.ts similarity index 100% rename from lib/bloom/index.js rename to lib/bloom/index.ts From 1d9786d67d71c4c00813e0ce0b8b6d4af91d1152 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 13:01:07 +0200 Subject: [PATCH 04/10] Migrate bloom to ts, limit its api to buffers --- lib/bloom/index.ts | 36 ++++++++++++++++++-------------- lib/runBlock.js | 2 +- lib/runTx.js | 2 +- package.json | 7 +++++-- tests/api/bloom.js | 24 ++++++++++----------- tests/api/evm/memory.js | 2 +- tests/api/evm/stack.js | 2 +- tests/api/freeLogs.js | 2 +- tests/api/index.js | 2 +- tests/api/runBlock.js | 4 ++-- tests/api/runBlockchain.js | 4 ++-- tests/api/runCode.js | 2 +- tests/api/runJit.js | 10 +++++---- tests/api/runTx.js | 6 +++--- tests/api/state/cache.js | 2 +- tests/api/state/stateManager.js | 2 +- tests/api/state/storageReader.js | 2 +- tests/api/utils.js | 2 +- tsconfig.json | 4 +++- 19 files changed, 64 insertions(+), 53 deletions(-) diff --git a/lib/bloom/index.ts b/lib/bloom/index.ts index d65b77f2b0..d9b4ada2e8 100644 --- a/lib/bloom/index.ts +++ b/lib/bloom/index.ts @@ -1,17 +1,19 @@ -const assert = require('assert') -const utils = require('ethereumjs-util') +import * as assert from 'assert' +import { zeros, keccak256 } from 'ethereumjs-util' const BYTE_SIZE = 256 -module.exports = class Bloom { +export default class Bloom { + bitvector: Buffer + /** * Represents a Bloom * @constructor * @param {Buffer} bitvector */ - constructor (bitvector) { + constructor (bitvector: Buffer) { if (!bitvector) { - this.bitvector = utils.zeros(BYTE_SIZE) + this.bitvector = zeros(BYTE_SIZE) } else { assert(bitvector.length === BYTE_SIZE, 'bitvectors must be 2048 bits long') this.bitvector = bitvector @@ -21,10 +23,11 @@ module.exports = class Bloom { /** * adds an element to a bit vector of a 64 byte bloom filter * @method add - * @param {Buffer|Array|String|Number} e the element to add + * @param {Buffer} e the element to add */ - add (e) { - e = utils.keccak256(e) + add (e: Buffer) { + assert(Buffer.isBuffer(e), 'Element should be buffer') + e = keccak256(e) const mask = 2047 // binary 11111111111 for (let i = 0; i < 3; i++) { @@ -39,11 +42,12 @@ module.exports = class Bloom { /** * checks if an element is in the bloom * @method check - * @param {Buffer|Array|String|Number} e the element to check + * @param {Buffer} e the element to check * @returns {boolean} Returns {@code true} if the element is in the bloom */ - check (e) { - e = utils.keccak256(e) + check (e: Buffer): boolean { + assert(Buffer.isBuffer(e), 'Element should be Buffer') + e = keccak256(e) const mask = 2047 // binary 11111111111 let match = true @@ -52,7 +56,7 @@ module.exports = class Bloom { const loc = mask & first2bytes const byteLoc = loc >> 3 const bitLoc = 1 << loc % 8 - match = (this.bitvector[BYTE_SIZE - byteLoc - 1] & bitLoc) + match = (this.bitvector[BYTE_SIZE - byteLoc - 1] & bitLoc) !== 0 } return Boolean(match) @@ -61,11 +65,11 @@ module.exports = class Bloom { /** * checks if multiple topics are in a bloom * @method multiCheck - * @param {Buffer[]|Array[]|String[]|Number[]} topics + * @param {Buffer[]} topics * @returns {boolean} Returns {@code true} if every topic is in the bloom */ - multiCheck (topics) { - return topics.every((t) => this.check(t)) + multiCheck (topics: Buffer[]): boolean { + return topics.every((t: Buffer) => this.check(t)) } /** @@ -73,7 +77,7 @@ module.exports = class Bloom { * @method or * @param {Bloom} bloom */ - or (bloom) { + or (bloom: Bloom) { if (bloom) { for (let i = 0; i <= BYTE_SIZE; i++) { this.bitvector[i] = this.bitvector[i] | bloom.bitvector[i] diff --git a/lib/runBlock.js b/lib/runBlock.js index 19f28488ce..dad023db22 100644 --- a/lib/runBlock.js +++ b/lib/runBlock.js @@ -1,6 +1,6 @@ const promisify = require('util.promisify') const ethUtil = require('ethereumjs-util') -const Bloom = require('./bloom') +const Bloom = require('./bloom').default const rlp = ethUtil.rlp const Trie = require('merkle-patricia-tree') const BN = ethUtil.BN diff --git a/lib/runTx.js b/lib/runTx.js index 3cc1cb4674..b970cce48c 100644 --- a/lib/runTx.js +++ b/lib/runTx.js @@ -1,6 +1,6 @@ const utils = require('ethereumjs-util') const BN = utils.BN -const Bloom = require('./bloom') +const Bloom = require('./bloom').default const Block = require('ethereumjs-block') const Account = require('ethereumjs-account') const Interpreter = require('./evm/interpreter') diff --git a/package.json b/package.json index f0581b2d3f..add77c77ba 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "testBuildIntegrity": "npm run build:dist && node ./tests/tester -s --dist --test='stackOverflow'", "testBlockchain": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --fork='Petersburg' --dist --excludeDir='GeneralStateTests'", "testBlockchainGeneralStateTests": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --dist --dir='GeneralStateTests'", - "testAPI": "tape './tests/api/**/*.js'", + "testAPI": "npm run build:dist && tape './tests/api/**/*.js'", "testAPI:browser": "karma start karma.conf.js", "test": "echo \"[INFO] Generic test cmd not used. See package.json for more specific test run cmds.\"", "lint": "standard", @@ -44,7 +44,7 @@ "ethereumjs-block": "~2.2.0", "ethereumjs-blockchain": "^3.4.0", "ethereumjs-common": "^1.1.0", - "ethereumjs-util": "^6.0.0", + "ethereumjs-util": "^6.1.0", "fake-merkle-patricia-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1", "merkle-patricia-tree": "^2.3.2", @@ -54,6 +54,8 @@ }, "devDependencies": { "@ethereumjs/config-prettier": "^1.1.1", + "@types/bn.js": "^4.11.5", + "@types/node": "^11.13.4", "browserify": "^16.2.3", "coveralls": "^3.0.0", "documentation": "^8.1.2", @@ -70,6 +72,7 @@ "minimist": "^1.1.1", "nyc": "^12.0.2", "prettier": "^1.16.4", + "rlp": "^2.2.3", "standard": "^10.0.0", "tap-spec": "^5.0.0", "tape": "4.6.3", diff --git a/tests/api/bloom.js b/tests/api/bloom.js index 77284afd97..bda51b5491 100644 --- a/tests/api/bloom.js +++ b/tests/api/bloom.js @@ -1,5 +1,5 @@ const tape = require('tape') -const Bloom = require('../../lib/bloom') +const Bloom = require('../../dist/bloom').default const utils = require('ethereumjs-util') const byteSize = 256 @@ -22,42 +22,42 @@ tape('bloom', (t) => { const vector = Buffer.from(hex, 'hex') const b = new Bloom(vector) - st.true(b.check('value 1'), 'should contain string "value 1"') - st.true(b.check('value 2'), 'should contain string "value 2"') + st.true(b.check(utils.toBuffer('value 1')), 'should contain string "value 1"') + st.true(b.check(utils.toBuffer('value 2')), 'should contain string "value 2"') st.end() }) t.test('check shouldnt be tautology', (st) => { const b = new Bloom() - st.false(b.check('random value'), 'should not contain string "random value"') + st.false(b.check(utils.toBuffer('random value')), 'should not contain string "random value"') st.end() }) t.test('should correctly add value', (st) => { const b = new Bloom() - b.add('value') - let found = b.check('value') + b.add(utils.toBuffer('value')) + let found = b.check(utils.toBuffer('value')) st.true(found, 'should contain added value') st.end() }) t.test('should check multiple values', (st) => { const b = new Bloom() - b.add('value 1') - b.add('value 2') - let found = b.multiCheck(['value 1', 'value 2']) + b.add(utils.toBuffer('value 1')) + b.add(utils.toBuffer('value 2')) + let found = b.multiCheck([utils.toBuffer('value 1'), utils.toBuffer('value 2')]) st.true(found, 'should contain both values') st.end() }) t.test('should or two filters', (st) => { const b1 = new Bloom() - b1.add('value 1') + b1.add(utils.toBuffer('value 1')) const b2 = new Bloom() - b2.add('value 2') + b2.add(utils.toBuffer('value 2')) b1.or(b2) - st.true(b1.check('value 2'), 'should contain "value 2" after or') + st.true(b1.check(utils.toBuffer('value 2')), 'should contain "value 2" after or') st.end() }) diff --git a/tests/api/evm/memory.js b/tests/api/evm/memory.js index dee7805846..cccf889545 100644 --- a/tests/api/evm/memory.js +++ b/tests/api/evm/memory.js @@ -1,5 +1,5 @@ const tape = require('tape') -const Memory = require('../../../lib/evm/memory') +const Memory = require('../../../dist/evm/memory') tape('Memory', t => { const m = new Memory() diff --git a/tests/api/evm/stack.js b/tests/api/evm/stack.js index ad8cc71ab0..834b948950 100644 --- a/tests/api/evm/stack.js +++ b/tests/api/evm/stack.js @@ -1,6 +1,6 @@ const tape = require('tape') const BN = require('bn.js') -const Stack = require('../../../lib/evm/stack') +const Stack = require('../../../dist/evm/stack') tape('Stack', t => { t.test('should be empty initially', st => { diff --git a/tests/api/freeLogs.js b/tests/api/freeLogs.js index 31f22cfac6..e0bd004502 100644 --- a/tests/api/freeLogs.js +++ b/tests/api/freeLogs.js @@ -1,5 +1,5 @@ const tape = require('tape') -const VM = require('../../lib/index') +const VM = require('../../dist/index') /* contract Contract1 { diff --git a/tests/api/index.js b/tests/api/index.js index c22ecf09b5..6da5142cea 100644 --- a/tests/api/index.js +++ b/tests/api/index.js @@ -3,7 +3,7 @@ const tape = require('tape') const util = require('ethereumjs-util') const Block = require('ethereumjs-block') const Trie = require('merkle-patricia-tree/secure') -const VM = require('../../lib/index') +const VM = require('../../dist/index') const { setupVM } = require('./utils') const { setupPreConditions } = require('../util') const testData = require('./testdata.json') diff --git a/tests/api/runBlock.js b/tests/api/runBlock.js index 23d6c365c7..958f942fd5 100644 --- a/tests/api/runBlock.js +++ b/tests/api/runBlock.js @@ -3,8 +3,8 @@ const tape = require('tape') const Block = require('ethereumjs-block') const Common = require('ethereumjs-common').default const util = require('ethereumjs-util') -const runBlock = require('../../lib/runBlock') -const { StateManager } = require('../../lib/state') +const runBlock = require('../../dist/runBlock') +const { StateManager } = require('../../dist/state') const testData = require('./testdata.json') const { setupVM } = require('./utils') const { setupPreConditions } = require('../util') diff --git a/tests/api/runBlockchain.js b/tests/api/runBlockchain.js index 56f3f3c7ce..8e74cbeb8d 100644 --- a/tests/api/runBlockchain.js +++ b/tests/api/runBlockchain.js @@ -5,8 +5,8 @@ const Blockchain = require('ethereumjs-blockchain') const Block = require('ethereumjs-block') const Common = require('ethereumjs-common').default const util = require('ethereumjs-util') -const runBlockchain = require('../../lib/runBlockchain') -const { StateManager } = require('../../lib/state') +const runBlockchain = require('../../dist/runBlockchain') +const { StateManager } = require('../../dist/state') const { createGenesis } = require('./utils') tape('runBlockchain', (t) => { diff --git a/tests/api/runCode.js b/tests/api/runCode.js index 0283a3f992..e626803c02 100644 --- a/tests/api/runCode.js +++ b/tests/api/runCode.js @@ -1,6 +1,6 @@ const tape = require('tape') const async = require('async') -const VM = require('../../lib/index') +const VM = require('../../dist/index') const STOP = '00' const JUMP = '56' diff --git a/tests/api/runJit.js b/tests/api/runJit.js index 70c72587af..9d3e11f2bb 100644 --- a/tests/api/runJit.js +++ b/tests/api/runJit.js @@ -1,6 +1,6 @@ const tape = require('tape') -const runJit = require('../../lib/runJit') -const exceptions = require('../../lib/exceptions.js') +const runJit = require('../../dist/runJit') +const exceptions = require('../../dist/exceptions.js') tape('Should run code with func type', (t) => { // TODO: Determine if account is still necessary for runJit @@ -10,7 +10,8 @@ tape('Should run code with func type', (t) => { code: (o) => ({ exceptionError: new exceptions.VmError('Invalid opcode') }) } - runJit(opts, (err, res) => { + const vm = {} + runJit.bind(vm)(opts, (err, res) => { t.ok(err, 'error should be set') t.equal(err.errorType, 'VmError') t.equal(err, res.exceptionError, 'callback error should be taken from exceptionError') @@ -25,7 +26,8 @@ tape('should run stringy code', (t) => { code: `return { exceptionError: null }` } - runJit(opts, (err, res) => { + const vm = {} + runJit.bind(vm)(opts, (err, res) => { t.error(err, 'error should be null') t.error(res.exceptionError, 'exceptionError should be null') t.equal(res.account, 'account') diff --git a/tests/api/runTx.js b/tests/api/runTx.js index 48269f2895..8ce01d3b95 100644 --- a/tests/api/runTx.js +++ b/tests/api/runTx.js @@ -2,9 +2,9 @@ const promisify = require('util.promisify') const tape = require('tape') const Transaction = require('ethereumjs-tx') const ethUtil = require('ethereumjs-util') -const runTx = require('../../lib/runTx') -const { StateManager } = require('../../lib/state') -const VM = require('../../lib/index') +const runTx = require('../../dist/runTx') +const { StateManager } = require('../../dist/state') +const VM = require('../../dist/index') const { createAccount } = require('./utils') function setup (vm = null) { diff --git a/tests/api/state/cache.js b/tests/api/state/cache.js index 6b421a23cb..3bc31cc356 100644 --- a/tests/api/state/cache.js +++ b/tests/api/state/cache.js @@ -2,7 +2,7 @@ const promisify = require('util.promisify') const tape = require('tape') const Trie = require('merkle-patricia-tree/secure.js') const Account = require('ethereumjs-account') -const Cache = require('../../../lib/state/cache') +const Cache = require('../../../dist/state/cache') const utils = require('../utils') tape('cache initialization', (t) => { diff --git a/tests/api/state/stateManager.js b/tests/api/state/stateManager.js index 2c8bbb9d55..41d7bc693b 100644 --- a/tests/api/state/stateManager.js +++ b/tests/api/state/stateManager.js @@ -1,7 +1,7 @@ const promisify = require('util.promisify') const tape = require('tape') const util = require('ethereumjs-util') -const StateManager = require('../../../lib/state/stateManager') +const StateManager = require('../../../dist/state/stateManager') const { createAccount } = require('../utils') tape('StateManager', (t) => { diff --git a/tests/api/state/storageReader.js b/tests/api/state/storageReader.js index ed3f564a23..e81308b45a 100644 --- a/tests/api/state/storageReader.js +++ b/tests/api/state/storageReader.js @@ -1,6 +1,6 @@ const promisify = require('util.promisify') const tape = require('tape') -const { StorageReader } = require('../../../lib/state') +const { StorageReader } = require('../../../dist/state') const mkStateManagerMock = () => { let i = 0 diff --git a/tests/api/utils.js b/tests/api/utils.js index 0decdcd1da..d69c6dfc0d 100644 --- a/tests/api/utils.js +++ b/tests/api/utils.js @@ -2,7 +2,7 @@ const Block = require('ethereumjs-block') const Account = require('ethereumjs-account') const level = require('level-mem') const Blockchain = require('ethereumjs-blockchain') -const VM = require('../../lib/index') +const VM = require('../../dist/index') function createGenesis (opts = {}) { opts.chain = opts.chain ? opts.chain : 'mainnet' diff --git a/tsconfig.json b/tsconfig.json index ed46006aaa..8809e0afd3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,9 @@ "outDir": "./dist", "allowJs": true, "target": "es5", - "lib": ["es2018"] + "lib": ["es2018"], + "sourceMap": true, + "strict": true }, "include": ["./lib/**/*"] } From e3969eadb894afaa17150b3f679008a6af958aa2 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 13:37:53 +0200 Subject: [PATCH 05/10] Mv lib/evm/stack.js to lib/evm/stack.ts --- lib/evm/{stack.js => stack.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/evm/{stack.js => stack.ts} (100%) diff --git a/lib/evm/stack.js b/lib/evm/stack.ts similarity index 100% rename from lib/evm/stack.js rename to lib/evm/stack.ts From 328f47cc7f9429173476916ade0422b4b9287a2e Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 13:53:25 +0200 Subject: [PATCH 06/10] Migrate stack to ts, limit it to BN --- lib/evm/loop.js | 2 +- lib/evm/stack.ts | 45 ++++++++++++++++++------------------------ tests/api/evm/stack.js | 8 +------- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/lib/evm/loop.js b/lib/evm/loop.js index fd94a507f5..92f5ca70ca 100644 --- a/lib/evm/loop.js +++ b/lib/evm/loop.js @@ -5,7 +5,7 @@ const { StorageReader } = require('../state') const PStateManager = require('../state/promisified') const { ERROR, VmError } = require('../exceptions') const Memory = require('./memory') -const Stack = require('./stack') +const Stack = require('./stack').default const EEI = require('./eei') const lookupOpInfo = require('./opcodes.js') const opFns = require('./opFns.js') diff --git a/lib/evm/stack.ts b/lib/evm/stack.ts index b2b1553122..e9feaa8a16 100644 --- a/lib/evm/stack.ts +++ b/lib/evm/stack.ts @@ -1,11 +1,13 @@ -const BN = require('bn.js') -const ethUtil = require('ethereumjs-util') +import BN = require('bn.js') +import { MAX_INTEGER } from 'ethereumjs-util' const { ERROR, VmError } = require('../exceptions') /** * Implementation of the stack used in evm. */ -module.exports = class Stack { +export default class Stack { + _store: BN[] + constructor () { this._store = [] } @@ -14,24 +16,29 @@ module.exports = class Stack { return this._store.length } - push (value) { - if (this._store.length > 1023) { - throw new VmError(ERROR.STACK_OVERFLOW) + push (value: BN) { + if (!BN.isBN(value)) { + throw new VmError(ERROR.INTERNAL_ERROR) } - if (!this._isValidValue(value)) { + if (value.gt(MAX_INTEGER)) { throw new VmError(ERROR.OUT_OF_RANGE) } + if (this._store.length > 1023) { + throw new VmError(ERROR.STACK_OVERFLOW) + } + this._store.push(value) } - pop () { + pop (): BN { if (this._store.length < 1) { throw new VmError(ERROR.STACK_UNDERFLOW) } - return this._store.pop() + // Length is checked above, so pop shouldn't return undefined + return this._store.pop()! } /** @@ -40,7 +47,7 @@ module.exports = class Stack { * @param {Number} num - Number of items to pop * @returns {Array} */ - popN (num = 1) { + popN (num: number = 1): BN[] { if (this._store.length < num) { throw new VmError(ERROR.STACK_UNDERFLOW) } @@ -56,7 +63,7 @@ module.exports = class Stack { * Swap top of stack with an item in the stack. * @param {Number} position - Index of item from top of the stack (0-indexed) */ - swap (position) { + swap (position: number) { if (this._store.length <= position) { throw new VmError(ERROR.STACK_UNDERFLOW) } @@ -73,7 +80,7 @@ module.exports = class Stack { * Pushes a copy of an item in the stack. * @param {Number} position - Index of item to be copied (1-indexed) */ - dup (position) { + dup (position: number) { if (this._store.length < position) { throw new VmError(ERROR.STACK_UNDERFLOW) } @@ -81,18 +88,4 @@ module.exports = class Stack { const i = this._store.length - position this.push(this._store[i]) } - - _isValidValue (value) { - if (BN.isBN(value)) { - if (value.lte(ethUtil.MAX_INTEGER)) { - return true - } - } else if (Buffer.isBuffer(value)) { - if (value.length <= 32) { - return true - } - } - - return false - } } diff --git a/tests/api/evm/stack.js b/tests/api/evm/stack.js index 834b948950..6a1b24adaf 100644 --- a/tests/api/evm/stack.js +++ b/tests/api/evm/stack.js @@ -1,6 +1,6 @@ const tape = require('tape') const BN = require('bn.js') -const Stack = require('../../../dist/evm/stack') +const Stack = require('../../../dist/evm/stack').default tape('Stack', t => { t.test('should be empty initially', st => { @@ -109,12 +109,6 @@ tape('Stack', t => { s.push(max) st.deepEqual(s.pop(), max) st.throws(() => s.push(max.addn(1))) - - const maxBuf = max.toArrayLike(Buffer, 'be', 32) - s.push(maxBuf) - st.deepEqual(s.pop(), maxBuf) - st.throws(() => s.push(max.addn(1).toArrayLike(Buffer, 'be', 32))) - st.end() }) }) From eb46a8273a39fc4f7020c5d86661b27e6d0a2e53 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 13:54:16 +0200 Subject: [PATCH 07/10] Mv lib/evm/memory.js to lib/evm/memory.ts --- lib/evm/{memory.js => memory.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/evm/{memory.js => memory.ts} (100%) diff --git a/lib/evm/memory.js b/lib/evm/memory.ts similarity index 100% rename from lib/evm/memory.js rename to lib/evm/memory.ts From 8efdefab275289e18f4a790de59e27af1917496f Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 14:02:56 +0200 Subject: [PATCH 08/10] Migrate evm memory to ts --- lib/evm/loop.js | 2 +- lib/evm/memory.ts | 26 +++++++++++++------------- tests/api/evm/memory.js | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/evm/loop.js b/lib/evm/loop.js index 92f5ca70ca..77d5ca3282 100644 --- a/lib/evm/loop.js +++ b/lib/evm/loop.js @@ -4,7 +4,7 @@ const utils = require('ethereumjs-util') const { StorageReader } = require('../state') const PStateManager = require('../state/promisified') const { ERROR, VmError } = require('../exceptions') -const Memory = require('./memory') +const Memory = require('./memory').default const Stack = require('./stack').default const EEI = require('./eei') const lookupOpInfo = require('./opcodes.js') diff --git a/lib/evm/memory.ts b/lib/evm/memory.ts index 7504d7572a..10ee2a2e96 100644 --- a/lib/evm/memory.ts +++ b/lib/evm/memory.ts @@ -1,8 +1,12 @@ +import * as assert from 'assert' + /** * Memory implements a simple memory model * for the ethereum virtual machine. */ -module.exports = class Memory { +export default class Memory { + _store: number[] + constructor () { this._store = [] } @@ -11,9 +15,9 @@ module.exports = class Memory { * Extends the memory given an offset and size. Rounds extended * memory to word-size. * @param {Number} offset - * @param {size} size + * @param {Number} size */ - extend (offset, size) { + extend (offset: number, size: number) { if (size === 0) { return } @@ -31,18 +35,14 @@ module.exports = class Memory { * @param {Number} size - How many bytes to write * @param {Buffer} value - Value */ - write (offset, size, value) { + write (offset: number, size: number, value: Buffer) { if (size === 0) { return } - if (value.length !== size) { - throw new Error('Invalid value size') - } - - if (offset + size > this._store.length) { - throw new Error('Value exceeds memory capacity') - } + assert(value.length === size, 'Invalid value size') + assert(offset + size <= this._store.length, 'Value exceeds memory capacity') + assert(Buffer.isBuffer(value), 'Invalid value type') for (let i = 0; i < size; i++) { this._store[offset + i] = value[i] @@ -56,7 +56,7 @@ module.exports = class Memory { * @param {Number} size - How many bytes to read * @returns {Buffer} */ - read (offset, size) { + read (offset: number, size: number): Buffer { const loaded = this._store.slice(offset, offset + size) // Fill the remaining length with zeros for (let i = loaded.length; i < size; i++) { @@ -66,7 +66,7 @@ module.exports = class Memory { } } -const ceil = (value, ceiling) => { +const ceil = (value: number, ceiling: number): number => { const r = value % ceiling if (r === 0) { return value diff --git a/tests/api/evm/memory.js b/tests/api/evm/memory.js index cccf889545..3d02accbf0 100644 --- a/tests/api/evm/memory.js +++ b/tests/api/evm/memory.js @@ -1,5 +1,5 @@ const tape = require('tape') -const Memory = require('../../../dist/evm/memory') +const Memory = require('../../../dist/evm/memory').default tape('Memory', t => { const m = new Memory() From f79e34eb5dec9333ab9d20f4360f4f5fdb6b5d86 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 14:23:02 +0200 Subject: [PATCH 09/10] Build:dist before coverage and api browser tests --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index add77c77ba..35c89e87e7 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "scripts": { "coverage": "nyc npm run coverageTests && nyc report --reporter=text-lcov > .nyc_output/lcov.info", - "coverageTests": "tape './tests/api/**/*.js' ./tests/tester.js -s", + "coverageTests": "npm run build:dist && tape './tests/api/**/*.js' ./tests/tester.js -s", "coveralls": "npm run coverage && if [ -n \"$COVERALLS_REPO_TOKEN\" ]; then coveralls <.nyc_output/lcov.info; fi", "testVM": "node ./tests/tester -v", "testStateByzantium": "npm run build:dist && node ./tests/tester -s --fork='Byzantium' --dist", @@ -18,7 +18,7 @@ "testBlockchain": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --fork='Petersburg' --dist --excludeDir='GeneralStateTests'", "testBlockchainGeneralStateTests": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --dist --dir='GeneralStateTests'", "testAPI": "npm run build:dist && tape './tests/api/**/*.js'", - "testAPI:browser": "karma start karma.conf.js", + "testAPI:browser": "npm run build:dist && karma start karma.conf.js", "test": "echo \"[INFO] Generic test cmd not used. See package.json for more specific test run cmds.\"", "lint": "standard", "format": "ethereumjs-config-format", From 9eb3b70749333b35fa52dfc12c56ba84ec5fdf1c Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Thu, 11 Apr 2019 14:41:11 +0200 Subject: [PATCH 10/10] Use tester dist flag for coverage tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35c89e87e7..c0316eb30b 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "scripts": { "coverage": "nyc npm run coverageTests && nyc report --reporter=text-lcov > .nyc_output/lcov.info", - "coverageTests": "npm run build:dist && tape './tests/api/**/*.js' ./tests/tester.js -s", + "coverageTests": "npm run build:dist && tape './tests/api/**/*.js' ./tests/tester.js -s --dist", "coveralls": "npm run coverage && if [ -n \"$COVERALLS_REPO_TOKEN\" ]; then coveralls <.nyc_output/lcov.info; fi", "testVM": "node ./tests/tester -v", "testStateByzantium": "npm run build:dist && node ./tests/tester -s --fork='Byzantium' --dist",