diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js deleted file mode 100644 index a71740f0ea..0000000000 --- a/src/app/execution/txRunner.js +++ /dev/null @@ -1,206 +0,0 @@ -'use strict' -var EthJSTX = require('ethereumjs-tx') -var EthJSBlock = require('ethereumjs-block') -var ethJSUtil = require('ethereumjs-util') -var BN = ethJSUtil.BN -var executionContext = require('../../execution-context') - -function TxRunner (vmaccounts, api) { - this._api = api - this.blockNumber = 0 - this.runAsync = true - if (executionContext.isVM()) { - this.blockNumber = 1150000 // The VM is running in Homestead mode, which started at this block. - this.runAsync = false // We have to run like this cause the VM Event Manager does not support running multiple txs at the same time. - } - this.pendingTxs = {} - this.vmaccounts = vmaccounts - this.queusTxs = [] -} - -TxRunner.prototype.rawRun = function (args, confirmationCb, gasEstimationForceSend, promptCb, cb) { - run(this, args, Date.now(), confirmationCb, gasEstimationForceSend, promptCb, cb) -} - -function executeTx (tx, gasPrice, api, promptCb, callback) { - if (gasPrice) tx.gasPrice = executionContext.web3().toHex(gasPrice) - if (api.personalMode()) { - promptCb( - (value) => { - sendTransaction(executionContext.web3().personal.sendTransaction, tx, value, callback) - }, - () => { - return callback('Canceled by user.') - } - ) - } else { - sendTransaction(executionContext.web3().eth.sendTransaction, tx, null, callback) - } -} - -TxRunner.prototype.execute = function (args, confirmationCb, gasEstimationForceSend, promptCb, callback) { - var self = this - - var data = args.data - if (data.slice(0, 2) !== '0x') { - data = '0x' + data - } - - if (!executionContext.isVM()) { - self.runInNode(args.from, args.to, data, args.value, args.gasLimit, args.useCall, confirmationCb, gasEstimationForceSend, promptCb, callback) - } else { - try { - self.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, callback) - } catch (e) { - callback(e, null) - } - } -} - -TxRunner.prototype.runInVm = function (from, to, data, value, gasLimit, useCall, callback) { - const self = this - var account = self.vmaccounts[from] - if (!account) { - return callback('Invalid account selected') - } - var tx = new EthJSTX({ - nonce: new BN(account.nonce++), - gasPrice: new BN(1), - gasLimit: new BN(gasLimit, 10), - to: to, - value: new BN(value, 10), - data: new Buffer(data.slice(2), 'hex') - }) - tx.sign(account.privateKey) - - const coinbases = [ '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e' ] - const difficulties = [ new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10) ] - var block = new EthJSBlock({ - header: { - timestamp: new Date().getTime() / 1000 | 0, - number: self.blockNumber, - coinbase: coinbases[self.blockNumber % coinbases.length], - difficulty: difficulties[self.blockNumber % difficulties.length], - gasLimit: new BN(gasLimit, 10).imuln(2) - }, - transactions: [], - uncleHeaders: [] - }) - if (!useCall) { - ++self.blockNumber - } else { - executionContext.vm().stateManager.checkpoint() - } - - executionContext.vm().runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (err, result) { - if (useCall) { - executionContext.vm().stateManager.revert(function () {}) - } - err = err ? err.message : err - result.status = '0x' + result.vm.exception.toString(16) - callback(err, { - result: result, - transactionHash: ethJSUtil.bufferToHex(new Buffer(tx.hash())) - }) - }) -} - -TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCall, confirmCb, gasEstimationForceSend, promptCb, callback) { - const self = this - var tx = { from: from, to: to, data: data, value: value } - - if (useCall) { - tx.gas = gasLimit - return executionContext.web3().eth.call(tx, function (error, result) { - callback(error, { - result: result, - transactionHash: result.transactionHash - }) - }) - } - executionContext.web3().eth.estimateGas(tx, function (err, gasEstimation) { - gasEstimationForceSend(err, () => { - // callback is called whenever no error - tx.gas = !gasEstimation ? gasLimit : gasEstimation - - if (self._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) { - return executeTx(tx, null, self._api, promptCb, callback) - } - - self._api.detectNetwork((err, network) => { - if (err) { - console.log(err) - return - } - - confirmCb(network, tx, tx.gas, (gasPrice) => { - return executeTx(tx, gasPrice, self._api, promptCb, callback) - }, (error) => { - callback(error) - }) - }) - }, () => { - var blockGasLimit = executionContext.currentblockGasLimit() - // NOTE: estimateGas very likely will return a large limit if execution of the code failed - // we want to be able to run the code in order to debug and find the cause for the failure - if (err) return callback(err) - - var warnEstimation = ' An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that\'s also the reason of strong gas estimation). ' - warnEstimation += ' ' + err - - if (gasEstimation > gasLimit) { - return callback('Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation) - } - if (gasEstimation > blockGasLimit) { - return callback('Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation) - } - }) - }) -} - -function tryTillResponse (txhash, done) { - executionContext.web3().eth.getTransactionReceipt(txhash, function (err, result) { - if (err || !result) { - // Try again with a bit of delay if error or if result still null - setTimeout(function () { tryTillResponse(txhash, done) }, 500) - } else { - done(err, { - result: result, - transactionHash: result.transactionHash - }) - } - }) -} - -function sendTransaction (sendTx, tx, pass, callback) { - var cb = function (err, resp) { - if (err) { - return callback(err, resp) - } - tryTillResponse(resp, callback) - } - var args = pass !== null ? [tx, pass, cb] : [tx, cb] - try { - sendTx.apply({}, args) - } catch (e) { - return callback(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `) - } -} - -function run (self, tx, stamp, confirmationCb, gasEstimationForceSend, promptCb, callback) { - if (!self.runAsync && Object.keys(self.pendingTxs).length) { - self.queusTxs.push({ tx, stamp, callback }) - } else { - self.pendingTxs[stamp] = tx - self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, (error, result) => { - delete self.pendingTxs[stamp] - callback(error, result) - if (self.queusTxs.length) { - var next = self.queusTxs.pop() - run(self, next.tx, next.stamp, next.callback) - } - }) - } -} - -module.exports = TxRunner diff --git a/src/universal-dapp.js b/src/universal-dapp.js index 3c17b939b3..f0e8a7f6e3 100644 --- a/src/universal-dapp.js +++ b/src/universal-dapp.js @@ -8,7 +8,7 @@ var BN = ethJSUtil.BN var remixLib = require('remix-lib') var EventManager = remixLib.EventManager var crypto = require('crypto') -var TxRunner = require('./app/execution/txRunner') +var txRunner = remixLib.execution.txRunner var txExecution = remixLib.execution.txExecution var txFormat = remixLib.execution.txFormat var txHelper = remixLib.execution.txHelper