Skip to content

Commit

Permalink
Fix blockchain tests
Browse files Browse the repository at this point in the history
This fixes the last set of blockchain tests:

* RPC_API_Test
* randomStatetest224BC
* randomStatetest234BC
* randomStatetest529BC
* ExtraData32
* log1_correct
* timeDiff0
* timeDiff12
* timeDiff13
* timeDiff14

These were mostly caused by missing block validation and the intentional disparity between the bloom filter implementation and the yellow paper introduced in #295.
  • Loading branch information
mattdean-digicatapult committed Nov 14, 2018
1 parent 6da9f00 commit 4b08400
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 27 deletions.
18 changes: 2 additions & 16 deletions lib/bloom.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,6 @@ const assert = require('assert')
const utils = require('ethereumjs-util')
const byteSize = 256

/**
* Drops leading zeroes from a buffer
* @function dropLeadingZeroes
* @param {Buffer} buff
* @returns {Buffer} a slice of the given buffer starting at the first non-zero entry
*/
function dropLeadingZeroes (buff) {
for (var i = 0; i < buff.length; i++) {
if (buff[i] !== 0) {
return buff.slice(i)
}
}
}

/**
* Represents a Bloom
* @constructor
Expand All @@ -36,7 +22,7 @@ var Bloom = module.exports = function (bitvector) {
* @param {Buffer} e the element to add
*/
Bloom.prototype.add = function (e) {
e = utils.keccak256(dropLeadingZeroes(e))
e = utils.keccak256(e)
var mask = 2047 // binary 11111111111

for (var i = 0; i < 3; i++) {
Expand All @@ -55,7 +41,7 @@ Bloom.prototype.add = function (e) {
* @returns {boolean} Returns {@code true} if the element is in the bloom
*/
Bloom.prototype.check = function (e) {
e = utils.keccak256(dropLeadingZeroes(e))
e = utils.keccak256(e)
var mask = 2047 // binary 11111111111
var match = true

Expand Down
11 changes: 8 additions & 3 deletions lib/runBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = function (opts, cb) {

// parse options
const block = opts.block
const skipBlockValidation = opts.skipBlockValidation || false
const generateStateRoot = !!opts.generate
const validateStateRoot = !generateStateRoot
const bloom = new Bloom()
Expand Down Expand Up @@ -80,10 +81,14 @@ module.exports = function (opts, cb) {
}

function validateBlock (cb) {
if (new BN(block.header.gasLimit).gte(new BN('8000000000000000', 16))) {
cb(new Error('Invalid block with gas limit greater than (2^63 - 1)'))
} else {
if (skipBlockValidation) {
cb()
} else {
if (new BN(block.header.gasLimit).gte(new BN('8000000000000000', 16))) {
cb(new Error('Invalid block with gas limit greater than (2^63 - 1)'))
} else {
block.validate(self.blockchain, cb)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/api/bloom.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ tape('bloom', (t) => {
bloom.add(Buffer.from('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', 'hex'))
st.equal(
bloom.bitvector.toString('hex'),
'00000000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000000000000000004000000080000200000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010008000000000000000002000000000000000000000000008000000000000'
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000081100200000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000002000000000000000004000000000000000000000'
)
st.end()
})
Expand Down
31 changes: 24 additions & 7 deletions tests/api/runBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ tape('runBlock', async (t) => {
const suite = setup()

t.test('should fail without params', async (st) => {
suite.p.runBlock()
await 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({})
await suite.p.runBlock({})
.then(() => st.fail('should have returned error'))
.catch((e) => st.ok(e.message.includes('invalid input'), 'correct error'))

Expand All @@ -64,7 +64,7 @@ tape('runBlock', async (t) => {

// The mocked VM uses a mocked runTx
// which always returns an error.
await suite.p.runBlock({ block, root: genesis.header.stateRoot })
await suite.p.runBlock({ block, root: genesis.header.stateRoot, skipBlockValidation: true })
.then(() => t.fail('should have returned error'))
.catch((e) => t.equal(e.message, 'test'))

Expand All @@ -82,13 +82,27 @@ tape('should fail when block gas limit higher than 2^63-1', async (t) => {
gasLimit: Buffer.from('8000000000000000', 16)
}
})
suite.p.runBlock({ block, root: genesis.header.stateRoot })
await suite.p.runBlock({ block, root: genesis.header.stateRoot })
.then(() => t.fail('should have returned error'))
.catch((e) => t.ok(e.message.includes('Invalid block')))

t.end()
})

tape('should fail when block validation fails', async (t) => {
const suite = setup()

const genesis = createGenesis()
const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp))
block.validate = (_, cb) => cb(new Error('test'))

await suite.p.runBlock({ block, root: genesis.header.stateRoot })
.then(() => t.fail('should have returned error'))
.catch((e) => t.ok(e.message.includes('test')))

t.end()
})

tape('should fail when tx gas limit higher than block gas limit', async (t) => {
const suite = setup()

Expand All @@ -98,7 +112,7 @@ tape('should fail when tx gas limit higher than block gas limit', async (t) => {

await suite.p.generateCanonicalGenesis()

await suite.p.runBlock({ block, root: genesis.header.stateRoot })
await suite.p.runBlock({ block, root: genesis.header.stateRoot, skipBlockValidation: true })
.then(() => t.fail('should have returned error'))
.catch((e) => t.ok(e.message.includes('higher gas limit')))

Expand All @@ -122,7 +136,9 @@ tape('should fail when runCall fails', async (t) => {
// which always returns an error.
// runTx is a full implementation that works.
suite.vm.runTx = runTx
await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root })

await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root, skipBlockValidation: true })

.then(() => t.fail('should have returned error'))
.catch((e) => t.equal(e.message, 'test'))

Expand All @@ -145,7 +161,8 @@ tape('should run valid block', async (t) => {
'genesis state root should match calculated state root'
)

let res = await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root })
let res = await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root, skipBlockValidation: true })

t.error(res.error, 'runBlock shouldn\'t have returned error')
t.equal(res.results[0].gasUsed.toString('hex'), '5208', 'actual gas used should equal blockHeader gasUsed')

Expand Down

0 comments on commit 4b08400

Please sign in to comment.