Skip to content

Commit

Permalink
vm: transition tests to TypeScript (all state and blockchain test fil…
Browse files Browse the repository at this point in the history
…es, some API tests)
  • Loading branch information
holgerd77 committed Sep 18, 2020
1 parent 601026b commit edcb1c9
Show file tree
Hide file tree
Showing 12 changed files with 600 additions and 572 deletions.
3 changes: 1 addition & 2 deletions packages/vm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"test:buildIntegrity": "npm run test:state -- --test='stackOverflow'",
"test:blockchain": "node -r ts-node/register --stack-size=1500 ./tests/tester --blockchain",
"test:blockchain:allForks": "echo 'Chainstart Homestead dao TangerineWhistle SpuriousDragon Byzantium Constantinople Petersburg Istanbul MuirGlacier Berlin ByzantiumToConstantinopleFixAt5 EIP158ToByzantiumAt5 FrontierToHomesteadAt5 HomesteadToDaoAt5 HomesteadToEIP150At5' | xargs -n1 | xargs -I v1 node -r ts-node/register --stack-size=1500 ./tests/tester --blockchain --fork=v1 --verify-test-amount-alltests",
"test:API": "tape -r ts-node/register --stack-size=1500 './tests/api/**/*.js'",
"test:API": "tape -r ts-node/register --stack-size=1500 './tests/api/**/*.js' './tests/api/**/*.ts'",
"test:API:browser": "npm run build && karma start karma.conf.js",
"test": "echo \"[INFO] Generic test cmd not used. See package.json for more specific test run cmds.\"",
"tslint": "ethereumjs-config-tslint",
Expand Down Expand Up @@ -54,7 +54,6 @@
"functional-red-black-tree": "^1.0.1",
"merkle-patricia-tree": "^4.0.0",
"rustbn.js": "~0.2.0",
"safe-buffer": "^5.1.1",
"util.promisify": "^1.0.1",
"mcl-wasm": "^0.4.5"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
const { setupPreConditions, verifyPostConditions, getDAOCommon } = require('./util.js')
const { addHexPrefix, rlp, bufferToInt } = require('ethereumjs-util')
const Trie = require('merkle-patricia-tree').SecureTrie
const { Block, BlockHeader } = require('@ethereumjs/block')
const Blockchain = require('@ethereumjs/blockchain').default
const Common = require('@ethereumjs/common').default
const level = require('level')
const levelMem = require('level-mem')

module.exports = async function runBlockchainTest(options, testData, t) {
import { addHexPrefix, rlp, bufferToInt } from 'ethereumjs-util'
import { SecureTrie as Trie } from 'merkle-patricia-tree'
import { Block, BlockHeader } from '@ethereumjs/block'
import Blockchain from '@ethereumjs/blockchain'
import tape = require('tape')
import { setupPreConditions, verifyPostConditions, getDAOCommon } from './util'

export default async function runBlockchainTest(options: any, testData: any, t: tape.Test) {
// ensure that the test data is the right fork data

if (testData.network != options.forkConfigTestSuite) {
Expand All @@ -30,10 +31,10 @@ module.exports = async function runBlockchainTest(options, testData, t) {
if (testData.sealEngine && testData.sealEngine === 'Ethash') {
validatePow = true
}

let eips = []
if (options.forkConfigVM == 'berlin') {
// currently, the BLS tests run on the Berlin network, but our VM does not activate EIP2537
// currently, the BLS tests run on the Berlin network, but our VM does not activate EIP2537
// if you run the Berlin HF
eips = [2537]
}
Expand All @@ -45,11 +46,11 @@ module.exports = async function runBlockchainTest(options, testData, t) {
db: blockchainDB,
common,
validateBlocks: true,
validatePow
validatePow,
})

if (validatePow) {
blockchain.ethash.cacheDB = cacheDB
;(blockchain.ethash as any).cacheDB = cacheDB
}

let VM
Expand All @@ -62,19 +63,16 @@ module.exports = async function runBlockchainTest(options, testData, t) {
const vm = new VM({
state,
blockchain,
common
common,
})

const genesisBlock = new Block(undefined, { common })
// create and add genesis block
const blockData = { header: formatBlockHeader(testData.genesisBlockHeader) }
const genesisBlock = new Block(blockData, { common })

// set up pre-state
await setupPreConditions(vm.stateManager._trie, testData)

// create and add genesis block
genesisBlock.header = new BlockHeader(formatBlockHeader(testData.genesisBlockHeader), {
common,
})

t.ok(vm.stateManager._trie.root.equals(genesisBlock.header.stateRoot), 'correct pre stateRoot')

if (testData.genesisRLP) {
Expand All @@ -87,7 +85,7 @@ module.exports = async function runBlockchainTest(options, testData, t) {

await blockchain.putGenesis(genesisBlock)

async function handleError(error, expectException) {
async function handleError(error: string | undefined, expectException: string) {
if (expectException) {
t.pass(`Expected exception ${expectException}`)
} else {
Expand All @@ -97,7 +95,7 @@ module.exports = async function runBlockchainTest(options, testData, t) {
}

let currentFork = common.hardfork()
let currentBlock
let currentBlock = 0
let lastBlock = 0
for (const raw of testData.blocks) {
lastBlock = currentBlock
Expand All @@ -106,27 +104,28 @@ module.exports = async function runBlockchainTest(options, testData, t) {
// Last checked: ethereumjs-testing v1.3.1 (2020-05-11)
const paramAll1 = 'expectExceptionALL'
const paramAll2 = 'expectException'
const expectException = raw[paramFork] ? raw[paramFork] : raw[paramAll1] || raw[paramAll2] || raw.blockHeader == undefined
const expectException = raw[paramFork]
? raw[paramFork]
: raw[paramAll1] || raw[paramAll2] || raw.blockHeader == undefined

// here we convert the rlp to block only to extract the number
// we have to do this again later because the common might run on a new hardfork
try {
let block = new Block(Buffer.from(raw.rlp.slice(2), 'hex'), {
common
})
common,
})
currentBlock = bufferToInt(block.header.number)
} catch(e) {
} catch (e) {
handleError(e, expectException)
continue
}

if (currentBlock < lastBlock) {
// "re-org": rollback the blockchain to currentBlock (i.e. delete that block number in the blockchain plus the children)
t.fail("re-orgs are not supported by the test suite")
t.fail('re-orgs are not supported by the test suite')
return
}
try {

// check if we should update common.
let newFork = common.setHardforkByBlockNumber(currentBlock)
if (newFork != currentFork) {
Expand All @@ -135,8 +134,8 @@ module.exports = async function runBlockchainTest(options, testData, t) {
}

const block = new Block(Buffer.from(raw.rlp.slice(2), 'hex'), {
common
})
common,
})
await blockchain.putBlock(block)

// This is a trick to avoid generating the canonical genesis
Expand Down Expand Up @@ -164,7 +163,7 @@ module.exports = async function runBlockchainTest(options, testData, t) {
await cacheDB.close()

if (expectException) {
t.fail("expected exception but test did not throw an exception: " + expectException)
t.fail('expected exception but test did not throw an exception: ' + expectException)
return
}
} catch (error) {
Expand All @@ -174,15 +173,15 @@ module.exports = async function runBlockchainTest(options, testData, t) {
}
}
t.equal(
blockchain.meta.rawHead.toString('hex'),
(blockchain.meta as any).rawHead.toString('hex'),
testData.lastblockhash,
'correct last header block',
)
await cacheDB.close()
}

function formatBlockHeader(data) {
const r = {}
function formatBlockHeader(data: any) {
const r: any = {}
const keys = Object.keys(data)
keys.forEach(function (key) {
r[key] = addHexPrefix(data[key])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
const { setupPreConditions, makeTx, makeBlockFromEnv } = require('./util')
const Trie = require('merkle-patricia-tree').SecureTrie
const { BN } = require('ethereumjs-util')
const { default: Common } = require('@ethereumjs/common')
const Account = require('@ethereumjs/account').default

function parseTestCases(forkConfigTestSuite, testData, data, gasLimit, value) {
import { setupPreConditions, makeTx, makeBlockFromEnv } from './util'
import { SecureTrie as Trie } from 'merkle-patricia-tree'
import { BN } from 'ethereumjs-util'
import Common from '@ethereumjs/common'
import Account from '@ethereumjs/account'
import tape = require('tape')

function parseTestCases(
forkConfigTestSuite: string,
testData: any,
data: string | undefined,
gasLimit: string | undefined,
value: string | undefined,
) {
let testCases = []
if (testData['post'][forkConfigTestSuite]) {
testCases = testData['post'][forkConfigTestSuite].map((testCase) => {
testCases = testData['post'][forkConfigTestSuite].map((testCase: any) => {
let testIndexes = testCase['indexes']
let tx = { ...testData.transaction }
if (data !== undefined && testIndexes['data'] !== data) {
Expand All @@ -34,49 +41,48 @@ function parseTestCases(forkConfigTestSuite, testData, data, gasLimit, value) {
})
}

testCases = testCases.filter((testCase) => {
testCases = testCases.filter((testCase: any) => {
return testCase != null
})

return testCases
}

async function runTestCase(options, testData, t) {
async function runTestCase(options: any, testData: any, t: tape.Test) {
const state = new Trie()
let block, vm
let VM
if (options.dist) {
VM = require('../dist/index.js').default
} else {
VM = require('../lib/index').default
}

let eips = []
let eips: number[] = []
if (options.forkConfigVM == 'berlin') {
// currently, the BLS tests run on the Berlin network, but our VM does not activate EIP2537
// currently, the BLS tests run on the Berlin network, but our VM does not activate EIP2537
// if you run the Berlin HF
eips = [2537]
eips = [2537]
}

const common = new Common({ chain: 'mainnet', hardfork: options.forkConfigVM, eips })
vm = new VM({
let vm = new VM({
state,
common: common
common: common,
})

await setupPreConditions(vm.stateManager._trie, testData)

let tx = makeTx(testData.transaction, { common })
block = makeBlockFromEnv(testData.env)
let block = makeBlockFromEnv(testData.env)

if (!tx.validate()) {
return
}

if (options.jsontrace) {
vm.on('step', function (e) {
vm.on('step', function (e: any) {
let hexStack = []
hexStack = e.stack.map((item) => {
hexStack = e.stack.map((item: any) => {
return '0x' + new BN(item).toString(16, 0)
})

Expand Down Expand Up @@ -124,7 +130,7 @@ async function runTestCase(options, testData, t) {
)
}

module.exports = async function runStateTest(options, testData, t) {
export default async function runStateTest(options: any, testData: any, t: tape.Test) {
try {
const testCases = parseTestCases(
options.forkConfigTestSuite,
Expand Down
38 changes: 26 additions & 12 deletions packages/vm/tests/api/bloom.js → packages/vm/tests/api/bloom.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
const tape = require('tape')
const Bloom = require('../../dist/bloom').default
const utils = require('ethereumjs-util')
import * as tape from 'tape'

import Bloom from '../../dist/bloom'
import * as utils from 'ethereumjs-util'

const byteSize = 256

tape('bloom', (t) => {
tape('bloom', (t: tape.Test) => {
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.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 hex =
'00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000'
const vector = Buffer.from(hex, 'hex')

const b = new Bloom(vector)
Expand All @@ -29,7 +34,10 @@ tape('bloom', (t) => {

t.test('check shouldnt be tautology', (st) => {
const b = new Bloom()
st.false(b.check(Buffer.from('random value', 'utf8')), 'should not contain string "random value"')
st.false(
b.check(Buffer.from('random value', 'utf8')),
'should not contain string "random value"',
)
st.end()
})

Expand Down Expand Up @@ -64,12 +72,18 @@ tape('bloom', (t) => {
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'))
bloom.add(
Buffer.from('8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', 'hex'),
)
bloom.add(
Buffer.from('0000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a631', 'hex'),
)
bloom.add(
Buffer.from('0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', 'hex'),
)
st.equal(
bloom.bitvector.toString('hex'),
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000081100200000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000002000000000000000004000000000000000000000'
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000081100200000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000002000000000000000004000000000000000000000',
)
st.end()
})
Expand Down
Loading

1 comment on commit edcb1c9

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: edcb1c9 Previous: 601026b Ratio
Block 9422905 1724 ops/sec (±3.03%) 1951 ops/sec (±3.65%) 1.13
Block 9422906 1661 ops/sec (±7.78%) 1842 ops/sec (±7.02%) 1.11
Block 9422907 1759 ops/sec (±1.20%) 1928 ops/sec (±1.10%) 1.10
Block 9422908 1790 ops/sec (±1.35%) 1898 ops/sec (±1.29%) 1.06
Block 9422909 1735 ops/sec (±1.06%) 1848 ops/sec (±1.45%) 1.07
Block 9422910 1415 ops/sec (±11.81%) 1843 ops/sec (±1.44%) 1.30
Block 9422911 1677 ops/sec (±1.50%) 1556 ops/sec (±12.15%) 0.93
Block 9422912 1659 ops/sec (±1.28%) 1601 ops/sec (±9.54%) 0.97
Block 9422913 1704 ops/sec (±1.08%) 1826 ops/sec (±1.33%) 1.07
Block 9422914 1631 ops/sec (±1.54%) 1732 ops/sec (±1.70%) 1.06

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.