separate runInVm code from runInNode

pull/3094/head
Iuri Matias 7 years ago
parent 05466899d1
commit 4055dca8a2
  1. 248
      src/app/execution/txRunner.js

@ -43,149 +43,155 @@ TxRunner.prototype.rawRun = function (args, cb) {
run(this, args, Date.now(), cb)
}
TxRunner.prototype.execute = function (args, callback) {
var self = this
function execute (gasPrice) {
if (gasPrice) tx.gasPrice = executionContext.web3().toHex(gasPrice)
function executeTx (tx, gasPrice, api, callback) {
if (gasPrice) tx.gasPrice = executionContext.web3().toHex(gasPrice)
if (self._api.personalMode()) {
modal.promptPassphrase(null, 'Personal mode is enabled. Please provide passphrase of account ' + tx.from, '', (value) => {
sendTransaction(executionContext.web3().personal.sendTransaction, tx, value, callback)
}, () => {
return callback('Canceled by user.')
})
} else {
sendTransaction(executionContext.web3().eth.sendTransaction, tx, null, callback)
}
if (api.personalMode()) {
modal.promptPassphrase(null, 'Personal mode is enabled. Please provide passphrase of account ' + tx.from, '', (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, callback) {
var self = this
var from = args.from
var to = args.to
var data = args.data
if (data.slice(0, 2) !== '0x') {
data = '0x' + data
}
var value = args.value
var gasLimit = args.gasLimit
var tx
if (!executionContext.isVM()) {
tx = {
from: from,
to: to,
data: data,
value: value
self.runInNode(args.from, args.to, data, args.value, args.gasLimit, args.useCall, callback)
} else {
self.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, callback)
}
}
TxRunner.prototype.runInVm = function (from, to, data, value, gasLimit, useCall, callback) {
const self = this
try {
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)
if (args.useCall) {
tx.gas = gasLimit
executionContext.web3().eth.call(tx, function (error, result) {
callback(error, {
result: result,
transactionHash: result.transactionHash
})
})
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.web3().eth.estimateGas(tx, function (err, gasEstimation) {
if (err) {
return callback(err, gasEstimation)
}
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
executionContext.vm().stateManager.checkpoint()
}
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)."
if (gasEstimation > gasLimit) {
return callback('Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation)
}
if (gasEstimation > blockGasLimit) {
return callback('Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation)
}
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()))
})
})
} catch (e) {
callback(e, null)
}
}
tx.gas = gasEstimation
TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCall, callback) {
const self = this
var tx = {
from: from,
to: to,
data: data,
value: value
}
if (!self._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
self._api.detectNetwork((err, network) => {
if (err) {
console.log(err)
} else {
if (network.name === 'Main') {
var content = confirmDialog(tx, gasEstimation, self)
modalDialog('Confirm transaction', content,
{ label: 'Confirm',
fn: () => {
self._api.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
if (!content.gasPriceStatus) {
callback('Given gas grice is not correct')
} else {
var gasPrice = executionContext.web3().toWei(content.querySelector('#gasprice').value, 'gwei')
execute(gasPrice)
}
}}, {
label: 'Cancel',
fn: () => {
return callback('Transaction canceled by user.')
}
})
} else {
execute()
}
}
})
} else {
execute()
}
if (useCall) {
tx.gas = gasLimit
executionContext.web3().eth.call(tx, function (error, result) {
callback(error, {
result: result,
transactionHash: result.transactionHash
})
}
})
} else {
try {
var account = self.vmaccounts[from]
if (!account) {
return callback('Invalid account selected')
executionContext.web3().eth.estimateGas(tx, function (err, gasEstimation) {
if (err) {
return callback(err, gasEstimation)
}
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)
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
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 (!args.useCall) {
++self.blockNumber
} else {
executionContext.vm().stateManager.checkpoint()
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)."
if (gasEstimation > gasLimit) {
return callback('Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation)
}
if (gasEstimation > blockGasLimit) {
return callback('Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation)
}
tx.gas = gasEstimation
executionContext.vm().runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (err, result) {
if (args.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()))
if (!self._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
self._api.detectNetwork((err, network) => {
if (err) {
console.log(err)
} else {
if (network.name === 'Main') {
var content = confirmDialog(tx, gasEstimation, self)
modalDialog('Confirm transaction', content,
{ label: 'Confirm',
fn: () => {
self._api.config.setUnpersistedProperty('doNotShowTransactionConfirmationAgain', content.querySelector('input#confirmsetting').checked)
if (!content.gasPriceStatus) {
callback('Given gas grice is not correct')
} else {
var gasPrice = executionContext.web3().toWei(content.querySelector('#gasprice').value, 'gwei')
executeTx(tx, gasPrice, self._api, callback)
}
}}, {
label: 'Cancel',
fn: () => {
return callback('Transaction canceled by user.')
}
})
} else {
executeTx(tx, null, self._api, callback)
}
}
})
})
} catch (e) {
callback(e, null)
}
} else {
executeTx(tx, null, self._api, callback)
}
})
}
}

Loading…
Cancel
Save