Merge pull request #1155 from ethereum/move_tx_runner_to_remix_lib

Move tx runner to remix lib
pull/1/head
yann300 7 years ago committed by GitHub
commit 62ae88ec33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .circleci/config.yml
  2. 3
      package.json
  3. 2
      src/app/execution/txLogger.js
  4. 206
      src/app/execution/txRunner.js
  5. 42
      src/app/execution/typeConversion.js
  6. 4
      src/universal-dapp.js

@ -26,10 +26,10 @@ jobs:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- dep-bundle-{{ checksum "package.json" }} - dep-bundle-2-{{ checksum "package.json" }}
- run: npm install - run: npm install
- save_cache: - save_cache:
key: dep-bundle-{{ checksum "package.json" }} key: dep-bundle-2-{{ checksum "package.json" }}
paths: paths:
- /repo/node_modules - /repo/node_modules
- run: npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build - run: npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build

@ -19,9 +19,6 @@
"csjs-inject": "^1.0.1", "csjs-inject": "^1.0.1",
"csslint": "^1.0.2", "csslint": "^1.0.2",
"deep-equal": "^1.0.1", "deep-equal": "^1.0.1",
"ethereumjs-abi": "https://github.com/ethereumjs/ethereumjs-abi",
"ethereumjs-block": "^1.6.0",
"ethereumjs-tx": "^1.3.3",
"ethereumjs-util": "^5.1.2", "ethereumjs-util": "^5.1.2",
"execr": "^1.0.1", "execr": "^1.0.1",
"exorcist": "^0.4.0", "exorcist": "^0.4.0",

@ -12,7 +12,7 @@ var EventManager = remixLib.EventManager
var helper = require('../../lib/helper') var helper = require('../../lib/helper')
var executionContext = require('../../execution-context') var executionContext = require('../../execution-context')
var modalDialog = require('../ui/modal-dialog-custom') var modalDialog = require('../ui/modal-dialog-custom')
var typeConversion = require('./typeConversion') var typeConversion = remixLib.execution.typeConversion
var css = csjs` var css = csjs`
.log { .log {

@ -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

@ -1,42 +0,0 @@
'use strict'
var ethJSUtil = require('ethereumjs-util')
var BN = ethJSUtil.BN
module.exports = {
toInt: (h) => {
if (h.indexOf && h.indexOf('0x') === 0) {
return (new BN(h.replace('0x', ''), 16)).toString(10)
} else if (h.constructor && h.constructor.name === 'BigNumber' || BN.isBN(h)) {
return h.toString(10)
}
return h
},
stringify: stringify
}
function stringify (v) {
try {
if (v instanceof Array) {
var ret = []
for (var k in v) {
ret.push(stringify(v[k]))
}
return ret
} else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber')) {
return v.toString(10)
} else if (v._isBuffer) {
return ethJSUtil.bufferToHex(v)
} else if (typeof v === 'object') {
var retObject = {}
for (var i in v) {
retObject[i] = stringify(v[i])
}
return retObject
} else {
return v
}
} catch (e) {
console.log(e)
return v
}
}

@ -8,7 +8,7 @@ var BN = ethJSUtil.BN
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var crypto = require('crypto') var crypto = require('crypto')
var TxRunner = require('./app/execution/txRunner') var TxRunner = remixLib.execution.txRunner
var txExecution = remixLib.execution.txExecution var txExecution = remixLib.execution.txExecution
var txFormat = remixLib.execution.txFormat var txFormat = remixLib.execution.txFormat
var txHelper = remixLib.execution.txHelper var txHelper = remixLib.execution.txHelper
@ -17,7 +17,7 @@ var modalCustom = require('./app/ui/modal-dialog-custom')
var uiUtil = require('./app/ui/util') var uiUtil = require('./app/ui/util')
var modalDialog = require('./app/ui/modaldialog') var modalDialog = require('./app/ui/modaldialog')
var typeConversion = require('./app/execution/typeConversion') var typeConversion = remixLib.execution.typeConversion
var confirmDialog = require('./app/execution/confirmDialog') var confirmDialog = require('./app/execution/confirmDialog')
/* /*

Loading…
Cancel
Save