From 3abda79c38519ce8b700f8c715f1e47ff0ff0ce8 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Sun, 22 Jul 2018 18:22:33 +0200 Subject: [PATCH 01/13] Add tests for bloom Signed-off-by: Sina Mahmoodi --- tests/api/bloom.js | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tests/api/bloom.js diff --git a/tests/api/bloom.js b/tests/api/bloom.js new file mode 100644 index 0000000000..45438af654 --- /dev/null +++ b/tests/api/bloom.js @@ -0,0 +1,63 @@ +const tape = require('tape') +const Bloom = require('../../lib/bloom') +const utils = require('ethereumjs-util') + +const byteSize = 256 + +tape('bloom', (t) => { + t.test('should initialize without params', (st) => { + const b = new Bloom() + st.deepEqual(b.bitvector, utils.zeros(byteSize), 'should be empty') + st.end() + }) + + t.test('shouldnt initialize with invalid bitvector', (st) => { + st.throws(() => new Bloom('invalid'), /AssertionError/, 'should fail for invalid type') + st.throws(() => new Bloom(utils.zeros(byteSize / 2), /AssertionError/), 'should fail for invalid length') + st.end() + }) + + t.test('should contain values of hardcoded bitvector', (st) => { + const hex = '00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000' + const vector = Buffer.from(hex, 'hex') + + const b = new Bloom(vector) + st.true(b.check('value 1'), 'should contain value 1') + st.true(b.check('value 2'), 'should contain value 2') + st.end() + }) + + t.test('check shouldnt be tautology', (st) => { + const b = new Bloom() + st.false(b.check('random value'), 'should not contain random value') + st.end() + }) + + t.test('should correctly add value', (st) => { + const b = new Bloom() + b.add('value') + let found = b.check('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']) + st.true(found, 'should contain both values') + st.end() + }) + + t.test('should or two filters', (st) => { + const b1 = new Bloom() + b1.add('value 1') + const b2 = new Bloom() + b2.add('value 2') + + b1.or(b2) + st.true(b1.check('value 2'), 'should contain value 2 after or') + st.end() + }) +}) From c50859a02d11cd9c25f3a69f3f9b23801df0b612 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 25 Jul 2018 10:56:02 +0200 Subject: [PATCH 02/13] Add tests for runJit Signed-off-by: Sina Mahmoodi --- tests/api/runJit.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/api/runJit.js diff --git a/tests/api/runJit.js b/tests/api/runJit.js new file mode 100644 index 0000000000..70c72587af --- /dev/null +++ b/tests/api/runJit.js @@ -0,0 +1,34 @@ +const tape = require('tape') +const runJit = require('../../lib/runJit') +const exceptions = require('../../lib/exceptions.js') + +tape('Should run code with func type', (t) => { + // TODO: Determine if account is still necessary for runJit + // as the callers don't seem to be using results.account + const opts = { + account: 'account', + code: (o) => ({ exceptionError: new exceptions.VmError('Invalid opcode') }) + } + + runJit(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') + t.equal(res.account, 'account') + t.end() + }) +}) + +tape('should run stringy code', (t) => { + const opts = { + account: 'account', + code: `return { exceptionError: null }` + } + + runJit(opts, (err, res) => { + t.error(err, 'error should be null') + t.error(res.exceptionError, 'exceptionError should be null') + t.equal(res.account, 'account') + t.end() + }) +}) From 3fd597c4a4c13ad986654b6f51766e802f10fc53 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 25 Jul 2018 11:45:45 +0200 Subject: [PATCH 03/13] Add tests for fakeBlockChain Signed-off-by: Sina Mahmoodi --- tests/api/fakeBlockChain.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/api/fakeBlockChain.js diff --git a/tests/api/fakeBlockChain.js b/tests/api/fakeBlockChain.js new file mode 100644 index 0000000000..15f1279a3e --- /dev/null +++ b/tests/api/fakeBlockChain.js @@ -0,0 +1,36 @@ +const tape = require('tape') +const fakeBlockchain = require('../../lib/fakeBlockChain') + +tape('fakeBlockChain', (t) => { + const blockchain = fakeBlockchain + + t.test('should fail to get block by invalid type', (st) => { + blockchain.getBlock(null, (err, block) => { + st.ok(err, 'should return error') + st.notOk(block) + st.end() + }) + }) + + t.test('should get block hash by number', (st) => { + blockchain.getBlock(1, isValidBlock(st)) + }) + + t.test('should get block hash by buffer', (st) => { + blockchain.getBlock(Buffer.from('0x0'), isValidBlock(st)) + }) + + t.test('should "del" block', (st) => { + blockchain.delBlock('0x0', (err) => { + st.error(err) + st.end() + }) + }) +}) + +const isValidBlock = (st) => (err, block) => { + st.notOk(err) + st.ok(block, 'should return non-empty value') + st.ok(Buffer.isBuffer(block.hash()), 'block hash should of type buffer') + st.end() +} From 1bb587a7e0f6e743f0bc1f79c6034d7d73e589f1 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 25 Jul 2018 14:15:02 +0200 Subject: [PATCH 04/13] Move bloomTest to other bloom test file Signed-off-by: Sina Mahmoodi --- tests/api/bloom.js | 13 +++++++++++++ tests/bloomTest.js | 16 ---------------- 2 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 tests/bloomTest.js diff --git a/tests/api/bloom.js b/tests/api/bloom.js index 45438af654..a3cb0c02be 100644 --- a/tests/api/bloom.js +++ b/tests/api/bloom.js @@ -60,4 +60,17 @@ tape('bloom', (t) => { st.true(b1.check('value 2'), 'should contain value 2 after or') st.end() }) + + t.test('should generate the correct bloom filter value ', (st) => { + let bloom = new Bloom() + bloom.add(Buffer.from('1d7022f5b17d2f8b695918fb48fa1089c9f85401', 'hex')) + bloom.add(Buffer.from('8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', 'hex')) + bloom.add(Buffer.from('0000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a631', 'hex')) + bloom.add(Buffer.from('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', 'hex')) + st.equal( + bloom.bitvector.toString('hex'), + '00000000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000000000000000004000000080000200000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010008000000000000000002000000000000000000000000008000000000000' + ) + st.end() + }) }) diff --git a/tests/bloomTest.js b/tests/bloomTest.js deleted file mode 100644 index c03a3fbd89..0000000000 --- a/tests/bloomTest.js +++ /dev/null @@ -1,16 +0,0 @@ -const tape = require('tape') -const Bloom = require('../lib/bloom.js') -tape('test the bloom filter', function (t) { - t.test('should generate the correct bloom filter value ', function (st) { - let bloom = new Bloom() - bloom.add(Buffer.from('1d7022f5b17d2f8b695918fb48fa1089c9f85401', 'hex')) - bloom.add(Buffer.from('8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', 'hex')) - bloom.add(Buffer.from('0000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a631', 'hex')) - bloom.add(Buffer.from('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', 'hex')) - t.equal( - bloom.bitvector.toString('hex'), - '00000000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000000000000000004000000080000200000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010008000000000000000002000000000000000000000000008000000000000' - ) - t.end() - }) -}) From 51d15a7347bea56fb23cfffe484c65e14dd81f32 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 25 Jul 2018 14:56:06 +0200 Subject: [PATCH 05/13] Fix: remove moved bloomTest from tester Signed-off-by: Sina Mahmoodi --- tests/tester.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tester.js b/tests/tester.js index dd0211cb7c..ae0368112d 100755 --- a/tests/tester.js +++ b/tests/tester.js @@ -248,7 +248,6 @@ function runTests (name, runnerArgs, cb) { function runAll () { require('./tester.js') require('./cacheTest.js') - require('./bloomTest.js') require('./genesishashes.js') async.series([ // runTests.bind(this, 'VMTests', {}), // VM tests disabled since we don't support Frontier gas costs From f67e22bd9a78c5424dad7be2d5d93e036dabbf81 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Fri, 27 Jul 2018 14:25:34 +0200 Subject: [PATCH 06/13] Add iterator to fakeBlockChain Signed-off-by: Sina Mahmoodi --- lib/fakeBlockChain.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/fakeBlockChain.js b/lib/fakeBlockChain.js index 91f8de05de..6c55caeead 100644 --- a/lib/fakeBlockChain.js +++ b/lib/fakeBlockChain.js @@ -24,5 +24,9 @@ module.exports = { delBlock: function (hash, cb) { cb(null) + }, + + iterator: function (name, onBlock, cb) { + cb(null) } } From db2a797448cd0f3b5545d6f370035ca198fe0f31 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Fri, 27 Jul 2018 14:26:17 +0200 Subject: [PATCH 07/13] Add tests for runBlockchain Signed-off-by: Sina Mahmoodi --- tests/api/runBlockchain.js | 105 +++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/api/runBlockchain.js diff --git a/tests/api/runBlockchain.js b/tests/api/runBlockchain.js new file mode 100644 index 0000000000..d55d0a9cbe --- /dev/null +++ b/tests/api/runBlockchain.js @@ -0,0 +1,105 @@ +const tape = require('tape') +const Levelup = require('levelup') +const Memdown = require('memdown') +const { promisify } = require('util') +const Blockchain = require('ethereumjs-blockchain') +const Block = require('ethereumjs-block') +const util = require('ethereumjs-util') +const runBlockchain = require('../../lib/runBlockchain') +const StateManager = require('../../lib/stateManager') + +tape('runBlockchain', (t) => { + const blockchainDB = new Levelup('', { db: Memdown }) + const blockchain = new Blockchain(blockchainDB) + const vm = { stateManager: new StateManager({ blockchain }) } + + const putGenesisP = promisify(blockchain.putGenesis.bind(blockchain)) + const putBlockP = promisify(blockchain.putBlock.bind(blockchain)) + const getHeadP = promisify(blockchain.getHead.bind(blockchain)) + const runBlockchainP = promisify(runBlockchain.bind(vm)) + + t.test('should run without a blockchain parameter', async (st) => { + await runBlockchainP() + st.end() + }) + + t.test('should run without blocks', async (st) => { + await runBlockchainP(blockchain) + st.end() + }) + + t.test('should run with genesis block', async (st) => { + const genesis = createGenesis() + + await putGenesisP(genesis) + st.ok(blockchain.meta.genesis, 'genesis should be set for blockchain') + + await runBlockchainP(blockchain) + st.end() + }) + + t.test('should run with valid and invalid blocks', async (st) => { + // Produce error on the third time runBlock is called + let runBlockInvocations = 0 + vm.runBlock = (opts, cb) => { + runBlockInvocations++ + if (runBlockInvocations === 3) { + return cb(new Error('test'), {}) + } + cb(null, {}) + } + + const genesis = createGenesis() + await putGenesisP(genesis) + + const b1 = createBlock(genesis, 1) + const b2 = createBlock(b1, 2) + const b3 = createBlock(b2, 3) + + blockchain.validate = false + + await putBlockP(b1) + await putBlockP(b2) + await putBlockP(b3) + + let head = await getHeadP() + st.deepEqual(head.hash(), b3.hash(), 'block3 should be the current head') + + await runBlockchainP(blockchain) + + head = await getHeadP() + st.deepEqual(head.hash(), b2.hash(), 'should have removed invalid block from head') + + st.end() + }) +}) + +tape('runBlockchain with fake blockchain', (t) => { + const vm = { + stateManager: new StateManager() + } + const runBlockchainP = promisify(runBlockchain.bind(vm)) + + t.test('should run without errors', async (st) => { + await runBlockchainP() + st.end() + }) +}) + +function createGenesis () { + const genesis = new Block() + genesis.setGenesisParams() +} + +function createBlock (parent = null, n = 0) { + if (parent === null) { + return createGenesis() + } + + const b = new Block() + b.header.number = util.toBuffer(n) + b.header.parentHash = parent.hash() + b.header.difficulty = '0xfffffff' + + return b +} From 376c93a9e730a47d5c94bf86282cc86238ea5382 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 31 Jul 2018 14:30:09 +0200 Subject: [PATCH 08/13] Add tests for runTx, add some validity checks to runTx Signed-off-by: Sina Mahmoodi --- lib/runTx.js | 18 ++++-- tests/api/runBlockchain.js | 2 + tests/api/runTx.js | 109 +++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 tests/api/runTx.js diff --git a/lib/runTx.js b/lib/runTx.js index 28ae76b32e..38663175a0 100644 --- a/lib/runTx.js +++ b/lib/runTx.js @@ -16,6 +16,11 @@ const Block = require('ethereumjs-block') * @param cb {Function} - the callback */ module.exports = function (opts, cb) { + if (typeof opts === 'function' && cb === undefined) { + cb = opts + return cb(new Error('invalid input, opts must be provided')) + } + var self = this var block = opts.block var tx = opts.tx @@ -23,6 +28,11 @@ module.exports = function (opts, cb) { var results var basefee + // tx is required + if (!tx) { + return cb(new Error('invalid input, tx is required')) + } + // create a reasonable default if no block is given if (!block) { block = new Block() @@ -63,6 +73,10 @@ module.exports = function (opts, cb) { * populates the cache with the 'to' and 'from' of the tx */ function populateCache (cb) { + if (opts.populateCache === false) { + return cb() + } + var accounts = new Set() accounts.add(tx.from.toString('hex')) accounts.add(block.header.coinbase.toString('hex')) @@ -71,10 +85,6 @@ module.exports = function (opts, cb) { accounts.add(tx.to.toString('hex')) } - if (opts.populateCache === false) { - return cb() - } - self.stateManager.warmCache(accounts, cb) } diff --git a/tests/api/runBlockchain.js b/tests/api/runBlockchain.js index d55d0a9cbe..078c2a656f 100644 --- a/tests/api/runBlockchain.js +++ b/tests/api/runBlockchain.js @@ -89,6 +89,8 @@ tape('runBlockchain with fake blockchain', (t) => { function createGenesis () { const genesis = new Block() genesis.setGenesisParams() + + return genesis } function createBlock (parent = null, n = 0) { diff --git a/tests/api/runTx.js b/tests/api/runTx.js new file mode 100644 index 0000000000..fae2bc27ed --- /dev/null +++ b/tests/api/runTx.js @@ -0,0 +1,109 @@ +const { promisify } = require('util') +const tape = require('tape') +const Transaction = require('ethereumjs-tx') +const Account = require('ethereumjs-account') +const runTx = require('../../lib/runTx') +const StateManager = require('../../lib/stateManager') + +tape('runTx', (t) => { + const vm = { stateManager: new StateManager({ }), emit: (e, val, cb) => { cb() }, runCall: (opts, cb) => cb(new Error('test')) } + const runTxP = promisify(runTx.bind(vm)) + const putAccountP = promisify(vm.stateManager.putAccount.bind(vm.stateManager)) + const cacheFlushP = promisify(vm.stateManager.cache.flush.bind(vm.stateManager.cache)) + + t.test('should fail to run without opts', async (st) => { + shouldFail(st, runTxP(), + (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') + ) + st.end() + }) + + t.test('should fail to run without tx', async (st) => { + shouldFail(st, runTxP({}), + (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') + ) + st.end() + }) + + t.test('should fail to run without signature', async (st) => { + const tx = getTransaction() + shouldFail(st, runTxP({ tx }), + (e) => st.ok(e.message.toLowerCase().includes('signature'), 'should fail with appropriate error') + ) + st.end() + }) + + t.test('should fail without sufficient funds', async (st) => { + const tx = getTransaction(true, true) + shouldFail(st, runTxP({ tx }), + (e) => st.ok(e.message.toLowerCase().includes('enough funds'), 'error should include "enough funds"') + ) + st.end() + }) + + t.test('should fail when runCall fails', async (st) => { + const tx = getTransaction(true, true) + const acc = getAccount() + await putAccountP(tx.from.toString('hex'), acc) + await cacheFlushP() + + shouldFail(st, + runTxP({ tx, populateCache: true }), + (e) => st.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') + ) + + st.end() + }) + + t.test('should behave the same when not using cache', async (st) => { + const tx = getTransaction(true, true) + const acc = getAccount() + await putAccountP(tx.from.toString('hex'), acc) + await cacheFlushP() + vm.stateManager.cache.clear() + + shouldFail(st, + runTxP({ tx, populateCache: false }), + (e) => st.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') + ) + + st.end() + }) +}) + +function shouldFail (st, p, onErr) { + p.then(() => st.fail('runTx didnt return any errors')).catch(onErr) +} + +function getTransaction (sign = false, calculageGas = false) { + const privateKey = Buffer.from('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex') + const txParams = { + nonce: '0x00', + gasPrice: 100, + gasLimit: 1000, + to: '0x0000000000000000000000000000000000000000', + value: '0x00', + data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', + chainId: 3 + } + + const tx = new Transaction(txParams) + if (sign) { + tx.sign(privateKey) + } + + if (calculageGas) { + tx.gas = tx.getUpfrontCost() + } + + return tx +} + +function getAccount () { + const raw = { + nonce: '0x00', + balance: '0xfff384' + } + const acc = new Account(raw) + return acc +} From 02edbca375a26943e5e570f289da4283062580c1 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 1 Aug 2018 17:15:46 +0200 Subject: [PATCH 09/13] Add tests and two input validation for runBlock, refactor tests a bit Signed-off-by: Sina Mahmoodi --- lib/runBlock.js | 9 +++ tests/api/runBlock.js | 97 ++++++++++++++++++++++ tests/api/runBlockchain.js | 8 +- tests/api/runTx.js | 91 +++++++++++---------- tests/api/testdata.json | 159 +++++++++++++++++++++++++++++++++++++ tests/api/utils.js | 23 ++++++ 6 files changed, 338 insertions(+), 49 deletions(-) create mode 100644 tests/api/runBlock.js create mode 100644 tests/api/testdata.json create mode 100644 tests/api/utils.js diff --git a/lib/runBlock.js b/lib/runBlock.js index 80d081e65a..f6dc557c23 100644 --- a/lib/runBlock.js +++ b/lib/runBlock.js @@ -14,6 +14,15 @@ const BN = ethUtil.BN * @param cb {Function} the callback which is given an error string */ module.exports = function (opts, cb) { + if (typeof opts === 'function' && cb === undefined) { + cb = opts + return cb(new Error('invalid input, opts must be provided')) + } + + if (!opts.block) { + return cb(new Error('invalid input, block must be provided')) + } + const self = this // parse options diff --git a/tests/api/runBlock.js b/tests/api/runBlock.js new file mode 100644 index 0000000000..9e8fbc9253 --- /dev/null +++ b/tests/api/runBlock.js @@ -0,0 +1,97 @@ +const { promisify } = require('util') +const tape = require('tape') +const Block = require('ethereumjs-block') +const Transaction = require('ethereumjs-tx') +const Account = require('ethereumjs-account') +const Common = require('ethereumjs-common') +const util = require('ethereumjs-util') +const runBlock = require('../../lib/runBlock') +const StateManager = require('../../lib/stateManager') +const runTx = require('../../lib/runTx') +const testData = require('./testdata.json') +const { createGenesis, createAccount } = require('./utils') + +function setup () { + const stateManager = new StateManager() + const vm = { + stateManager, + emit: (e, val, cb) => cb(), + populateCache: stateManager.warmCache.bind(stateManager), + runTx: (opts, cb) => cb(new Error('test')), + runCall: (opts, cb) => cb(new Error('test')), + _common: new Common('mainnet', 'byzantium') + } + + return { + vm, + data: testData, + p: { + runBlock: promisify(runBlock.bind(vm)), + putAccount: promisify(vm.stateManager.putAccount.bind(vm.stateManager)), + cacheFlush: promisify(vm.stateManager.cache.flush.bind(vm.stateManager.cache)) + } + } +} + +tape('runBlock', async (t) => { + const suite = setup() + + t.test('should fail without params', async (st) => { + suite.p.runBlock() + .then(() => st.fail('should have returned error')) + .catch((e) => st.ok(e.message.includes('invalid input'), 'correct error')) + + st.end() + }) + + t.test('should fail without opts', async (st) => { + suite.p.runBlock({}) + .then(() => st.fail('should have returned error')) + .catch((e) => st.ok(e.message.includes('invalid input'), 'correct error')) + + st.end() + }) + + t.test('should fail when runTx fails', async (st) => { + const genesis = createGenesis() + const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) + await suite.p.runBlock({ block, root: genesis.header.stateRoot }) + .then(() => t.fail('should have returned error')) + .catch((e) => t.equal(e.message, 'test')) + + st.end() + }) +}) + +tape('should fail when tx gas limit higher than block gas limit', async (t) => { + const suite = setup() + + const genesis = createGenesis() + const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) + block.transactions[0].gasLimit = Buffer.from('033ec6', 'hex') + suite.p.runBlock({ block, root: genesis.header.stateRoot }) + .then(() => t.fail('should have returned error')) + .catch((e) => t.ok(e.message.includes('higher gas limit'))) + + t.end() +}) + +tape('should fail when runCall fails', async (t) => { + const suite = setup() + + const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) + // Add some balance to accounts, so they can run txes + for (let i = 0; i < block.transactions.length; i++) { + let tx = new Transaction(block.transactions[i]) + const acc = createAccount() + await suite.p.putAccount(tx.from.toString('hex'), acc) + } + await suite.p.cacheFlush() + + suite.vm.runTx = runTx + await suite.p.runBlock({ block, root: suite.vm.stateManager.trie.root }) + .then(() => t.fail('should have returned error')) + .catch((e) => t.equal(e.message, 'test')) + + t.end() +}) diff --git a/tests/api/runBlockchain.js b/tests/api/runBlockchain.js index 078c2a656f..3411ce9d56 100644 --- a/tests/api/runBlockchain.js +++ b/tests/api/runBlockchain.js @@ -7,6 +7,7 @@ const Block = require('ethereumjs-block') const util = require('ethereumjs-util') const runBlockchain = require('../../lib/runBlockchain') const StateManager = require('../../lib/stateManager') +const { createGenesis } = require('./utils') tape('runBlockchain', (t) => { const blockchainDB = new Levelup('', { db: Memdown }) @@ -86,13 +87,6 @@ tape('runBlockchain with fake blockchain', (t) => { }) }) -function createGenesis () { - const genesis = new Block() - genesis.setGenesisParams() - - return genesis -} - function createBlock (parent = null, n = 0) { if (parent === null) { return createGenesis() diff --git a/tests/api/runTx.js b/tests/api/runTx.js index fae2bc27ed..ec7baa0462 100644 --- a/tests/api/runTx.js +++ b/tests/api/runTx.js @@ -1,25 +1,37 @@ const { promisify } = require('util') const tape = require('tape') const Transaction = require('ethereumjs-tx') -const Account = require('ethereumjs-account') const runTx = require('../../lib/runTx') const StateManager = require('../../lib/stateManager') +const { createAccount } = require('./utils') + +function setup () { + const vm = { + stateManager: new StateManager({ }), + emit: (e, val, cb) => { cb() }, + runCall: (opts, cb) => cb(new Error('test')) + } + + return { + vm, + runTx: promisify(runTx.bind(vm)), + putAccount: promisify(vm.stateManager.putAccount.bind(vm.stateManager)), + cacheFlush: promisify(vm.stateManager.cache.flush.bind(vm.stateManager.cache)) + } +} tape('runTx', (t) => { - const vm = { stateManager: new StateManager({ }), emit: (e, val, cb) => { cb() }, runCall: (opts, cb) => cb(new Error('test')) } - const runTxP = promisify(runTx.bind(vm)) - const putAccountP = promisify(vm.stateManager.putAccount.bind(vm.stateManager)) - const cacheFlushP = promisify(vm.stateManager.cache.flush.bind(vm.stateManager.cache)) + const suite = setup() t.test('should fail to run without opts', async (st) => { - shouldFail(st, runTxP(), + shouldFail(st, suite.runTx(), (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') ) st.end() }) t.test('should fail to run without tx', async (st) => { - shouldFail(st, runTxP({}), + shouldFail(st, suite.runTx({}), (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') ) st.end() @@ -27,7 +39,7 @@ tape('runTx', (t) => { t.test('should fail to run without signature', async (st) => { const tx = getTransaction() - shouldFail(st, runTxP({ tx }), + shouldFail(st, suite.runTx({ tx }), (e) => st.ok(e.message.toLowerCase().includes('signature'), 'should fail with appropriate error') ) st.end() @@ -35,40 +47,44 @@ tape('runTx', (t) => { t.test('should fail without sufficient funds', async (st) => { const tx = getTransaction(true, true) - shouldFail(st, runTxP({ tx }), + shouldFail(st, suite.runTx({ tx }), (e) => st.ok(e.message.toLowerCase().includes('enough funds'), 'error should include "enough funds"') ) st.end() }) +}) - t.test('should fail when runCall fails', async (st) => { - const tx = getTransaction(true, true) - const acc = getAccount() - await putAccountP(tx.from.toString('hex'), acc) - await cacheFlushP() +tape('should fail when runCall fails', async (t) => { + const suite = setup() - shouldFail(st, - runTxP({ tx, populateCache: true }), - (e) => st.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') - ) + const tx = getTransaction(true, true) + const acc = createAccount() + await suite.putAccount(tx.from.toString('hex'), acc) + await suite.cacheFlush() - st.end() - }) + shouldFail(t, + suite.runTx({ tx, populateCache: true }), + (e) => t.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') + ) - t.test('should behave the same when not using cache', async (st) => { - const tx = getTransaction(true, true) - const acc = getAccount() - await putAccountP(tx.from.toString('hex'), acc) - await cacheFlushP() - vm.stateManager.cache.clear() - - shouldFail(st, - runTxP({ tx, populateCache: false }), - (e) => st.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') - ) + t.end() +}) - st.end() - }) +tape('should behave the same when not using cache', async (t) => { + const suite = setup() + + const tx = getTransaction(true, true) + const acc = createAccount() + await suite.putAccount(tx.from.toString('hex'), acc) + await suite.cacheFlush() + suite.vm.stateManager.cache.clear() + + shouldFail(t, + suite.runTx({ tx, populateCache: false }), + (e) => t.equal(e.message, 'test', 'error should be equal to what the mock runCall returns') + ) + + t.end() }) function shouldFail (st, p, onErr) { @@ -98,12 +114,3 @@ function getTransaction (sign = false, calculageGas = false) { return tx } - -function getAccount () { - const raw = { - nonce: '0x00', - balance: '0xfff384' - } - const acc = new Account(raw) - return acc -} diff --git a/tests/api/testdata.json b/tests/api/testdata.json new file mode 100644 index 0000000000..d3ac807ab4 --- /dev/null +++ b/tests/api/testdata.json @@ -0,0 +1,159 @@ +{ + "blocks": [ + { + "blockHeader": { + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty": "0x020000", + "extraData": "0x", + "gasLimit": "0x023ec6", + "gasUsed": "0x021536", + "hash": "0xf53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3", + "mixHash": "0x29f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3", + "nonce": "0x8957e6d004a31802", + "number": "0x01", + "parentHash": "0xce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae", + "receiptTrie": "0x5c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7", + "stateRoot": "0xa65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4", + "timestamp": "0x56851097", + "transactionsTrie": "0x70616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "rlp": "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845685109780a029f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3888957e6d004a31802f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0", + "transactions": [ + { + "data": "0x", + "gasLimit": "0x55f0", + "gasPrice": "0x0a", + "nonce": "0x00", + "r": "0x575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecd", + "s": "0x6baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188", + "to": "0xaaaf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1c", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x01", + "r": "0x4fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5b", + "s": "0x17bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192e", + "to": "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1b", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x02", + "r": "0x04377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458ada", + "s": "0x53a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5", + "to": "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1c", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x03", + "r": "0x4fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615", + "s": "0x651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668", + "to": "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1c", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x04", + "r": "0x78e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567d", + "s": "0x13254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198dd", + "to": "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1b", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x05", + "r": "0xa7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54", + "s": "0x534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506", + "to": "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1b", + "value": "0x0a" + }, + { + "data": "0x", + "gasLimit": "0x5208", + "gasPrice": "0x0a", + "nonce": "0x06", + "r": "0x34bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59", + "s": "0x78807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616", + "to": "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "v": "0x1b", + "value": "0x0a" + } + ], + "uncleHeaders": [] + } + ], + "genesisBlockHeader": { + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty": "0x020000", + "extraData": "0x42", + "gasLimit": "0x023e38", + "gasUsed": "0x00", + "hash": "0xce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae", + "mixHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce": "0x0102030405060708", + "number": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot": "0xaf81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0", + "timestamp": "0x54c98c81", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "genesisRLP": "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0", + "lastblockhash": "0xf53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3", + "postState": { + "8888f1f195afa192cfee860698584c030f4c9db1": { + "balance": "0x456391824508d41c", + "code": "0x", + "nonce": "0x00", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x4a723dc6b40b8cedf70fa8", + "code": "0x", + "nonce": "0x07", + "storage": {} + }, + "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x3c", + "code": "0x", + "nonce": "0x00", + "storage": {} + } + }, + "pre": { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x4a723dc6b40b8a9a000000", + "code": "0x", + "nonce": "0x00", + "storage": {} + }, + "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x02540be400", + "code": "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff", + "nonce": "0x00", + "storage": {} + } + } +} diff --git a/tests/api/utils.js b/tests/api/utils.js new file mode 100644 index 0000000000..daacb8a53c --- /dev/null +++ b/tests/api/utils.js @@ -0,0 +1,23 @@ +const Block = require('ethereumjs-block') +const Account = require('ethereumjs-account') + +function createGenesis () { + const genesis = new Block() + genesis.setGenesisParams() + + return genesis +} + +function createAccount () { + const raw = { + nonce: '0x00', + balance: '0xfff384' + } + const acc = new Account(raw) + return acc +} + +module.exports = { + createGenesis, + createAccount +} From cac3e5384c2651c437fb14bd7f36d6eadf7bc3d2 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 1 Aug 2018 22:05:57 +0200 Subject: [PATCH 10/13] Add tests for index, fix err handling in runBlockchain Signed-off-by: Sina Mahmoodi --- lib/fakeBlockChain.js | 1 + lib/runBlockchain.js | 5 ++- tests/api/index.js | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 tests/api/index.js diff --git a/lib/fakeBlockChain.js b/lib/fakeBlockChain.js index 6c55caeead..f08e976774 100644 --- a/lib/fakeBlockChain.js +++ b/lib/fakeBlockChain.js @@ -2,6 +2,7 @@ const Buffer = require('safe-buffer').Buffer const utils = require('ethereumjs-util') module.exports = { + fake: true, getBlock: function (blockTag, cb) { var hash diff --git a/lib/runBlockchain.js b/lib/runBlockchain.js index a2013fbfc3..255bb392f3 100644 --- a/lib/runBlockchain.js +++ b/lib/runBlockchain.js @@ -53,8 +53,9 @@ module.exports = function (blockchain, cb) { }, function (err, results) { if (err) { // remove invalid block - console.log('Invalid block error:', err) - blockchain.delBlock(block.header.hash(), cb) + blockchain.delBlock(block.header.hash(), function () { + cb(err) + }) } else { // set as new head block headBlock = block diff --git a/tests/api/index.js b/tests/api/index.js new file mode 100644 index 0000000000..78c424dc67 --- /dev/null +++ b/tests/api/index.js @@ -0,0 +1,100 @@ +const { promisify } = require('util') +const tape = require('tape') +const Level = require('levelup') +const util = require('ethereumjs-util') +const Blockchain = require('ethereumjs-blockchain') +const Block = require('ethereumjs-block') +const VM = require('../../lib/index') +const testData = require('./testdata.json') + +tape('VM with fake blockchain', (t) => { + t.test('should insantiate without params', (st) => { + const vm = new VM() + st.ok(vm.stateManager) + st.equal(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has default trie') + st.ok(vm.stateManager.blockchain.fake, 'it has fake blockchain by default') + st.end() + }) + + t.test('should be able to activate precompiles', (st) => { + let vm = new VM({ activatePrecompiles: true }) + st.notEqual(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has different root') + st.end() + }) + + t.test('should only accept valid chain and fork', (st) => { + let vm = new VM({ chain: 'ropsten', hardfork: 'byzantium' }) + st.equal(vm.stateManager._common.param('gasPrices', 'ecAdd'), 500) + + try { + vm = new VM({ chain: 'mainchain', hardfork: 'homestead' }) + st.fail('should have failed for invalid chain') + } catch (e) { + st.ok(e.message.includes('not supported')) + } + + st.end() + }) + + t.test('should run blockchain without blocks', async (st) => { + const vm = new VM() + const run = promisify(vm.runBlockchain.bind(vm)) + await run() + st.end() + }) +}) + +tape('VM with blockchain', (t) => { + const db = new Level('', { + db: require('memdown') + }) + var cacheDB = new Level('./.cachedb') + const blockchain = new Blockchain(db) + blockchain.ethash.cacheDB = cacheDB + + const putGenesisP = promisify(blockchain.putGenesis.bind(blockchain)) + const putBlockP = promisify(blockchain.putBlock.bind(blockchain)) + const getHeadP = promisify(blockchain.getHead.bind(blockchain)) + + t.test('should instantiate', (st) => { + const vm = new VM({ + blockchain + }) + st.equal(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has default trie') + st.notOk(vm.stateManager.blockchain.fake, 'it doesn\'t have fake blockchain') + st.end() + }) + + t.test('should run blockchain without blocks', async (st) => { + const vm = new VM({ blockchain }) + await runBlockchain(vm) + st.end() + }) + + t.test('should run blockchain with blocks', async (st) => { + const vm = new VM({ blockchain }) + const genesis = new Block(Buffer.from(testData.genesisRLP.slice(2), 'hex')) + const block = new Block(Buffer.from(testData.blocks[0].rlp.slice(2), 'hex')) + + await putGenesisP(genesis) + st.equal(blockchain.meta.genesis, 'ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae') + + await putBlockP(block) + const head = await getHeadP() + st.equal( + head.hash().toString('hex'), + 'f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3' + ) + + vm.runBlock = (block, cb) => cb(new Error('test')) + runBlockchain(vm) + .then(() => st.fail('it hasn\'t returned any errors')) + .catch((e) => { st.equal(e.message, 'test', 'it has correctly propagated runBlock\'s error') }) + + st.end() + }) +}) + +const runBlockchain = (vm) => { + return promisify(vm.runBlockchain.bind(vm))() +} From a72c5e470ec953cdc44552b6ea3b95104055a630 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 1 Aug 2018 22:45:08 +0200 Subject: [PATCH 11/13] Add tests for stateManager, fix getStateRoot in stateManager Signed-off-by: Sina Mahmoodi --- lib/stateManager.js | 2 +- tests/api/stateManager.js | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/api/stateManager.js diff --git a/lib/stateManager.js b/lib/stateManager.js index c7f7c3ed7c..1a5c514bb7 100644 --- a/lib/stateManager.js +++ b/lib/stateManager.js @@ -270,7 +270,7 @@ proto.revert = function (cb) { // proto.getStateRoot = function (cb) { var self = this - self.cacheFlush(function (err) { + self.cache.flush(function (err) { if (err) { return cb(err) } diff --git a/tests/api/stateManager.js b/tests/api/stateManager.js new file mode 100644 index 0000000000..d0d3a5f4d7 --- /dev/null +++ b/tests/api/stateManager.js @@ -0,0 +1,38 @@ +const { promisify } = require('util') +const tape = require('tape') +const util = require('ethereumjs-util') +const StateManager = require('../../lib/stateManager') +const { createAccount } = require('./utils') + +tape('StateManager', (t) => { + t.test('should instantiate', (st) => { + const stateManager = new StateManager() + st.ok(stateManager.blockchain.fake, 'it has fake blockchain') + + st.equal(stateManager.trie.root, util.KECCAK256_RLP, 'it has default root') + stateManager.getStateRoot((err, res) => { + st.error(err, 'getStateRoot returns no error') + st.equal(res, util.KECCAK256_RLP, 'it has default root') + }) + + st.equal(stateManager._common.hardfork(), 'byzantium', 'it has default hardfork') + st.end() + }) + + t.test('should put and get account', async (st) => { + const stateManager = new StateManager() + const account = createAccount() + + await promisify(stateManager.putAccount.bind(stateManager))( + 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', + account + ) + + let res = await promisify(stateManager.getAccount.bind(stateManager))( + 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' + ) + + st.equal(res.balance.toString('hex'), 'fff384') + st.end() + }) +}) From 909dfdbf162f4cda8a93c08e03f2cd2c29067f45 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 1 Aug 2018 23:16:39 +0200 Subject: [PATCH 12/13] Add testAPI cmd, fix a case Signed-off-by: Sina Mahmoodi --- package.json | 1 + tests/api/index.js | 7 ++++--- tests/api/runBlockchain.js | 13 +++++++++---- tests/api/runner.js | 8 ++++++++ tests/tester.js | 1 + 5 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 tests/api/runner.js diff --git a/package.json b/package.json index 98d54f44b7..cdf4a1e4c4 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "testBlockchainBlockGasLimit": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --dist --dir='bcBlockGasLimitTest'", "testBlockchainValid": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --dist --dir='bcValidBlockTest'", "testBlockchainTotalDifficulty": "npm run build:dist && node --stack-size=1500 ./tests/tester -b --dist --dir='bcTotalDifficultyTest'", + "testAPI": "node ./tests/api/runner", "test": "node ./tests/tester -a", "lint": "standard", "prepublishOnly": "npm run lint && npm run build:dist && npm run testBuildIntegrity", diff --git a/tests/api/index.js b/tests/api/index.js index 78c424dc67..8a83939932 100644 --- a/tests/api/index.js +++ b/tests/api/index.js @@ -89,9 +89,10 @@ tape('VM with blockchain', (t) => { vm.runBlock = (block, cb) => cb(new Error('test')) runBlockchain(vm) .then(() => st.fail('it hasn\'t returned any errors')) - .catch((e) => { st.equal(e.message, 'test', 'it has correctly propagated runBlock\'s error') }) - - st.end() + .catch((e) => { + st.equal(e.message, 'test', 'it has correctly propagated runBlock\'s error') + st.end() + }) }) }) diff --git a/tests/api/runBlockchain.js b/tests/api/runBlockchain.js index 3411ce9d56..4bbd109abc 100644 --- a/tests/api/runBlockchain.js +++ b/tests/api/runBlockchain.js @@ -66,12 +66,17 @@ tape('runBlockchain', (t) => { let head = await getHeadP() st.deepEqual(head.hash(), b3.hash(), 'block3 should be the current head') - await runBlockchainP(blockchain) + try { + await runBlockchainP(blockchain) + st.fail('should have returned error') + } catch (e) { + st.equal(e.message, 'test') - head = await getHeadP() - st.deepEqual(head.hash(), b2.hash(), 'should have removed invalid block from head') + head = await getHeadP() + st.deepEqual(head.hash(), b2.hash(), 'should have removed invalid block from head') - st.end() + st.end() + } }) }) diff --git a/tests/api/runner.js b/tests/api/runner.js new file mode 100644 index 0000000000..812d800fd1 --- /dev/null +++ b/tests/api/runner.js @@ -0,0 +1,8 @@ +require('./index') +require('./runBlockchain') +require('./runBlock') +require('./runTx') +require('./stateManager') +require('./bloom') +require('./runJit') +require('./fakeBlockChain') diff --git a/tests/tester.js b/tests/tester.js index ae0368112d..c004c71e5f 100755 --- a/tests/tester.js +++ b/tests/tester.js @@ -249,6 +249,7 @@ function runAll () { require('./tester.js') require('./cacheTest.js') require('./genesishashes.js') + require('./api/runner.js') async.series([ // runTests.bind(this, 'VMTests', {}), // VM tests disabled since we don't support Frontier gas costs runTests.bind(this, 'GeneralStateTests', {}), From 44a92c802699aabfeff17e72576cfc7c7bee87ee Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Wed, 1 Aug 2018 23:30:42 +0200 Subject: [PATCH 13/13] Fix small lint error Signed-off-by: Sina Mahmoodi --- tests/api/runBlock.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/api/runBlock.js b/tests/api/runBlock.js index 9e8fbc9253..9e235e8280 100644 --- a/tests/api/runBlock.js +++ b/tests/api/runBlock.js @@ -2,7 +2,6 @@ const { promisify } = require('util') const tape = require('tape') const Block = require('ethereumjs-block') const Transaction = require('ethereumjs-tx') -const Account = require('ethereumjs-account') const Common = require('ethereumjs-common') const util = require('ethereumjs-util') const runBlock = require('../../lib/runBlock')