From 4055dca8a2a081a7ab2f698af2906319e20d9fa4 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Mon, 19 Feb 2018 13:40:41 -0500 Subject: [PATCH 01/10] separate runInVm code from runInNode --- src/app/execution/txRunner.js | 248 +++++++++++++++++----------------- 1 file changed, 127 insertions(+), 121 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 0d48c8e485..efa012a883 100644 --- a/src/app/execution/txRunner.js +++ b/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) + } + }) } } From 5e868c8ba5c6e54e91823243a5987273b53bf5dc Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:08:10 -0500 Subject: [PATCH 02/10] refactor: remove unnecessary level of depth from runInNode --- src/app/execution/txRunner.js | 102 ++++++++++++++++------------------ 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index efa012a883..bb0b452f57 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -126,73 +126,67 @@ TxRunner.prototype.runInVm = function (from, to, data, value, gasLimit, useCall, TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCall, callback) { const self = this - var tx = { - from: from, - to: to, - data: data, - value: value - } + var tx = { from: from, to: to, data: data, value: value } if (useCall) { tx.gas = gasLimit - executionContext.web3().eth.call(tx, function (error, result) { + return executionContext.web3().eth.call(tx, function (error, result) { callback(error, { result: result, transactionHash: result.transactionHash }) }) - } 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.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 - 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) - } + 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 + tx.gas = gasEstimation - 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', + 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: () => { - 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) - } + return callback('Transaction canceled by user.') + } + }) + } else { + executeTx(tx, null, self._api, callback) } - }) - } else { - executeTx(tx, null, self._api, callback) - } - }) - } + } + }) + } else { + executeTx(tx, null, self._api, callback) + } + }) } function tryTillResponse (txhash, done) { From 18fda2f31b3899adebac11126e5d8bbb68b53ee4 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:17:06 -0500 Subject: [PATCH 03/10] refactor: remove unnecessary level of depth from runInNode --- src/app/execution/txRunner.js | 57 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index bb0b452f57..748ca1a24a 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -155,37 +155,36 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal tx.gas = gasEstimation - 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', + if (self._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) { + return executeTx(tx, null, self._api, callback) + } + 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: () => { - 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) - } + return callback('Transaction canceled by user.') + } + }) + } else { + executeTx(tx, null, self._api, callback) } - }) - } else { - executeTx(tx, null, self._api, callback) - } + } + }) }) } From 280a87bf7618597bc480f6d0a426b08891b31a28 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:35:24 -0500 Subject: [PATCH 04/10] refactor: remove unnecessary level of depth from runInNode --- src/app/execution/txRunner.js | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 748ca1a24a..7dfd537665 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -161,28 +161,28 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal 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', + return + } + 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: () => { - 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) - } + return callback('Transaction canceled by user.') + } + }) + } else { + executeTx(tx, null, self._api, callback) } }) }) From 38f4ba1a522f5e839506564afebfcc9b7217b43a Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:42:51 -0500 Subject: [PATCH 05/10] refactor: remove unnecessary level of depth from runInNode --- src/app/execution/txRunner.js | 39 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 7dfd537665..ffd84e98c2 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -163,27 +163,26 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal console.log(err) return } - 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) + if (network.name !== 'Main') { + return executeTx(tx, null, self._api, callback) } + 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.') + } + }) }) }) } From dd35250ea2022bf216b42af71a6f4849e4f2dbd4 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:45:20 -0500 Subject: [PATCH 06/10] refactor: remove unnecessary level of depth from runInNode --- src/app/execution/txRunner.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index ffd84e98c2..5bfd5f5aab 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -172,11 +172,10 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal 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) + return callback('Given gas grice is not correct') } + var gasPrice = executionContext.web3().toWei(content.querySelector('#gasprice').value, 'gwei') + executeTx(tx, gasPrice, self._api, callback) }}, { label: 'Cancel', fn: () => { From aa49f0d2bf06e1b89094710c25a0b8263b3f85ef Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 17:51:40 -0500 Subject: [PATCH 07/10] refactor: remove unnecessary level of depth from runInVm --- src/app/execution/txRunner.js | 92 +++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 5bfd5f5aab..23fe9ebc07 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -68,60 +68,60 @@ TxRunner.prototype.execute = function (args, callback) { if (!executionContext.isVM()) { 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) + 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 - 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) + 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() - } + 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())) - }) + 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) - } + }) } TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCall, callback) { From da160377aba6f6b7e2ef217831b9aa3d33dcddf9 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 18:07:55 -0500 Subject: [PATCH 08/10] move confirmation dialog to its own file --- src/app/execution/confirmDialog.js | 75 ++++++++++++++++++++++++++++++ src/app/execution/txRunner.js | 72 +--------------------------- 2 files changed, 76 insertions(+), 71 deletions(-) create mode 100644 src/app/execution/confirmDialog.js diff --git a/src/app/execution/confirmDialog.js b/src/app/execution/confirmDialog.js new file mode 100644 index 0000000000..c05f8ff150 --- /dev/null +++ b/src/app/execution/confirmDialog.js @@ -0,0 +1,75 @@ +var executionContext = require('../../execution-context') +var typeConversion = require('../../lib/typeConversion') +var yo = require('yo-yo') +var csjs = require('csjs-inject') +var remixLib = require('remix-lib') +var styleGuide = remixLib.ui.styleGuide +var styles = styleGuide() + +var css = csjs` + .txInfoBox { + ${styles.rightPanel.compileTab.box_CompileContainer}; // add askToConfirmTXContainer to Remix and then replace this styling + } + .wrapword { + white-space: pre-wrap; /* Since CSS 2.1 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + } +` + +function confirmDialog (tx, gasEstimation, self) { + var amount = executionContext.web3().fromWei(typeConversion.toInt(tx.value), 'ether') + var input = yo`` + var el = yo` +
+
You are creating a transaction on the main network. Click confirm if you are sure to continue.
+
+
From: ${tx.from}
+
To: ${tx.to ? tx.to : '(Contract Creation)'}
+
Amount: ${amount} Ether
+
Gas estimation: ${gasEstimation}
+
Gas limit: ${tx.gas}
+
Gas price: Gwei (visit ethgasstation.info to get more info about gas price)
+
Max transaction fee:
+
Data:
+
${tx.data}
+
+
+ ${input} + Do not ask for confirmation again. (the setting will not be persisted for the next page reload) +
+
+ ` + + var warnMessage = ' Please fix this issue before sending any transaction. ' + function gasPriceChanged () { + try { + var gasPrice = el.querySelector('#gasprice').value + var fee = executionContext.web3().toBigNumber(tx.gas).mul(executionContext.web3().toBigNumber(executionContext.web3().toWei(gasPrice.toString(10), 'gwei'))) + el.querySelector('#txfee').innerHTML = ' ' + executionContext.web3().fromWei(fee.toString(10), 'ether') + ' Ether' + el.gasPriceStatus = true + } catch (e) { + el.querySelector('#txfee').innerHTML = warnMessage + e.message + el.gasPriceStatus = false + } + } + + executionContext.web3().eth.getGasPrice((error, gasPrice) => { + if (error) { + el.querySelector('#txfee').innerHTML = 'Unable to retrieve the current network gas price.' + warnMessage + error + } else { + try { + el.querySelector('#gasprice').value = executionContext.web3().fromWei(gasPrice.toString(10), 'gwei') + gasPriceChanged() + } catch (e) { + el.querySelector('#txfee').innerHTML = warnMessage + e.message + el.gasPriceStatus = false + } + } + }) + return el +} + +module.exports = confirmDialog diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 23fe9ebc07..9729c4c201 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -5,26 +5,9 @@ var ethJSUtil = require('ethereumjs-util') var BN = ethJSUtil.BN var executionContext = require('../../execution-context') var modalDialog = require('../ui/modaldialog') -var yo = require('yo-yo') -var typeConversion = require('../../lib/typeConversion') -var csjs = require('csjs-inject') -var remixLib = require('remix-lib') -var styleGuide = remixLib.ui.styleGuide -var styles = styleGuide() var modal = require('../ui/modal-dialog-custom') -var css = csjs` - .txInfoBox { - ${styles.rightPanel.compileTab.box_CompileContainer}; // add askToConfirmTXContainer to Remix and then replace this styling - } - .wrapword { - white-space: pre-wrap; /* Since CSS 2.1 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - } -` +var confirmDialog = require('./confirmDialog') function TxRunner (vmaccounts, api) { this._api = api @@ -231,57 +214,4 @@ function run (self, tx, stamp, callback) { } } -function confirmDialog (tx, gasEstimation, self) { - var amount = executionContext.web3().fromWei(typeConversion.toInt(tx.value), 'ether') - var input = yo`` - var el = yo` -
-
You are creating a transaction on the main network. Click confirm if you are sure to continue.
-
-
From: ${tx.from}
-
To: ${tx.to ? tx.to : '(Contract Creation)'}
-
Amount: ${amount} Ether
-
Gas estimation: ${gasEstimation}
-
Gas limit: ${tx.gas}
-
Gas price: Gwei (visit ethgasstation.info to get more info about gas price)
-
Max transaction fee:
-
Data:
-
${tx.data}
-
-
- ${input} - Do not ask for confirmation again. (the setting will not be persisted for the next page reload) -
-
- ` - - var warnMessage = ' Please fix this issue before sending any transaction. ' - function gasPriceChanged () { - try { - var gasPrice = el.querySelector('#gasprice').value - var fee = executionContext.web3().toBigNumber(tx.gas).mul(executionContext.web3().toBigNumber(executionContext.web3().toWei(gasPrice.toString(10), 'gwei'))) - el.querySelector('#txfee').innerHTML = ' ' + executionContext.web3().fromWei(fee.toString(10), 'ether') + ' Ether' - el.gasPriceStatus = true - } catch (e) { - el.querySelector('#txfee').innerHTML = warnMessage + e.message - el.gasPriceStatus = false - } - } - - executionContext.web3().eth.getGasPrice((error, gasPrice) => { - if (error) { - el.querySelector('#txfee').innerHTML = 'Unable to retrieve the current network gas price.' + warnMessage + error - } else { - try { - el.querySelector('#gasprice').value = executionContext.web3().fromWei(gasPrice.toString(10), 'gwei') - gasPriceChanged() - } catch (e) { - el.querySelector('#txfee').innerHTML = warnMessage + e.message - el.gasPriceStatus = false - } - } - }) - return el -} - module.exports = TxRunner From 91fe08a6db8add300fd9997d3ad6d7568b617fbb Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Tue, 20 Feb 2018 18:40:24 -0500 Subject: [PATCH 09/10] extract logic from confirmDialog and move it into txRunner --- src/app/execution/confirmDialog.js | 51 ++++++++++++------------------ src/app/execution/txRunner.js | 35 +++++++++++++++++++- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/app/execution/confirmDialog.js b/src/app/execution/confirmDialog.js index c05f8ff150..60654b8092 100644 --- a/src/app/execution/confirmDialog.js +++ b/src/app/execution/confirmDialog.js @@ -1,5 +1,3 @@ -var executionContext = require('../../execution-context') -var typeConversion = require('../../lib/typeConversion') var yo = require('yo-yo') var csjs = require('csjs-inject') var remixLib = require('remix-lib') @@ -19,9 +17,15 @@ var css = csjs` } ` -function confirmDialog (tx, gasEstimation, self) { - var amount = executionContext.web3().fromWei(typeConversion.toInt(tx.value), 'ether') - var input = yo`` +function confirmDialog (tx, amount, gasEstimation, self, newGasPriceCb, initialParamsCb) { + var onGasPriceChange = function () { + var gasPrice = el.querySelector('#gasprice').value + newGasPriceCb(gasPrice, (priceStatus, txFeeText) => { + el.querySelector('#txfee').innerHTML = txFeeText + el.gasPriceStatus = priceStatus + }) + } + var el = yo`
You are creating a transaction on the main network. Click confirm if you are sure to continue.
@@ -31,44 +35,31 @@ function confirmDialog (tx, gasEstimation, self) {
Amount: ${amount} Ether
Gas estimation: ${gasEstimation}
Gas limit: ${tx.gas}
-
Gas price: Gwei (visit ethgasstation.info to get more info about gas price)
+
Gas price: Gwei (visit ethgasstation.info to get more info about gas price)
Max transaction fee:
Data:
${tx.data}
- ${input} + Do not ask for confirmation again. (the setting will not be persisted for the next page reload)
` - var warnMessage = ' Please fix this issue before sending any transaction. ' - function gasPriceChanged () { - try { - var gasPrice = el.querySelector('#gasprice').value - var fee = executionContext.web3().toBigNumber(tx.gas).mul(executionContext.web3().toBigNumber(executionContext.web3().toWei(gasPrice.toString(10), 'gwei'))) - el.querySelector('#txfee').innerHTML = ' ' + executionContext.web3().fromWei(fee.toString(10), 'ether') + ' Ether' - el.gasPriceStatus = true - } catch (e) { - el.querySelector('#txfee').innerHTML = warnMessage + e.message - el.gasPriceStatus = false + initialParamsCb((txFeeText, gasPriceValue, gasPriceStatus) => { + if (txFeeText) { + el.querySelector('#txfee').innerHTML = txFeeText } - } - - executionContext.web3().eth.getGasPrice((error, gasPrice) => { - if (error) { - el.querySelector('#txfee').innerHTML = 'Unable to retrieve the current network gas price.' + warnMessage + error - } else { - try { - el.querySelector('#gasprice').value = executionContext.web3().fromWei(gasPrice.toString(10), 'gwei') - gasPriceChanged() - } catch (e) { - el.querySelector('#txfee').innerHTML = warnMessage + e.message - el.gasPriceStatus = false - } + if (gasPriceValue) { + el.querySelector('#gasprice').value = gasPriceValue + onGasPriceChange() + } + if (gasPriceStatus !== undefined) { + el.gasPriceStatus = gasPriceStatus } }) + return el } diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index 9729c4c201..b6ec966aa2 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -6,6 +6,7 @@ var BN = ethJSUtil.BN var executionContext = require('../../execution-context') var modalDialog = require('../ui/modaldialog') var modal = require('../ui/modal-dialog-custom') +var typeConversion = require('../../lib/typeConversion') var confirmDialog = require('./confirmDialog') @@ -149,7 +150,39 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal if (network.name !== 'Main') { return executeTx(tx, null, self._api, callback) } - var content = confirmDialog(tx, gasEstimation, self) + + var amount = executionContext.web3().fromWei(typeConversion.toInt(tx.value), 'ether') + var content = confirmDialog(tx, amount, gasEstimation, self, + (gasPrice, cb) => { + let txFeeText, priceStatus + // TODO: this try catch feels like an anti pattern, can/should be + // removed, but for now keeping the original logic + try { + var fee = executionContext.web3().toBigNumber(tx.gas).mul(executionContext.web3().toBigNumber(executionContext.web3().toWei(gasPrice.toString(10), 'gwei'))) + txFeeText = ' ' + executionContext.web3().fromWei(fee.toString(10), 'ether') + ' Ether' + priceStatus = true + } catch (e) { + txFeeText = ' Please fix this issue before sending any transaction. ' + e.message + priceStatus = false + } + cb(txFeeText, priceStatus) + }, + (cb) => { + executionContext.web3().eth.getGasPrice((error, gasPrice) => { + var warnMessage = ' Please fix this issue before sending any transaction. ' + if (error) { + return cb('Unable to retrieve the current network gas price.' + warnMessage + error) + } + try { + var gasPriceValue = executionContext.web3().fromWei(gasPrice.toString(10), 'gwei') + cb(null, gasPriceValue) + } catch (e) { + cb(warnMessage + e.message, null, false) + } + }) + } + ) + modalDialog('Confirm transaction', content, { label: 'Confirm', fn: () => { From f08b43acecb151cfbf92f780262f67f9aa9a92d1 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Wed, 21 Feb 2018 10:39:32 -0500 Subject: [PATCH 10/10] fix callback params --- src/app/execution/txRunner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/execution/txRunner.js b/src/app/execution/txRunner.js index b6ec966aa2..e109881860 100644 --- a/src/app/execution/txRunner.js +++ b/src/app/execution/txRunner.js @@ -165,7 +165,7 @@ TxRunner.prototype.runInNode = function (from, to, data, value, gasLimit, useCal txFeeText = ' Please fix this issue before sending any transaction. ' + e.message priceStatus = false } - cb(txFeeText, priceStatus) + cb(priceStatus, txFeeText) }, (cb) => { executionContext.web3().eth.getGasPrice((error, gasPrice) => {