Merge pull request #790 from ethereum/debugVMcall

Improve Logger
pull/1/head
yann300 7 years ago committed by GitHub
commit 33b093c3d9
  1. 7
      src/app/execution/eventsDecoder.js
  2. 31
      src/app/execution/txListener.js
  3. 55
      src/app/execution/txLogger.js
  4. 6
      src/app/tabs/run-tab.js
  5. 27
      src/universal-dapp.js

@ -18,8 +18,9 @@ class EventsDecoder {
* @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) cb(error)
if (error) return cb(error)
this._decodeLogs(tx, receipt, contractName, compiledContracts, cb)
})
}
@ -29,7 +30,7 @@ class EventsDecoder {
return cb('cannot decode logs - contract or receipt not resolved ')
}
if (!receipt.logs) {
return cb(null, [])
return cb(null, { decoded: [], raw: [] })
}
this._decodeEvents(tx, receipt.logs, contract, contracts, cb)
}
@ -70,7 +71,7 @@ class EventsDecoder {
}
events.push({ event: event, args: decoded })
}
cb(null, events)
cb(null, { decoded: events, raw: logs })
}
}

@ -31,7 +31,33 @@ class TxListener {
this.startListening()
}
})
opt.event.udapp.register('transactionExecuted', (error, to, data, lookupOnly, txResult) => {
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,
output: txResult.result,
returnValue: executionContext.isVM() ? txResult.result.vm.return : ethJSUtil.toBuffer(txResult.result),
envMode: executionContext.getProvider()
}
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
@ -42,7 +68,7 @@ class TxListener {
executionContext.web3().eth.getTransaction(txResult.transactionHash, (error, tx) => {
if (error) return console.log(error)
if (txResult && txResult.result && txResult.result.vm) tx.returnValue = txResult.result.vm.return
tx.envMode = executionContext.getProvider()
this._resolve([tx], () => {
})
})
@ -174,7 +200,6 @@ class TxListener {
}
_resolveTx (tx, cb) {
console.log(tx)
var contracts = this._api.contracts()
if (!contracts) return cb()
var contractName

@ -13,6 +13,7 @@ var helper = require('../../lib/helper')
var ethJSUtil = require('ethereumjs-util')
var BN = ethJSUtil.BN
var executionContext = require('../../execution-context')
var modalDialog = require('../ui/modal-dialog-custom')
var css = csjs`
.log {
@ -74,7 +75,12 @@ class TxLogger {
this.opts = opts
this.logKnownTX = opts.api.editorpanel.registerCommand('knownTransaction', (args, cmds, append) => {
var data = args[0]
var el = renderKnownTransaction(this, data)
var el
if (data.tx.isCall) {
el = renderCall(this, data)
} else {
el = renderKnownTransaction(this, data)
}
append(el)
}, { activate: true })
@ -115,6 +121,10 @@ class TxLogger {
opts.events.txListener.register('newTransaction', (tx) => {
log(this, tx, opts.api)
})
opts.events.txListener.register('newCall', (tx) => {
log(this, tx, opts.api)
})
}
}
@ -139,7 +149,7 @@ function renderKnownTransaction (self, data) {
self.event.trigger('debugRequested', [data.tx.hash])
}
var tx = yo`
<span class=${css.container} id="tx${data.tx.hash}">
<span id="tx${data.tx.hash}">
<div class="${css.log}">
${context(self, {from, to, data})}
<div class=${css.buttons}>
@ -165,7 +175,7 @@ function renderKnownTransaction (self, data) {
input: data.tx.input,
'decoded input': data.resolvedData && data.resolvedData.params ? JSON.stringify(value(data.resolvedData.params), null, '\t') : ' - ',
'decoded output': data.resolvedData && data.resolvedData.decodedReturnValue ? JSON.stringify(value(data.resolvedData.decodedReturnValue), null, '\t') : ' - ',
logs: JSON.stringify(data.logs, null, '\t') || '0',
logs: data.logs,
val: data.tx.value
})
tx.appendChild(table)
@ -175,6 +185,31 @@ function renderKnownTransaction (self, data) {
return tx
}
function renderCall (self, data) {
function debug () {
if (data.tx.envMode === 'vm') {
self.event.trigger('debugRequested', [data.tx.hash])
} else {
modalDialog.alert('Cannot debug this call. Debugging calls is only possible in JavaScript VM mode.')
}
}
var to = data.resolvedData.contractName + '.' + data.resolvedData.fn + ' ' + helper.shortenHexData(data.tx.to)
var from = data.tx.from ? data.tx.from : ' - '
var input = data.tx.input ? helper.shortenHexData(data.tx.input) : ''
var tx = yo`
<span id="tx${data.tx.hash}">
<div class="${css.log}">
<span><span class=${css.tx}>[call]</span> from:${from}, to:${to}, data:${input}, return: </span>
<div class=${css.buttons}>
<button class=${css.debug} onclick=${debug}>Debug</button>
</div>
</div>
<div> ${JSON.stringify(value(data.resolvedData.decodedReturnValue), null, '\t')}</div>
</span>
`
return tx
}
function renderUnknownTransaction (self, data) {
var from = data.tx.from
var to = data.tx.to
@ -182,7 +217,7 @@ function renderUnknownTransaction (self, data) {
self.event.trigger('debugRequested', [data.tx.hash])
}
var tx = yo`
<span class=${css.container} id="tx${data.tx.hash}">
<span id="tx${data.tx.hash}">
<div class="${css.log}">
${context(self, {from, to, data})}
<div class=${css.buttons}>
@ -205,7 +240,7 @@ function renderUnknownTransaction (self, data) {
input: data.tx.input,
hash: data.tx.hash,
gas: data.tx.gas,
logs: JSON.stringify(data.logs) || '0'
logs: data.logs
})
tx.appendChild(table)
}
@ -225,13 +260,13 @@ function context (self, opts) {
var val = data.tx.value
var hash = data.tx.hash ? helper.shortenHexData(data.tx.hash) : ''
var input = data.tx.input ? helper.shortenHexData(data.tx.input) : ''
var logs = data.logs ? data.logs.length : 0
var logs = data.logs && data.logs.decoded ? data.logs.decoded.length : 0
var block = data.tx.blockNumber || ''
var i = data.tx.transactionIndex
if (executionContext.getProvider() === 'vm') {
return yo`<span><span class=${css.tx}>[vm]</span> from:${from}, to:${to}, value:${value(val)} wei, data:${input}, ${logs} logs, hash:${hash}</span>`
} else if (executionContext.getProvider() !== 'vm' && data.resolvedData) {
return yo`<span><span class='${css.tx}'>[block:${block} txIndex:${i}]</span> from:${from}, to:${to}, value:${value(val)} wei</span>`
return yo`<span><span class='${css.tx}'>[block:${block} txIndex:${i}]</span> from:${from}, to:${to}, value:${value(val)} wei, ${logs} logs, data:${input}, hash:${hash}</span>`
} else {
to = helper.shortenHexData(to)
hash = helper.shortenHexData(data.tx.blockHash)
@ -247,7 +282,7 @@ function value (v) {
ret.push(value(v[k]))
}
return ret
} else if (BN.isBN(v)) {
} else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber')) {
return v.toString(10)
} else if (v.indexOf && v.indexOf('0x') === 0) {
return (new BN(v.replace('0x', ''), 16)).toString(10)
@ -349,7 +384,9 @@ function createTable (opts) {
var logs = yo`
<tr class="${css.tr}">
<td class="${css.td}"> logs </td>
<td class="${css.td}"><i class="fa fa-clipboard ${css.clipboardCopy}" aria-hidden="true" onclick=${function () { copy(opts.logs || '0') }} title='Copy to clipboard'></i>${opts.logs || '0'}</td>
<td class="${css.td}">
<i class="fa fa-clipboard ${css.clipboardCopy}" aria-hidden="true" onclick=${function () { copy(JSON.stringify(opts.logs.decoded || [], null, '\t')) }} title='Copy Logs to clipboard'></i>
<i class="fa fa-clipboard ${css.clipboardCopy}" aria-hidden="true" onclick=${function () { copy(JSON.stringify(opts.logs.raw || '0')) }} title='Copy Raw Logs to clipboard'></i>${JSON.stringify(opts.logs.decoded || [], null, '\t')}</td>
</tr class="${css.tr}">
`
if (opts.logs) table.appendChild(logs)

@ -317,11 +317,11 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value))
} else {
modalDialogCustom.alert(error)
appAPI.logMessage(`creation of ${contractName} errored: ` + error)
}
})
} else {
modalDialogCustom.alert(error)
appAPI.logMessage(`creation of ${contractName} errored: ` + error)
}
})
}
@ -411,7 +411,7 @@ function settings (appAPI, appEvents) {
`
// EVENTS
appEvents.udapp.register('transactionExecuted', (error, to, data, lookupOnly, txResult) => {
appEvents.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
if (error) return
if (!lookupOnly) el.querySelector('#value').value = '0'
})

@ -13,7 +13,6 @@ var txFormat = require('./app/execution/txFormat')
var txHelper = require('./app/execution/txHelper')
var txExecution = require('./app/execution/txExecution')
var helper = require('./lib/helper')
var modalDialogCustom = require('./app/ui/modal-dialog-custom')
var executionContext = require('./execution-context')
// copy to copyToClipboard
@ -121,7 +120,9 @@ function UniversalDApp (opts = {}) {
UniversalDApp.prototype.reset = function (contracts, transactionContextAPI) {
this.el.innerHTML = ''
this.contracts = contracts
this.transactionContextAPI = transactionContextAPI
if (transactionContextAPI) {
this.transactionContextAPI = transactionContextAPI
}
this.accounts = {}
if (executionContext.isVM()) {
this._addAccount('3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511', '0x56BC75E2D63100000')
@ -311,13 +312,21 @@ UniversalDApp.prototype.getCallButton = function (args) {
})
function call (isUserAction) {
var logMsg
if (isUserAction) {
if (!args.funABI.constant) {
logMsg = `transact to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}`
} else {
logMsg = `call to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}`
}
}
txFormat.buildData(args.contractAbi, self.contracts, false, args.funABI, inputField.val(), self, (error, data) => {
if (!error) {
if (isUserAction) {
if (!args.funABI.constant) {
self._api.logMessage(`transact to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'} pending ... `)
self._api.logMessage(`${logMsg} pending ... `)
} else {
self._api.logMessage(`call to ${args.contractName}.${(args.funABI.name) ? args.funABI.name : '(fallback)'}`)
self._api.logMessage(`${logMsg}`)
}
}
txExecution.callFunction(args.address, data, args.funABI, self, (error, txResult) => {
@ -326,7 +335,7 @@ UniversalDApp.prototype.getCallButton = function (args) {
if (isVM) {
var vmError = txExecution.checkVMError(txResult)
if (vmError.error) {
modalDialogCustom.alert(vmError.message)
self._api.logMessage(`${logMsg} errored: ${vmError.message} `)
return
}
}
@ -335,11 +344,11 @@ UniversalDApp.prototype.getCallButton = function (args) {
$outputOverride.html(decoded)
}
} else {
modalDialogCustom.alert(error)
self._api.logMessage(`${logMsg} errored: ${error} `)
}
})
} else {
modalDialogCustom.alert(error)
self._api.logMessage(`${logMsg} errored: ${error} `)
}
})
}
@ -459,7 +468,9 @@ UniversalDApp.prototype.runTx = function (args, cb) {
function (callback) {
self.txRunner.rawRun(tx, function (error, result) {
if (!args.useCall) {
self.event.trigger('transactionExecuted', [error, args.to, args.data, false, result])
self.event.trigger('transactionExecuted', [error, args.from, args.to, args.data, false, result])
} else {
self.event.trigger('callExecuted', [error, args.from, args.to, args.data, true, result])
}
if (error) {
if (typeof (error) !== 'string') {

Loading…
Cancel
Save