From 05a62a18fb87877f930ab365cc0bd73b135927b1 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 11:51:57 -0500 Subject: [PATCH 01/14] move txHelper reference to Remix-lib --- src/app/contract/contractParser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/contract/contractParser.js b/src/app/contract/contractParser.js index 27796062d8..3d3afa6733 100644 --- a/src/app/contract/contractParser.js +++ b/src/app/contract/contractParser.js @@ -1,6 +1,7 @@ 'use strict' -var txHelper = require('../execution/txHelper') +var remixLib = require('remix-lib') +var txHelper = remixLib.execution.txHelper module.exports = (contractName, contract, compiledSource) => { return getDetails(contractName, contract, compiledSource) From ad2d416affc54e1f31a2d9687b7829272f1bbf0c Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 12:11:05 -0500 Subject: [PATCH 02/14] move debugger reference to Remix-lib --- src/app/debugger/debugger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/debugger/debugger.js b/src/app/debugger/debugger.js index 1f78525ad6..b3dedc5e54 100644 --- a/src/app/debugger/debugger.js +++ b/src/app/debugger/debugger.js @@ -3,7 +3,7 @@ var remixDebugger = require('remix-debugger') var remixLib = require('remix-lib') var remixCore = require('remix-core') -var executionContext = require('../../execution-context') +var executionContext = remixLib.execution.executionContext /** * Manage remix and source highlighting From 369ab61b6d42c70090b66f5f53700aa654c7bf80 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 12:46:54 -0500 Subject: [PATCH 03/14] move txLogger reference to Remix-lib --- src/app/execution/txLogger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/execution/txLogger.js b/src/app/execution/txLogger.js index 6e782a7acc..89320c47ff 100644 --- a/src/app/execution/txLogger.js +++ b/src/app/execution/txLogger.js @@ -10,7 +10,7 @@ var styles = styleGuide.chooser() var EventManager = remixLib.EventManager var helper = require('../../lib/helper') -var executionContext = require('../../execution-context') +var executionContext = remixLib.execution.executionContext var modalDialog = require('../ui/modal-dialog-custom') var typeConversion = require('../../lib/typeConversion') From 2507e36576a5fc30cee5273e1830788a3de40cf3 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 13:09:48 -0500 Subject: [PATCH 04/14] add single execution context --- src/app/debugger/debugger.js | 2 +- src/app/execution/execution-context.js | 4 ++++ src/app/execution/txLogger.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 src/app/execution/execution-context.js diff --git a/src/app/debugger/debugger.js b/src/app/debugger/debugger.js index b3dedc5e54..62029ddc45 100644 --- a/src/app/debugger/debugger.js +++ b/src/app/debugger/debugger.js @@ -3,7 +3,7 @@ var remixDebugger = require('remix-debugger') var remixLib = require('remix-lib') var remixCore = require('remix-core') -var executionContext = remixLib.execution.executionContext +var executionContext = require('../execution/execution-context') /** * Manage remix and source highlighting diff --git a/src/app/execution/execution-context.js b/src/app/execution/execution-context.js new file mode 100644 index 0000000000..eafad31e9d --- /dev/null +++ b/src/app/execution/execution-context.js @@ -0,0 +1,4 @@ +var remixLib = require('remix-lib') +var executionContext = remixLib.execution.executionContext + +module.exports = executionContext diff --git a/src/app/execution/txLogger.js b/src/app/execution/txLogger.js index 89320c47ff..40c39152e2 100644 --- a/src/app/execution/txLogger.js +++ b/src/app/execution/txLogger.js @@ -10,7 +10,7 @@ var styles = styleGuide.chooser() var EventManager = remixLib.EventManager var helper = require('../../lib/helper') -var executionContext = remixLib.execution.executionContext +var executionContext = require('./execution-context') var modalDialog = require('../ui/modal-dialog-custom') var typeConversion = require('../../lib/typeConversion') From ce9424af23f1a7b78d8464533359940ed40a27ef Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 13:23:34 -0500 Subject: [PATCH 05/14] add single execution context --- src/app/debugger/debugger.js | 2 +- src/app/execution/execution-context.js | 4 - src/app/execution/txLogger.js | 2 +- src/execution-context.js | 227 +------------------------ 4 files changed, 4 insertions(+), 231 deletions(-) delete mode 100644 src/app/execution/execution-context.js diff --git a/src/app/debugger/debugger.js b/src/app/debugger/debugger.js index 62029ddc45..1f78525ad6 100644 --- a/src/app/debugger/debugger.js +++ b/src/app/debugger/debugger.js @@ -3,7 +3,7 @@ var remixDebugger = require('remix-debugger') var remixLib = require('remix-lib') var remixCore = require('remix-core') -var executionContext = require('../execution/execution-context') +var executionContext = require('../../execution-context') /** * Manage remix and source highlighting diff --git a/src/app/execution/execution-context.js b/src/app/execution/execution-context.js deleted file mode 100644 index eafad31e9d..0000000000 --- a/src/app/execution/execution-context.js +++ /dev/null @@ -1,4 +0,0 @@ -var remixLib = require('remix-lib') -var executionContext = remixLib.execution.executionContext - -module.exports = executionContext diff --git a/src/app/execution/txLogger.js b/src/app/execution/txLogger.js index 40c39152e2..6e782a7acc 100644 --- a/src/app/execution/txLogger.js +++ b/src/app/execution/txLogger.js @@ -10,7 +10,7 @@ var styles = styleGuide.chooser() var EventManager = remixLib.EventManager var helper = require('../../lib/helper') -var executionContext = require('./execution-context') +var executionContext = require('../../execution-context') var modalDialog = require('../ui/modal-dialog-custom') var typeConversion = require('../../lib/typeConversion') diff --git a/src/execution-context.js b/src/execution-context.js index c4e77bdba6..eafad31e9d 100644 --- a/src/execution-context.js +++ b/src/execution-context.js @@ -1,227 +1,4 @@ -'use strict' - -var Web3 = require('web3') var remixLib = require('remix-lib') -var EventManager = remixLib.EventManager -var EthJSVM = require('ethereumjs-vm') -var ethUtil = require('ethereumjs-util') -var StateManager = require('ethereumjs-vm/lib/stateManager') -var Web3VMProvider = remixLib.vm.Web3VMProvider -var rlp = ethUtil.rlp - -var injectedProvider - -var web3 -if (typeof window.web3 !== 'undefined') { - injectedProvider = window.web3.currentProvider - web3 = new Web3(injectedProvider) -} else { - web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) -} - -var blankWeb3 = new Web3() - -/* - extend vm state manager and instanciate VM -*/ - -class StateManagerCommonStorageDump extends StateManager { - constructor (arg) { - super(arg) - this.keyHashes = {} - } - - putContractStorage (address, key, value, cb) { - this.keyHashes[ethUtil.sha3(key).toString('hex')] = ethUtil.bufferToHex(key) - super.putContractStorage(address, key, value, cb) - } - - dumpStorage (address, cb) { - var self = this - this._getStorageTrie(address, function (err, trie) { - if (err) { - return cb(err) - } - var storage = {} - var stream = trie.createReadStream() - stream.on('data', function (val) { - var value = rlp.decode(val.value) - storage['0x' + val.key.toString('hex')] = { - key: self.keyHashes[val.key.toString('hex')], - value: '0x' + value.toString('hex') - } - }) - stream.on('end', function () { - cb(storage) - }) - }) - } -} - -var stateManager = new StateManagerCommonStorageDump({}) -var vm = new EthJSVM({ - enableHomestead: true, - activatePrecompiles: true -}) - -// FIXME: move state manager in EthJSVM ctr -vm.stateManager = stateManager -vm.blockchain = stateManager.blockchain -vm.trie = stateManager.trie -vm.stateManager.checkpoint() - -var web3VM = new Web3VMProvider() -web3VM.setVM(vm) - -var mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' - -/* - trigger contextChanged, web3EndpointChanged -*/ -function ExecutionContext () { - var self = this - this.event = new EventManager() - - var executionContext = null - - this.init = function (config) { - if (config.get('settings/always-use-vm')) { - executionContext = 'vm' - } else { - executionContext = injectedProvider ? 'injected' : 'vm' - } - } - - this.getProvider = function () { - return executionContext - } - - this.isVM = function () { - return executionContext === 'vm' - } - - this.web3 = function () { - return this.isVM() ? web3VM : web3 - } - - this.detectNetwork = function (callback) { - if (this.isVM()) { - callback(null, { id: '-', name: 'VM' }) - } else { - this.web3().version.getNetwork((err, id) => { - var name = null - if (err) name = 'Unknown' - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md - else if (id === '1') name = 'Main' - else if (id === '2') name = 'Morden (deprecated)' - else if (id === '3') name = 'Ropsten' - else if (id === '4') name = 'Rinkeby' - else if (id === '42') name = 'Kovan' - else name = 'Custom' - - if (id === '1') { - this.web3().eth.getBlock(0, (error, block) => { - if (error) console.log('cant query first block') - if (block && block.hash !== mainNetGenesisHash) name = 'Custom' - callback(err, { id, name }) - }) - } else { - callback(err, { id, name }) - } - }) - } - } - - this.internalWeb3 = function () { - return web3 - } - - this.blankWeb3 = function () { - return blankWeb3 - } - - this.vm = function () { - return vm - } - - this.setContext = function (context, endPointUrl, confirmCb, infoCb) { - executionContext = context - this.executionContextChange(context, endPointUrl, confirmCb, infoCb) - } - - this.executionContextChange = function (context, endPointUrl, confirmCb, infoCb, cb) { - if (!cb) cb = () => {} - - if (context === 'vm') { - executionContext = context - vm.stateManager.revert(function () { - vm.stateManager.checkpoint() - }) - self.event.trigger('contextChanged', ['vm']) - return cb() - } - - if (context === 'injected') { - if (injectedProvider === undefined) { - var alertMsg = 'No injected Web3 provider found. ' - alertMsg += 'Make sure your provider (e.g. MetaMask) is active and running ' - alertMsg += '(when recently activated you may have to reload the page).' - infoCb(alertMsg) - return cb() - } else { - executionContext = context - web3.setProvider(injectedProvider) - self.event.trigger('contextChanged', ['injected']) - return cb() - } - } - - if (context === 'web3') { - confirmCb(cb) - } - } - - this.currentblockGasLimit = function () { - return this.blockGasLimit - } - - this.blockGasLimitDefault = 4300000 - this.blockGasLimit = this.blockGasLimitDefault - setInterval(() => { - if (this.getProvider() !== 'vm') { - web3.eth.getBlock('latest', (err, block) => { - if (!err) { - // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 - this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault - } else { - this.blockGasLimit = this.blockGasLimitDefault - } - }) - } - }, 15000) - - // TODO: not used here anymore and needs to be moved - function setProviderFromEndpoint (endpoint, context, cb) { - var oldProvider = web3.currentProvider - - if (endpoint === 'ipc') { - web3.setProvider(new web3.providers.IpcProvider()) - } else { - web3.setProvider(new web3.providers.HttpProvider(endpoint)) - } - if (web3.isConnected()) { - executionContext = context - self.event.trigger('contextChanged', ['web3']) - self.event.trigger('web3EndpointChanged') - cb() - } else { - web3.setProvider(oldProvider) - var alertMsg = 'Not possible to connect to the Web3 provider. ' - alertMsg += 'Make sure the provider is running and a connection is open (via IPC or RPC).' - cb(alertMsg) - } - } - this.setProviderFromEndpoint = setProviderFromEndpoint -} +var executionContext = remixLib.execution.executionContext -module.exports = new ExecutionContext() +module.exports = executionContext From 777b4bcb06ad031c4aa20ac54e28b94482c176dd Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 14:08:01 -0500 Subject: [PATCH 06/14] move run-tab references to remixLib --- src/app/tabs/run-tab.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/app/tabs/run-tab.js b/src/app/tabs/run-tab.js index 5b0cef0291..2f90914100 100644 --- a/src/app/tabs/run-tab.js +++ b/src/app/tabs/run-tab.js @@ -2,14 +2,15 @@ var $ = require('jquery') var yo = require('yo-yo') var helper = require('../../lib/helper.js') -var txExecution = require('../execution/txExecution') -var txFormat = require('../execution/txFormat') -var txHelper = require('../execution/txHelper') -var modalDialogCustom = require('../ui/modal-dialog-custom') +var remixLib = require('remix-lib') +var txExecution = remixLib.execution.txExecution +var txFormat = remixLib.execution.txFormat +var txHelper = remixLib.execution.txHelper var executionContext = require('../../execution-context') +var modalDialogCustom = require('../ui/modal-dialog-custom') var copyToClipboard = require('../ui/copy-to-clipboard') var Recorder = require('../../recorder') -var EventManager = require('remix-lib').EventManager +var EventManager = remixLib.EventManager var addTooltip = require('../ui/tooltip') var csjs = require('csjs-inject') From 538cf9567979771671bd094c9d3fa8bbf664ef0a Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 14:09:32 -0500 Subject: [PATCH 07/14] move recorder references to remixLib --- src/recorder.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recorder.js b/src/recorder.js index 1f863568cb..6a6c8a5d40 100644 --- a/src/recorder.js +++ b/src/recorder.js @@ -2,8 +2,8 @@ var remixLib = require('remix-lib') var EventManager = remixLib.EventManager var ethutil = require('ethereumjs-util') var executionContext = require('./execution-context') -var format = require('./app/execution/txFormat') -var txHelper = require('./app/execution/txHelper') +var format = remixLib.execution.txFormat +var txHelper = remixLib.execution.txHelper var async = require('async') var modal = require('./app/ui/modal-dialog-custom') From d5f062485459029e4f9ef5e06b7c9329eb0daabe Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 14:35:22 -0500 Subject: [PATCH 08/14] move udapp references to remixLib --- src/universal-dapp.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/universal-dapp.js b/src/universal-dapp.js index 21c8f32de0..1b8bda322e 100644 --- a/src/universal-dapp.js +++ b/src/universal-dapp.js @@ -8,9 +8,9 @@ var remixLib = require('remix-lib') var EventManager = remixLib.EventManager var crypto = require('crypto') var TxRunner = require('./app/execution/txRunner') -var txFormat = require('./app/execution/txFormat') -var txHelper = require('./app/execution/txHelper') -var txExecution = require('./app/execution/txExecution') +var txExecution = remixLib.execution.txExecution +var txFormat = remixLib.execution.txFormat +var txHelper = remixLib.execution.txHelper var executionContext = require('./execution-context') var modalCustom = require('./app/ui/modal-dialog-custom') From 16f0b1df3c6898d1136d98e69bd50a18ca34c278 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 15:40:24 -0500 Subject: [PATCH 09/14] use original txFormat file --- src/universal-dapp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/universal-dapp.js b/src/universal-dapp.js index 1b8bda322e..24bfd10921 100644 --- a/src/universal-dapp.js +++ b/src/universal-dapp.js @@ -9,7 +9,7 @@ var EventManager = remixLib.EventManager var crypto = require('crypto') var TxRunner = require('./app/execution/txRunner') var txExecution = remixLib.execution.txExecution -var txFormat = remixLib.execution.txFormat +var txFormat = require('./app/execution/txFormat') var txHelper = remixLib.execution.txHelper var executionContext = require('./execution-context') var modalCustom = require('./app/ui/modal-dialog-custom') From 515a075af3459a62b041d11228df8b1ce03434d4 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 16:00:54 -0500 Subject: [PATCH 10/14] remove txExecution code (moved to remix-lib) --- src/app/execution/txExecution.js | 75 -------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 src/app/execution/txExecution.js diff --git a/src/app/execution/txExecution.js b/src/app/execution/txExecution.js deleted file mode 100644 index 424a6f16a3..0000000000 --- a/src/app/execution/txExecution.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict' - -module.exports = { - /** - * deploy the given contract - * - * @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ). - * @param {Object} udap - udapp. - * @param {Function} callback - callback. - */ - createContract: function (data, udapp, callback) { - udapp.runTx({data: data, useCall: false}, (error, txResult) => { - // see universaldapp.js line 660 => 700 to check possible values of txResult (error case) - callback(error, txResult) - }) - }, - - /** - * call the current given contract - * - * @param {String} to - address of the contract to call. - * @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ). - * @param {Object} funAbi - abi definition of the function to call. - * @param {Object} udap - udapp. - * @param {Function} callback - callback. - */ - callFunction: function (to, data, funAbi, udapp, callback) { - udapp.runTx({to: to, data: data, useCall: funAbi.constant}, (error, txResult) => { - // see universaldapp.js line 660 => 700 to check possible values of txResult (error case) - callback(error, txResult) - }) - }, - - /** - * check if the vm has errored - * - * @param {Object} txResult - the value returned by the vm - * @return {Object} - { error: true/false, message: DOMNode } - */ - checkVMError: function (txResult) { - var errorCode = { - OUT_OF_GAS: 'out of gas', - STACK_UNDERFLOW: 'stack underflow', - STACK_OVERFLOW: 'stack overflow', - INVALID_JUMP: 'invalid JUMP', - INVALID_OPCODE: 'invalid opcode', - REVERT: 'revert', - STATIC_STATE_CHANGE: 'static state change' - } - var ret = { - error: false, - message: '' - } - if (!txResult.result.vm.exceptionError) { - return ret - } - var error = `VM error: ${txResult.result.vm.exceptionError}.\n` - var msg - if (txResult.result.vm.exceptionError === errorCode.INVALID_OPCODE) { - msg = `\t\n\tThe execution might have thrown.\n` - ret.error = true - } else if (txResult.result.vm.exceptionError === errorCode.OUT_OF_GAS) { - msg = `\tThe transaction ran out of gas. Please increase the Gas Limit.\n` - ret.error = true - } else if (txResult.result.vm.exceptionError === errorCode.REVERT) { - msg = `\tThe transaction has been reverted to the initial state.\nNote: The constructor should be payable if you send value.` - ret.error = true - } else if (txResult.result.vm.exceptionError === errorCode.STATIC_STATE_CHANGE) { - msg = `\tState changes is not allowed in Static Call context\n` - ret.error = true - } - ret.message = `${error}${txResult.result.vm.exceptionError}${msg}\tDebug the transaction to get more information.` - return ret - } -} From eb63a5e8513148582eafed84f9beb33075f85705 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 15 Feb 2018 16:05:00 -0500 Subject: [PATCH 11/14] move eventsDecoder to remixLib --- src/app.js | 2 +- src/app/execution/eventsDecoder.js | 123 ----------------------------- 2 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 src/app/execution/eventsDecoder.js diff --git a/src/app.js b/src/app.js index 600d56a447..5eccf39897 100644 --- a/src/app.js +++ b/src/app.js @@ -33,7 +33,7 @@ var examples = require('./app/editor/example-contracts') var modalDialogCustom = require('./app/ui/modal-dialog-custom') var Txlistener = require('./app/execution/txListener') var TxLogger = require('./app/execution/txLogger') -var EventsDecoder = require('./app/execution/eventsDecoder') +var EventsDecoder = remixLib.execution.EventsDecoder var handleImports = require('./app/compiler/compiler-imports') var FileManager = require('./app/files/fileManager') var ContextualListener = require('./app/editor/contextualListener') diff --git a/src/app/execution/eventsDecoder.js b/src/app/execution/eventsDecoder.js deleted file mode 100644 index 2127f469b4..0000000000 --- a/src/app/execution/eventsDecoder.js +++ /dev/null @@ -1,123 +0,0 @@ -'use strict' -var ethJSABI = require('ethereumjs-abi') -var txHelper = require('../execution/txHelper') - -/** - * Register to txListener and extract events - * - */ -class EventsDecoder { - constructor (opt = {}) { - this._api = opt.api - } - -/** - * use Transaction Receipt to decode logs. assume that the transaction as already been resolved by txListener. - * logs are decoded only if the contract if known by remix. - * - * @param {Object} tx - transaction object - * @param {Function} cb - callback - */ - parseLogs (tx, contractName, compiledContracts, cb) { - if (tx.isCall) return cb(null, { decoded: [], raw: [] }) - this._api.resolveReceipt(tx, (error, receipt) => { - if (error) return cb(error) - this._decodeLogs(tx, receipt, contractName, compiledContracts, cb) - }) - } - - _decodeLogs (tx, receipt, contract, contracts, cb) { - if (!contract || !receipt) { - return cb('cannot decode logs - contract or receipt not resolved ') - } - if (!receipt.logs) { - return cb(null, { decoded: [], raw: [] }) - } - this._decodeEvents(tx, receipt.logs, contract, contracts, cb) - } - - _eventABI (contract) { - var eventABI = {} - contract.abi.forEach(function (funABI, i) { - if (funABI.type !== 'event') { - return - } - var hash = ethJSABI.eventID(funABI.name, funABI.inputs.map(function (item) { return item.type })) - eventABI[hash.toString('hex')] = { event: funABI.name, inputs: funABI.inputs } - }) - return eventABI - } - - _eventsABI (compiledContracts) { - var eventsABI = {} - txHelper.visitContracts(compiledContracts, (contract) => { - eventsABI[contract.name] = this._eventABI(contract.object) - }) - return eventsABI - } - - _event (hash, eventsABI) { - for (var k in eventsABI) { - if (eventsABI[k][hash]) { - return eventsABI[k][hash] - } - } - return null - } - - _decodeEvents (tx, logs, contractName, compiledContracts, cb) { - var eventsABI = this._eventsABI(compiledContracts) - var events = [] - for (var i in logs) { - // [address, topics, mem] - var log = logs[i] - var topicId = log.topics[0] - var abi = this._event(topicId.replace('0x', ''), eventsABI) - if (abi) { - var event - try { - var decoded = new Array(abi.inputs.length) - event = abi.event - var indexed = 1 - var nonindexed = [] - // decode indexed param - abi.inputs.map(function (item, index) { - if (item.indexed) { - var encodedData = log.topics[indexed].replace('0x', '') - try { - decoded[index] = ethJSABI.rawDecode([item.type], new Buffer(encodedData, 'hex'))[0] - if (typeof decoded[index] !== 'string') { - decoded[index] = ethJSABI.stringify([item.type], decoded[index]) - } - } catch (e) { - decoded[index] = encodedData - } - indexed++ - } else { - nonindexed.push(item.type) - } - }) - // decode non indexed param - var nonindexededResult = ethJSABI.rawDecode(nonindexed, new Buffer(log.data.replace('0x', ''), 'hex')) - nonindexed = ethJSABI.stringify(nonindexed, nonindexededResult) - // ordering - var j = 0 - abi.inputs.map(function (item, index) { - if (!item.indexed) { - decoded[index] = nonindexed[j] - j++ - } - }) - } catch (e) { - decoded = log.data - } - events.push({ topic: topicId, event: event, args: decoded }) - } else { - events.push({ data: log.data, topics: log.topics }) - } - } - cb(null, { decoded: events, raw: logs }) - } -} - -module.exports = EventsDecoder From 60d3ee80c0f1e33224a2fd994ed6393a389c43fc Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 16 Feb 2018 09:48:58 -0500 Subject: [PATCH 12/14] move txlistener code to remix-lib --- src/app.js | 2 +- src/app/execution/txListener.js | 365 -------------------------------- 2 files changed, 1 insertion(+), 366 deletions(-) delete mode 100644 src/app/execution/txListener.js diff --git a/src/app.js b/src/app.js index 5eccf39897..f2f8c6dd66 100644 --- a/src/app.js +++ b/src/app.js @@ -31,8 +31,8 @@ var EditorPanel = require('./app/panels/editor-panel') var RighthandPanel = require('./app/panels/righthand-panel') var examples = require('./app/editor/example-contracts') var modalDialogCustom = require('./app/ui/modal-dialog-custom') -var Txlistener = require('./app/execution/txListener') var TxLogger = require('./app/execution/txLogger') +var Txlistener = remixLib.execution.txListener var EventsDecoder = remixLib.execution.EventsDecoder var handleImports = require('./app/compiler/compiler-imports') var FileManager = require('./app/files/fileManager') diff --git a/src/app/execution/txListener.js b/src/app/execution/txListener.js deleted file mode 100644 index e7139cebed..0000000000 --- a/src/app/execution/txListener.js +++ /dev/null @@ -1,365 +0,0 @@ -'use strict' -var async = require('async') -var ethJSABI = require('ethereumjs-abi') -var ethJSUtil = require('ethereumjs-util') -var remixLib = require('remix-lib') -var EventManager = remixLib.EventManager -var codeUtil = remixLib.util -var executionContext = require('../../execution-context') -var txFormat = require('./txFormat') -var txHelper = require('./txHelper') - -/** - * poll web3 each 2s if web3 - * listen on transaction executed event if VM - * attention: blocks returned by the event `newBlock` have slightly different json properties whether web3 or the VM is used - * trigger 'newBlock' - * - */ -class TxListener { - constructor (opt) { - this.event = new EventManager() - this._api = opt.api - this._resolvedTransactions = {} - this._resolvedContracts = {} - this._isListening = false - this._listenOnNetwork = false - this._loopId = null - this.init() - executionContext.event.register('contextChanged', (context) => { - if (this._isListening) { - this.stopListening() - this.startListening() - } - }) - - opt.event.udapp.register('callExecuted', (error, from, to, data, lookupOnly, txResult) => { - if (error) return - // we go for that case if - // in VM mode - // in web3 mode && listen remix txs only - if (!this._isListening) return // we don't listen - if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network - - var call = { - from: from, - to: to, - input: data, - hash: txResult.transactionHash ? txResult.transactionHash : 'call' + (from || '') + to + data, - isCall: true, - returnValue: executionContext.isVM() ? txResult.result.vm.return : ethJSUtil.toBuffer(txResult.result), - envMode: executionContext.getProvider() - } - - addExecutionCosts(txResult, call) - this._resolveTx(call, (error, resolvedData) => { - if (!error) { - this.event.trigger('newCall', [call]) - } - }) - }) - - opt.event.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => { - if (error) return - if (lookupOnly) return - // we go for that case if - // in VM mode - // in web3 mode && listen remix txs only - if (!this._isListening) return // we don't listen - if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network - executionContext.web3().eth.getTransaction(txResult.transactionHash, (error, tx) => { - if (error) return console.log(error) - - addExecutionCosts(txResult, tx) - tx.envMode = executionContext.getProvider() - tx.status = txResult.result.status // 0x0 or 0x1 - this._resolve([tx], () => { - }) - }) - }) - - function addExecutionCosts (txResult, tx) { - if (txResult && txResult.result) { - if (txResult.result.vm) { - tx.returnValue = txResult.result.vm.return - if (txResult.result.vm.gasUsed) tx.executionCost = txResult.result.vm.gasUsed.toString(10) - } - if (txResult.result.gasUsed) tx.transactionCost = txResult.result.gasUsed.toString(10) - } - } - } - - /** - * define if txlistener should listen on the network or if only tx created from remix are managed - * - * @param {Bool} type - true if listen on the network - */ - setListenOnNetwork (listenOnNetwork) { - this._listenOnNetwork = listenOnNetwork - if (this._loopId) { - clearInterval(this._loopId) - } - if (this._listenOnNetwork) { - this._startListenOnNetwork() - } - } - - /** - * reset recorded transactions - */ - init () { - this.blocks = [] - this.lastBlock = null - } - - /** - * start listening for incoming transactions - * - * @param {String} type - type/name of the provider to add - * @param {Object} obj - provider - */ - startListening () { - this.init() - this._isListening = true - if (this._listenOnNetwork && executionContext.getProvider() !== 'vm') { - this._startListenOnNetwork() - } - } - - /** - * stop listening for incoming transactions. do not reset the recorded pool. - * - * @param {String} type - type/name of the provider to add - * @param {Object} obj - provider - */ - stopListening () { - if (this._loopId) { - clearInterval(this._loopId) - } - this._loopId = null - this._isListening = false - } - - _startListenOnNetwork () { - this._loopId = setInterval(() => { - var currentLoopId = this._loopId - executionContext.web3().eth.getBlockNumber((error, blockNumber) => { - if (this._loopId === null) return - if (error) return console.log(error) - if (currentLoopId === this._loopId && (!this.lastBlock || blockNumber > this.lastBlock)) { - if (!this.lastBlock) this.lastBlock = blockNumber - 1 - var current = this.lastBlock + 1 - this.lastBlock = blockNumber - while (blockNumber >= current) { - try { - this._manageBlock(current) - } catch (e) { - console.log(e) - } - current++ - } - } - }) - }, 2000) - } - - _manageBlock (blockNumber) { - executionContext.web3().eth.getBlock(blockNumber, true, (error, result) => { - if (!error) { - this._newBlock(Object.assign({type: 'web3'}, result)) - } - }) - } - - /** - * try to resolve the contract name from the given @arg address - * - * @param {String} address - contract address to resolve - * @return {String} - contract name - */ - resolvedContract (address) { - return this._resolvedContracts[address] - } - - /** - * try to resolve the transaction from the given @arg txHash - * - * @param {String} txHash - contract address to resolve - * @return {String} - contract name - */ - resolvedTransaction (txHash) { - return this._resolvedTransactions[txHash] - } - - _newBlock (block) { - this.blocks.push(block) - this._resolve(block.transactions, () => { - this.event.trigger('newBlock', [block]) - }) - } - - _resolve (transactions, callback) { - async.each(transactions, (tx, cb) => { - this._resolveTx(tx, (error, resolvedData) => { - if (error) cb(error) - if (resolvedData) { - this.event.trigger('txResolved', [tx, resolvedData]) - } - this.event.trigger('newTransaction', [tx]) - cb() - }) - }, () => { - callback() - }) - } - - _resolveTx (tx, cb) { - var contracts = this._api.contracts() - if (!contracts) return cb() - var contractName - if (!tx.to || tx.to === '0x0') { // testrpc returns 0x0 in that case - // contract creation / resolve using the creation bytes code - // if web3: we have to call getTransactionReceipt to get the created address - // if VM: created address already included - var code = tx.input - contractName = this._tryResolveContract(code, contracts, true) - if (contractName) { - this._api.resolveReceipt(tx, (error, receipt) => { - if (error) return cb(error) - var address = receipt.contractAddress - this._resolvedContracts[address] = contractName - var fun = this._resolveFunction(contractName, contracts, tx, true) - if (this._resolvedTransactions[tx.hash]) { - this._resolvedTransactions[tx.hash].contractAddress = address - } - return cb(null, {to: null, contractName: contractName, function: fun, creationAddress: address}) - }) - return - } - return cb() - } else { - // first check known contract, resolve against the `runtimeBytecode` if not known - contractName = this._resolvedContracts[tx.to] - if (!contractName) { - executionContext.web3().eth.getCode(tx.to, (error, code) => { - if (error) return cb(error) - if (code) { - var contractName = this._tryResolveContract(code, contracts, false) - if (contractName) { - this._resolvedContracts[tx.to] = contractName - var fun = this._resolveFunction(contractName, contracts, tx, false) - return cb(null, {to: tx.to, contractName: contractName, function: fun}) - } - } - return cb() - }) - return - } - if (contractName) { - var fun = this._resolveFunction(contractName, contracts, tx, false) - return cb(null, {to: tx.to, contractName: contractName, function: fun}) - } - return cb() - } - } - - _resolveFunction (contractName, compiledContracts, tx, isCtor) { - var contract = txHelper.getContract(contractName, compiledContracts) - if (!contract) { - console.log('txListener: cannot resolve ' + contractName) - return - } - var abi = contract.object.abi - var inputData = tx.input.replace('0x', '') - if (!isCtor) { - var methodIdentifiers = contract.object.evm.methodIdentifiers - for (var fn in methodIdentifiers) { - if (methodIdentifiers[fn] === inputData.substring(0, 8)) { - var fnabi = getFunction(abi, fn) - this._resolvedTransactions[tx.hash] = { - contractName: contractName, - to: tx.to, - fn: fn, - params: this._decodeInputParams(inputData.substring(8), fnabi) - } - if (tx.returnValue) { - this._resolvedTransactions[tx.hash].decodedReturnValue = txFormat.decodeResponse(tx.returnValue, fnabi) - } - return this._resolvedTransactions[tx.hash] - } - } - // fallback function - this._resolvedTransactions[tx.hash] = { - contractName: contractName, - to: tx.to, - fn: '(fallback)', - params: null - } - } else { - var bytecode = contract.object.evm.bytecode.object - var params = null - if (bytecode && bytecode.length) { - params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi)) - } - this._resolvedTransactions[tx.hash] = { - contractName: contractName, - to: null, - fn: '(constructor)', - params: params - } - } - return this._resolvedTransactions[tx.hash] - } - - _tryResolveContract (codeToResolve, compiledContracts, isCreation) { - var found = null - txHelper.visitContracts(compiledContracts, (contract) => { - var bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object - if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) { - found = contract.name - return true - } - }) - return found - } - - _decodeInputParams (data, abi) { - data = ethJSUtil.toBuffer('0x' + data) - var inputTypes = [] - for (var i = 0; i < abi.inputs.length; i++) { - inputTypes.push(abi.inputs[i].type) - } - var decoded = ethJSABI.rawDecode(inputTypes, data) - decoded = ethJSABI.stringify(inputTypes, decoded) - var ret = {} - for (var k in abi.inputs) { - ret[abi.inputs[k].type + ' ' + abi.inputs[k].name] = decoded[k] - } - return ret - } -} - -// those function will be duplicate after the merged of the compile and run tabs split -function getConstructorInterface (abi) { - var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] } - for (var i = 0; i < abi.length; i++) { - if (abi[i].type === 'constructor') { - funABI.inputs = abi[i].inputs || [] - break - } - } - - return funABI -} - -function getFunction (abi, fnName) { - fnName = fnName.split('(')[0] - for (var i = 0; i < abi.length; i++) { - if (abi[i].name === fnName) { - return abi[i] - } - } - return null -} - -module.exports = TxListener From ff806f04fb7f584dbf31365d9148cf9c50051278 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 16 Feb 2018 10:08:31 -0500 Subject: [PATCH 13/14] remove unneded package --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 42060a51a2..aba16682a4 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "ethereumjs-block": "^1.6.0", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.2", - "ethereumjs-vm": "2.3.1", "execr": "^1.0.1", "exorcist": "^0.4.0", "fast-async": "^6.1.2", From bca533232569c5256f282ee1df7607b3ed14b7d6 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 16 Feb 2018 10:22:52 -0500 Subject: [PATCH 14/14] move txHelper reference to Remix-lib --- src/app/execution/txFormat.js | 3 +- src/app/execution/txHelper.js | 121 ---------------------------------- 2 files changed, 2 insertions(+), 122 deletions(-) delete mode 100644 src/app/execution/txHelper.js diff --git a/src/app/execution/txFormat.js b/src/app/execution/txFormat.js index f529167963..cd7946eeb9 100644 --- a/src/app/execution/txFormat.js +++ b/src/app/execution/txFormat.js @@ -2,7 +2,8 @@ var ethJSABI = require('ethereumjs-abi') var ethJSUtil = require('ethereumjs-util') var BN = ethJSUtil.BN -var helper = require('./txHelper') +var remixLib = require('remix-lib') +var helper = remixLib.execution.txHelper var TreeView = require('remix-debugger').ui.TreeView var executionContext = require('../../execution-context') diff --git a/src/app/execution/txHelper.js b/src/app/execution/txHelper.js deleted file mode 100644 index f11a9247e9..0000000000 --- a/src/app/execution/txHelper.js +++ /dev/null @@ -1,121 +0,0 @@ -'use strict' -var ethJSABI = require('ethereumjs-abi') - -module.exports = { - encodeParams: function (funABI, args) { - var types = [] - if (funABI.inputs && funABI.inputs.length) { - for (var i = 0; i < funABI.inputs.length; i++) { - var type = funABI.inputs[i].type - types.push(type) - if (args.length < types.length) { - args.push('') - } - } - } - - // NOTE: the caller will concatenate the bytecode and this - // it could be done here too for consistency - return ethJSABI.rawEncode(types, args) - }, - - encodeFunctionId: function (funABI) { - var types = [] - if (funABI.inputs && funABI.inputs.length) { - for (var i = 0; i < funABI.inputs.length; i++) { - types.push(funABI.inputs[i].type) - } - } - - return ethJSABI.methodID(funABI.name, types) - }, - - sortAbiFunction: function (contractabi) { - var abi = contractabi.sort(function (a, b) { - if (a.name > b.name) { - return -1 - } else { - return 1 - } - }).sort(function (a, b) { - if (a.constant === true) { - return -1 - } else { - return 1 - } - }) - return abi - }, - - getConstructorInterface: function (abi) { - var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] } - if (typeof abi === 'string') { - try { - abi = JSON.parse(abi) - } catch (e) { - console.log('exception retrieving ctor abi ' + abi) - return funABI - } - } - - for (var i = 0; i < abi.length; i++) { - if (abi[i].type === 'constructor') { - funABI.inputs = abi[i].inputs || [] - break - } - } - - return funABI - }, - - getFunction: function (abi, fnName) { - for (var i = 0; i < abi.length; i++) { - if (abi[i].name === fnName) { - return abi[i] - } - } - return null - }, - - getFallbackInterface: function (abi) { - for (var i = 0; i < abi.length; i++) { - if (abi[i].type === 'fallback') { - return abi[i] - } - } - }, - - /** - * return the contract obj of the given @arg name. Uses last compilation result. - * return null if not found - * @param {String} name - contract name - * @returns contract obj and associated file: { contract, file } or null - */ - getContract: (contractName, contracts) => { - for (var file in contracts) { - if (contracts[file][contractName]) { - return { object: contracts[file][contractName], file: file } - } - } - return null - }, - - /** - * call the given @arg cb (function) for all the contracts. Uses last compilation result - * stop visiting when cb return true - * @param {Function} cb - callback - */ - visitContracts: (contracts, cb) => { - for (var file in contracts) { - for (var name in contracts[file]) { - if (cb({ name: name, object: contracts[file][name], file: file })) return - } - } - }, - - inputParametersDeclarationToString: function (abiinputs) { - var inputs = (abiinputs || []).map((inp) => inp.type + ' ' + inp.name) - return inputs.join(', ') - } - -}