diff --git a/.travis.yml b/.travis.yml index 6086898..100f486 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,31 @@ +sudo: false +os: + - linux + language: node_js node_js: - - "7" -before_install: - - npm install . - - cd tools - - wget https://storage.googleapis.com/chromium-v8/node-linux-rel/node-linux-rel-41967-121bf38bc0a2973476ba378ddd3ff3b5f97ae494.zip -O nodejs.zip - - unzip nodejs.zip - - cd bin + - "8" -env: - - CXX=g++-4.8 addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-4.8 - - wget - - unzip + +branches: + # We need to whitelist the branches which we want to have "push" automation. + # Pull request automation is not constrained to this set of branches. + only: + - master matrix: fast_finish: true include: - os: linux - node_js: "7" - env: TEST_SUITE=test - - os: linux - node_js: "7" + node_js: "8" env: TEST_SUITE=lint -script: ./npm run $TEST_SUITE - + - os: linux + node_js: "8" + env: CXX=g++-4.8 TEST_SUITE=test +script: npm run $TEST_SUITE diff --git a/EVMimports.js b/EVMimports.js index 43abc25..bf6dcc0 100644 --- a/EVMimports.js +++ b/EVMimports.js @@ -12,6 +12,10 @@ const U128_SIZE_BYTES = 16 const ADDRESS_SIZE_BYTES = 20 const U256_SIZE_BYTES = 32 +const log = require('loglevel') +log.setLevel('warn') // hide logs +//log.setLevel('debug') // for debugging + // The interface exposed to the WebAessembly Core module.exports = class Interface { constructor (kernel) { @@ -109,6 +113,7 @@ module.exports = class Interface { * @param {integer} offset */ getAddress (offset) { + log.debug('EVMImports.js getAddress') this.takeGas(2) this.setMemory(offset, ADDRESS_SIZE_BYTES, this.kernel.environment.address.toMemory()) @@ -121,6 +126,7 @@ module.exports = class Interface { * @param {integer} resultOffset */ getBalance (addressOffset, offset, cbIndex) { + log.debug('EVMImports.js getBalance') this.takeGas(20) const path = [...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES), 'balance'] @@ -140,6 +146,7 @@ module.exports = class Interface { * @param {integer} offset */ getTxOrigin (offset) { + log.debug('EVMImports.js getTxOrigin') this.takeGas(2) this.setMemory(offset, ADDRESS_SIZE_BYTES, this.kernel.environment.origin.toMemory()) @@ -151,6 +158,7 @@ module.exports = class Interface { * @param {integer} offset */ getCaller (offset) { + log.debug('EVMImports.js getCaller') this.takeGas(2) this.setMemory(offset, ADDRESS_SIZE_BYTES, this.kernel.environment.caller.toMemory()) @@ -162,6 +170,7 @@ module.exports = class Interface { * @param {integer} offset */ getCallValue (offset) { + log.debug('EVMImports.js getCallValue') this.takeGas(2) this.setMemory(offset, U128_SIZE_BYTES, this.kernel.environment.callValue.toMemory(U128_SIZE_BYTES)) @@ -173,6 +182,7 @@ module.exports = class Interface { * @return {integer} */ getCallDataSize () { + log.debug('EVMImports.js getCallDataSize') this.takeGas(2) return this.kernel.environment.callData.length @@ -186,6 +196,7 @@ module.exports = class Interface { * @param {integer} length the length of data to copy */ callDataCopy (offset, dataOffset, length) { + log.debug('EVMImports.js callDataCopy') this.takeGas(3 + Math.ceil(length / 32) * 3) if (length) { @@ -201,6 +212,7 @@ module.exports = class Interface { * @param {integer} dataOffset the offset in the input data */ callDataCopy256 (offset, dataOffset) { + log.debug('EVMImports.js callDataCopy256') this.takeGas(3) const callData = this.kernel.environment.callData.slice(dataOffset, dataOffset + 32) this.setMemory(offset, U256_SIZE_BYTES, callData) @@ -211,6 +223,7 @@ module.exports = class Interface { * @return {interger} */ getCodeSize (cbIndex) { + log.debug('EVMImports.js getCodeSize') this.takeGas(2) const opPromise = this.kernel.environment.state @@ -228,6 +241,7 @@ module.exports = class Interface { * @param {integer} length the length of code to copy */ codeCopy (resultOffset, codeOffset, length, cbIndex) { + log.debug('EVMimports.js codeCopy') this.takeGas(3 + Math.ceil(length / 32) * 3) let opPromise @@ -255,6 +269,7 @@ module.exports = class Interface { * @return {integer} */ getExternalCodeSize (addressOffset, cbOffset) { + log.debug('EVMImports.js getExternalCodeSize') this.takeGas(20) const address = [...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES), 'code'] const opPromise = this.kernel.environment.state.root @@ -274,6 +289,7 @@ module.exports = class Interface { * @param {integer} length the length of code to copy */ externalCodeCopy (addressOffset, resultOffset, codeOffset, length, cbIndex) { + log.debug('EVMImports.js externalCodeCopy') this.takeGas(20 + Math.ceil(length / 32) * 3) const address = [...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES), 'code'] @@ -302,6 +318,7 @@ module.exports = class Interface { * @return {integer} */ getTxGasPrice () { + log.debug('EVMImports.js getTxGasPrice') this.takeGas(2) return this.kernel.environment.gasPrice @@ -313,6 +330,7 @@ module.exports = class Interface { * @param {integer} offset the offset to load the hash into */ getBlockHash (number, offset, cbOffset) { + log.debug('EVMImports.js getBlockHash') this.takeGas(20) const diff = this.kernel.environment.block.number - number @@ -335,6 +353,8 @@ module.exports = class Interface { * @param offset */ getBlockCoinbase (offset) { + log.debug('EVMImports.js getBlockCoinbase') + log.debug('this.kernel.environment.coinbase:', this.kernel.environment.coinbase) this.takeGas(2) this.setMemory(offset, ADDRESS_SIZE_BYTES, this.kernel.environment.coinbase.toMemory()) @@ -345,6 +365,7 @@ module.exports = class Interface { * @return {integer} */ getBlockTimestamp () { + log.debug('EVMImports.js getBlockTimestamp') this.takeGas(2) return this.kernel.environment.block.timestamp @@ -355,6 +376,7 @@ module.exports = class Interface { * @return {integer} */ getBlockNumber () { + log.debug('EVMImports.js getBlockNumber') this.takeGas(2) return this.kernel.environment.block.number @@ -365,6 +387,7 @@ module.exports = class Interface { * @return {integer} */ getBlockDifficulty (offset) { + log.debug('EVMImports.js getBlockDifficulty') this.takeGas(2) this.setMemory(offset, U256_SIZE_BYTES, this.kernel.environment.block.difficulty.toMemory()) @@ -375,6 +398,7 @@ module.exports = class Interface { * @return {integer} */ getBlockGasLimit () { + log.debug('EVMImports.js getBlockGasLimit') this.takeGas(2) return this.kernel.environment.block.gasLimit @@ -387,6 +411,7 @@ module.exports = class Interface { * @param {integer} number of topics */ log (dataOffset, length, numberOfTopics, topic1, topic2, topic3, topic4) { + log.debug('EVMImports.js log') if (numberOfTopics < 0 || numberOfTopics > 4) { throw new Error('Invalid numberOfTopics') } @@ -427,6 +452,7 @@ module.exports = class Interface { * @return {integer} Return 1 or 0 depending on if the VM trapped on the message or not */ create (valueOffset, dataOffset, length, resultOffset, cbIndex) { + log.debug('EVMImports.js create') this.takeGas(32000) const value = U256.fromMemory(this.getMemory(valueOffset, U128_SIZE_BYTES)) @@ -461,6 +487,7 @@ module.exports = class Interface { * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not */ _call (gasHigh, gasLow, addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, cbIndex) { + log.debug('EVMimports.js _call') this.takeGas(40) const gas = from64bit(gasHigh, gasLow) @@ -474,12 +501,14 @@ module.exports = class Interface { this.takeGas(-gas) } + log.debug('EVMimports.js _call calling this.kernel.environment.state.root.get(address)') let opPromise = this.kernel.environment.state.root.get(address) .catch(() => { // why does this exist? this.takeGas(25000) }) + log.debug('EVMimports.js _call pushing opPromise to pushOpsQueue') // wait for all the prevouse async ops to finish before running the callback this.kernel.pushOpsQueue(opPromise, cbIndex, () => { return 1 @@ -498,6 +527,7 @@ module.exports = class Interface { * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not */ callCode (gas, addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, cbIndex) { + log.debug('EVMimports.js callCode') this.takeGas(40) // Load the params from mem const path = [...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES), 'code'] @@ -508,6 +538,9 @@ module.exports = class Interface { this.takeGas(6700) } + //log.debug('EVMimports.js callCode this.kernel.environment.state:', this.kernel.environment.state) + // environment.state is a Vertex object + // TODO: should be message? const opPromise = this.kernel.environment.state.root.get(path) .catch(() => { @@ -534,6 +567,7 @@ module.exports = class Interface { * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not */ callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) { + log.debug('EVMimports.js callDelegate') // FIXME: count properly this.takeGas(40) @@ -551,6 +585,7 @@ module.exports = class Interface { * @param {interger} valueOffset the memory offset to load the value from */ storageStore (pathOffset, valueOffset, cbIndex) { + log.debug('EVMimports.js storageStore') this.takeGas(5000) const path = ['storage', ...this.getMemory(pathOffset, U256_SIZE_BYTES)] // copy the value @@ -584,6 +619,7 @@ module.exports = class Interface { * @param {interger} resultOffset the memory offset to load the value from */ storageLoad (pathOffset, resultOffset, cbIndex) { + log.debug('EVMimports.js storageLoad') this.takeGas(50) // convert the path to an array @@ -615,6 +651,7 @@ module.exports = class Interface { * @param {integer} offset the offset to load the address from */ selfDestruct (addressOffset) { + log.debug('EVMimports.js selfDestruct') this.kernel.environment.selfDestruct = true this.kernel.environment.selfDestructAddress = this.getMemory(addressOffset, ADDRESS_SIZE_BYTES) this.kernel.environment.gasRefund += 24000 diff --git a/environment.js b/environment.js index 778874c..00f70e4 100644 --- a/environment.js +++ b/environment.js @@ -11,6 +11,7 @@ module.exports = class Environment { const defaults = { block: new Block(), blockchain: fakeBlockChain, + coinbase: new Address('0x0000000000000000000000000000000000000000'), // gas tank gasPrice: 0, gasLeft: 1000000, diff --git a/package.json b/package.json index a5bc9b4..bec21b8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "lint": "standard", "test": "node --harmony --expose-wasm ./tests/interfaceRunner.js", - "build": "node ./tests/buildTests.js && ./tools/wabt/out/wast2wasm ./wasm/interface.wast -o ./wasm/interface.wasm" + "build": "node ./tests/buildTests.js && ./tools/wabt/out/clang/Debug/wat2wasm ./wasm/interface.wast -o ./wasm/interface.wasm" }, "repository": { "type": "git", @@ -40,7 +40,8 @@ "bn.js": "^4.11.6", "ethereumjs-block": "^1.2.2", "ethereumjs-tx": "^1.1.2", - "merkle-trie": "0.1.2", + "loglevel": "1.5.1", + "merkle-trie": "0.0.0", "ethereumjs-util": "^5.0.0" } } diff --git a/tests/buildTests.js b/tests/buildTests.js index d203c5b..a289e2f 100644 --- a/tests/buildTests.js +++ b/tests/buildTests.js @@ -10,5 +10,5 @@ let tests = fs.readdirSync(dir).filter((file) => file.endsWith('.wast')) for (let testName of tests) { testName = testName.split('.')[0] // Compile Command - cp.execSync(`${__dirname}/../tools/wabt/out/wast2wasm ${dir}/${testName}.wast -o ${dir}/${testName}.wasm`) + cp.execSync(`${__dirname}/../tools/wabt/out/clang/Debug/wat2wasm ${dir}/${testName}.wast -o ${dir}/${testName}.wasm`) } diff --git a/tests/interface/address.wasm b/tests/interface/address.wasm index f264f03..9291f8c 100644 Binary files a/tests/interface/address.wasm and b/tests/interface/address.wasm differ diff --git a/tests/interface/balance.wasm b/tests/interface/balance.wasm index 9bfc3bd..1f94431 100644 Binary files a/tests/interface/balance.wasm and b/tests/interface/balance.wasm differ diff --git a/tests/interface/basic_gas_ops.wasm b/tests/interface/basic_gas_ops.wasm index ee1ae93..ffc8f14 100644 Binary files a/tests/interface/basic_gas_ops.wasm and b/tests/interface/basic_gas_ops.wasm differ diff --git a/tests/interface/call.wasm b/tests/interface/call.wasm index 45fa4b0..dad6a16 100644 Binary files a/tests/interface/call.wasm and b/tests/interface/call.wasm differ diff --git a/tests/interface/callDataCopy.wasm b/tests/interface/callDataCopy.wasm index 51faf4f..ea069d5 100644 Binary files a/tests/interface/callDataCopy.wasm and b/tests/interface/callDataCopy.wasm differ diff --git a/tests/interface/callDataSize.wasm b/tests/interface/callDataSize.wasm index b88a6d9..ff056e6 100644 Binary files a/tests/interface/callDataSize.wasm and b/tests/interface/callDataSize.wasm differ diff --git a/tests/interface/callValue.wasm b/tests/interface/callValue.wasm index 5f2017d..14fe962 100644 Binary files a/tests/interface/callValue.wasm and b/tests/interface/callValue.wasm differ diff --git a/tests/interface/caller.wasm b/tests/interface/caller.wasm index 8d23f4a..03277ce 100644 Binary files a/tests/interface/caller.wasm and b/tests/interface/caller.wasm differ diff --git a/tests/interface/coinbase.wasm b/tests/interface/coinbase.wasm index 7a53a5a..e74de13 100644 Binary files a/tests/interface/coinbase.wasm and b/tests/interface/coinbase.wasm differ diff --git a/tests/interface/origin.wasm b/tests/interface/origin.wasm index f4aa847..b02650d 100644 Binary files a/tests/interface/origin.wasm and b/tests/interface/origin.wasm differ diff --git a/tests/interface/sstore.wasm b/tests/interface/sstore.wasm index 0512435..fc41d8d 100644 Binary files a/tests/interface/sstore.wasm and b/tests/interface/sstore.wasm differ diff --git a/tools/wabt b/tools/wabt index 2177e75..dac347e 160000 --- a/tools/wabt +++ b/tools/wabt @@ -1 +1 @@ -Subproject commit 2177e7517b857d557cbf9b8477c31f96a8ed66bb +Subproject commit dac347ecb3a33eb67f62cd9061c58a1b4a2b549b diff --git a/wasm/interface.wasm b/wasm/interface.wasm index efaf02b..c09cab5 100644 Binary files a/wasm/interface.wasm and b/wasm/interface.wasm differ