Unverified Commit 0e91a817 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #451 from ethereum/refactor_remix_debug5_ab

misc refactors remix-debug / remix-lib
parents 7f4b79ef 76d83196
...@@ -2,7 +2,6 @@ var registry = require('../../global/registry') ...@@ -2,7 +2,6 @@ var registry = require('../../global/registry')
var remixLib = require('@remix-project/remix-lib') var remixLib = require('@remix-project/remix-lib')
var yo = require('yo-yo') var yo = require('yo-yo')
var EventsDecoder = remixLib.execution.EventsDecoder var EventsDecoder = remixLib.execution.EventsDecoder
var TransactionReceiptResolver = require('../../lib/transactionReceiptResolver')
const transactionDetailsLinks = { const transactionDetailsLinks = {
'Main': 'https://www.etherscan.io/tx/', 'Main': 'https://www.etherscan.io/tx/',
...@@ -27,7 +26,19 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) { ...@@ -27,7 +26,19 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) {
}) })
// ----------------- Tx listener ----------------- // ----------------- Tx listener -----------------
const transactionReceiptResolver = new TransactionReceiptResolver(blockchain) let _transactionReceipts = {}
const transactionReceiptResolver = (tx, cb) => {
if (_transactionReceipts[tx.hash]) {
return cb(null, _transactionReceipts[tx.hash])
}
blockchain.web3().eth.getTransactionReceipt(tx.hash, (error, receipt) => {
if (error) {
return cb(error)
}
_transactionReceipts[tx.hash] = receipt
cb(null, receipt)
})
}
const txlistener = blockchain.getTxListener({ const txlistener = blockchain.getTxListener({
api: { api: {
...@@ -35,9 +46,7 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) { ...@@ -35,9 +46,7 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) {
if (compilersArtefacts['__last']) return compilersArtefacts.getAllContractDatas() if (compilersArtefacts['__last']) return compilersArtefacts.getAllContractDatas()
return null return null
}, },
resolveReceipt: function (tx, cb) { resolveReceipt: transactionReceiptResolver
transactionReceiptResolver.resolve(tx, cb)
}
} }
}) })
...@@ -45,11 +54,7 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) { ...@@ -45,11 +54,7 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) {
blockchain.startListening(txlistener) blockchain.startListening(txlistener)
const eventsDecoder = new EventsDecoder({ const eventsDecoder = new EventsDecoder({
api: { resolveReceipt: transactionReceiptResolver
resolveReceipt: function (tx, cb) {
transactionReceiptResolver.resolve(tx, cb)
}
}
}) })
txlistener.startListening() txlistener.startListening()
registry.put({api: eventsDecoder, name: 'eventsDecoder'}) registry.put({api: eventsDecoder, name: 'eventsDecoder'})
......
'use strict'
module.exports = class TransactionReceiptResolver {
constructor (blockchain) {
this._transactionReceipts = {}
this.blockchain = blockchain
}
resolve (tx, cb) {
if (this._transactionReceipts[tx.hash]) {
return cb(null, this._transactionReceipts[tx.hash])
}
this.blockchain.web3().eth.getTransactionReceipt(tx.hash, (error, receipt) => {
if (!error) {
this._transactionReceipts[tx.hash] = receipt
cb(null, receipt)
} else {
cb(error)
}
})
}
}
...@@ -33,7 +33,7 @@ function Ethdebugger (opts) { ...@@ -33,7 +33,7 @@ function Ethdebugger (opts) {
this.traceManager = new TraceManager({web3: this.web3}) this.traceManager = new TraceManager({web3: this.web3})
this.codeManager = new CodeManager(this.traceManager) this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager) this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)})
this.storageResolver = null this.storageResolver = null
this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true }) this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
...@@ -42,10 +42,11 @@ function Ethdebugger (opts) { ...@@ -42,10 +42,11 @@ function Ethdebugger (opts) {
Ethdebugger.prototype.setManagers = function () { Ethdebugger.prototype.setManagers = function () {
this.traceManager = new TraceManager({web3: this.web3}) this.traceManager = new TraceManager({web3: this.web3})
this.codeManager = new CodeManager(this.traceManager) this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager) this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)})
this.storageResolver = null this.storageResolver = null
this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true }) this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
this.event.trigger('managersChanged')
} }
Ethdebugger.prototype.resolveStep = function (index) { Ethdebugger.prototype.resolveStep = function (index) {
......
...@@ -15,13 +15,20 @@ class BreakpointManager { ...@@ -15,13 +15,20 @@ class BreakpointManager {
* @param {Object} _debugger - type of EthDebugger * @param {Object} _debugger - type of EthDebugger
* @return {Function} _locationToRowConverter - function implemented by editor which return a column/line position for a char source location * @return {Function} _locationToRowConverter - function implemented by editor which return a column/line position for a char source location
*/ */
constructor (_debugger, _locationToRowConverter, _jumpToCallback) { constructor ({traceManager, callTree, solidityProxy, locationToRowConverter}) {
this.event = new EventManager() this.event = new EventManager()
this.debugger = _debugger this.traceManager = traceManager
this.callTree = callTree
this.solidityProxy = solidityProxy
this.breakpoints = {} this.breakpoints = {}
this.locationToRowConverter = _locationToRowConverter this.locationToRowConverter = locationToRowConverter
this.previousLine this.previousLine
this.jumpToCallback = _jumpToCallback || (() => {}) // eslint-disable-line }
setManagers({traceManager, callTree, solidityProxy}) {
this.traceManager = traceManager
this.callTree = callTree
this.solidityProxy = solidityProxy
} }
/** /**
...@@ -30,7 +37,10 @@ class BreakpointManager { ...@@ -30,7 +37,10 @@ class BreakpointManager {
* *
*/ */
async jumpNextBreakpoint (fromStep, defaultToLimit) { async jumpNextBreakpoint (fromStep, defaultToLimit) {
this.jump(fromStep || 0, 1, defaultToLimit) if (!this.locationToRowConverter) {
return console.log('row converter not provided')
}
this.jump(fromStep || 0, 1, defaultToLimit, this.traceManager.trace)
} }
/** /**
...@@ -39,7 +49,29 @@ class BreakpointManager { ...@@ -39,7 +49,29 @@ class BreakpointManager {
* *
*/ */
async jumpPreviousBreakpoint (fromStep, defaultToLimit) { async jumpPreviousBreakpoint (fromStep, defaultToLimit) {
this.jump(fromStep || 0, -1, defaultToLimit) if (!this.locationToRowConverter) {
return console.log('row converter not provided')
}
this.jump(fromStep || 0, -1, defaultToLimit, this.traceManager.trace)
}
depthChange (step, trace) {
return trace[step].depth !== trace[step - 1].depth
}
hitLine(currentStep, sourceLocation, previousSourceLocation, trace) {
// isJumpDestInstruction -> returning from a internal function call
// depthChange -> returning from an external call
// sourceLocation.start <= previousSourceLocation.start && ... -> previous src is contained in the current one
if ((helper.isJumpDestInstruction(trace[currentStep]) && previousSourceLocation.jump === 'o') ||
this.depthChange(currentStep, trace) ||
(sourceLocation.start <= previousSourceLocation.start &&
sourceLocation.start + sourceLocation.length >= previousSourceLocation.start + previousSourceLocation.length)) {
return false
}
this.event.trigger('breakpointStep', [currentStep])
this.event.trigger('breakpointHit', [sourceLocation, currentStep])
return true
} }
/** /**
...@@ -48,55 +80,30 @@ class BreakpointManager { ...@@ -48,55 +80,30 @@ class BreakpointManager {
* @param {Bool} defaultToLimit - if true jump to the limit (end if direction is 1, beginning if direction is -1) of the trace if no more breakpoint found * @param {Bool} defaultToLimit - if true jump to the limit (end if direction is 1, beginning if direction is -1) of the trace if no more breakpoint found
* *
*/ */
async jump (fromStep, direction, defaultToLimit) { async jump (fromStep, direction, defaultToLimit, trace) {
if (!this.locationToRowConverter) {
console.log('row converter not provided')
return
}
function depthChange (step, trace) {
return trace[step].depth !== trace[step - 1].depth
}
function hitLine (currentStep, sourceLocation, previousSourceLocation, self) {
// isJumpDestInstruction -> returning from a internal function call
// depthChange -> returning from an external call
// sourceLocation.start <= previousSourceLocation.start && ... -> previous src is contained in the current one
if ((helper.isJumpDestInstruction(self.debugger.traceManager.trace[currentStep]) && previousSourceLocation.jump === 'o') ||
depthChange(currentStep, self.debugger.traceManager.trace) ||
(sourceLocation.start <= previousSourceLocation.start &&
sourceLocation.start + sourceLocation.length >= previousSourceLocation.start + previousSourceLocation.length)) {
return false
}
self.jumpToCallback(currentStep)
self.event.trigger('breakpointHit', [sourceLocation, currentStep])
return true
}
let sourceLocation let sourceLocation
let previousSourceLocation let previousSourceLocation
let currentStep = fromStep + direction let currentStep = fromStep + direction
let lineHadBreakpoint = false let lineHadBreakpoint = false
while (currentStep > 0 && currentStep < this.debugger.traceManager.trace.length) { while (currentStep > 0 && currentStep < trace.length) {
try { try {
previousSourceLocation = sourceLocation previousSourceLocation = sourceLocation
sourceLocation = await this.debugger.callTree.extractValidSourceLocation(currentStep) sourceLocation = await this.callTree.extractValidSourceLocation(currentStep)
} catch (e) { } catch (e) {
console.log('cannot jump to breakpoint ' + e) return console.log('cannot jump to breakpoint ' + e)
return
} }
let lineColumn = await this.locationToRowConverter(sourceLocation) let lineColumn = await this.locationToRowConverter(sourceLocation)
if (this.previousLine !== lineColumn.start.line) { if (this.previousLine !== lineColumn.start.line) {
if (direction === -1 && lineHadBreakpoint) { // TODO : improve this when we will build the correct structure before hand if (direction === -1 && lineHadBreakpoint) { // TODO : improve this when we will build the correct structure before hand
lineHadBreakpoint = false lineHadBreakpoint = false
if (hitLine(currentStep + 1, previousSourceLocation, sourceLocation, this)) { if (this.hitLine(currentStep + 1, previousSourceLocation, sourceLocation, trace)) {
return return
} }
} }
this.previousLine = lineColumn.start.line this.previousLine = lineColumn.start.line
if (this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line)) { if (this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line)) {
lineHadBreakpoint = true lineHadBreakpoint = true
if (direction === 1 && hitLine(currentStep, sourceLocation, previousSourceLocation, this)) { if (direction === 1 && this.hitLine(currentStep, sourceLocation, previousSourceLocation, trace)) {
return return
} }
} }
...@@ -108,9 +115,9 @@ class BreakpointManager { ...@@ -108,9 +115,9 @@ class BreakpointManager {
return return
} }
if (direction === -1) { if (direction === -1) {
this.jumpToCallback(0) this.event.trigger('breakpointStep', [0])
} else if (direction === 1) { } else if (direction === 1) {
this.jumpToCallback(this.debugger.traceManager.trace.length - 1) this.event.trigger('breakpointStep', [trace.length - 1])
} }
} }
...@@ -122,7 +129,7 @@ class BreakpointManager { ...@@ -122,7 +129,7 @@ class BreakpointManager {
* @return {Bool} return true if the given @arg fileIndex @arg line refers to a breakpoint * @return {Bool} return true if the given @arg fileIndex @arg line refers to a breakpoint
*/ */
hasBreakpointAtLine (fileIndex, line) { hasBreakpointAtLine (fileIndex, line) {
const filename = this.debugger.solidityProxy.fileNameFromIndex(fileIndex) const filename = this.solidityProxy.fileNameFromIndex(fileIndex)
if (!(filename && this.breakpoints[filename])) { if (!(filename && this.breakpoints[filename])) {
return false return false
} }
......
...@@ -16,7 +16,16 @@ function CodeManager (_traceManager) { ...@@ -16,7 +16,16 @@ function CodeManager (_traceManager) {
this.event = new EventManager() this.event = new EventManager()
this.isLoading = false this.isLoading = false
this.traceManager = _traceManager this.traceManager = _traceManager
this.codeResolver = new CodeResolver({web3: this.traceManager.web3}) this.codeResolver = new CodeResolver({getCode: async (address) => {
return new Promise((resolve, reject) => {
this.traceManager.web3.eth.getCode(address, (error, code) => {
if (error) {
return reject(error)
}
return resolve(code)
})
})
}})
} }
/** /**
......
'use strict' 'use strict'
const codeUtils = require('./codeUtils') const codeUtils = require('./codeUtils')
function CodeResolver (options) { function CodeResolver ({getCode}) {
this.web3 = options.web3 this.getCode = getCode
this.bytecodeByAddress = {} // bytes code by contract addesses this.bytecodeByAddress = {} // bytes code by contract addesses
this.instructionsByAddress = {} // assembly items instructions list by contract addesses this.instructionsByAddress = {} // assembly items instructions list by contract addesses
...@@ -16,20 +16,13 @@ CodeResolver.prototype.clear = function () { ...@@ -16,20 +16,13 @@ CodeResolver.prototype.clear = function () {
} }
CodeResolver.prototype.resolveCode = async function (address) { CodeResolver.prototype.resolveCode = async function (address) {
return new Promise((resolve, reject) => { const cache = this.getExecutingCodeFromCache(address)
const cache = this.getExecutingCodeFromCache(address) if (cache) {
if (cache) { return cache
return resolve(cache) }
}
this.web3.eth.getCode(address, (error, code) => { const code = await this.getCode(address)
if (error) { return this.cacheExecutingCode(address, code)
// return console.log(error)
return reject(error)
}
return resolve(this.cacheExecutingCode(address, code))
})
})
} }
CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) { CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) {
...@@ -41,11 +34,8 @@ CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) { ...@@ -41,11 +34,8 @@ CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) {
} }
CodeResolver.prototype.formatCode = function (hexCode) { CodeResolver.prototype.formatCode = function (hexCode) {
const code = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex')) const [code, instructionsIndexByBytesOffset] = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex'))
return { return {code, instructionsIndexByBytesOffset}
code: code[0],
instructionsIndexByBytesOffset: code[1]
}
} }
CodeResolver.prototype.getExecutingCodeFromCache = function (address) { CodeResolver.prototype.getExecutingCodeFromCache = function (address) {
......
...@@ -21,12 +21,20 @@ function Debugger (options) { ...@@ -21,12 +21,20 @@ function Debugger (options) {
compilationResult: this.compilationResult compilationResult: this.compilationResult
}) })
this.breakPointManager = new BreakpointManager(this.debugger, async (sourceLocation) => { const {traceManager, callTree, solidityProxy} = this.debugger
this.breakPointManager = new BreakpointManager({traceManager, callTree, solidityProxy, locationToRowConverter: async (sourceLocation) => {
const compilationResult = await this.compilationResult() const compilationResult = await this.compilationResult()
if (!compilationResult) return { start: null, end: null } if (!compilationResult) return { start: null, end: null }
return this.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, compilationResult.source.sources, compilationResult.data.sources) return this.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, compilationResult.source.sources, compilationResult.data.sources)
}, (step) => { }})
this.event.trigger('breakpointStep', [step])
this.breakPointManager.event.register('managersChanged', () => {
const {traceManager, callTree, solidityProxy} = this.debugger
this.breakPointManager.setManagers({traceManager, callTree, solidityProxy})
})
this.breakPointManager.event.register('breakpointStep', (step) => {
this.step_manager.jumpTo(step)
}) })
this.debugger.setBreakpointManager(this.breakPointManager) this.debugger.setBreakpointManager(this.breakPointManager)
...@@ -38,10 +46,6 @@ function Debugger (options) { ...@@ -38,10 +46,6 @@ function Debugger (options) {
this.debugger.event.register('traceUnloaded', this, () => { this.debugger.event.register('traceUnloaded', this, () => {
this.event.trigger('debuggerStatus', [false]) this.event.trigger('debuggerStatus', [false])
}) })
this.event.register('breakpointStep', (step) => {
this.step_manager.jumpTo(step)
})
} }
Debugger.prototype.registerAndHighlightCodeItem = async function (index) { Debugger.prototype.registerAndHighlightCodeItem = async function (index) {
......
...@@ -369,8 +369,8 @@ function computeOffsets (types, stateDefinitions, contractName, location) { ...@@ -369,8 +369,8 @@ function computeOffsets (types, stateDefinitions, contractName, location) {
} }
module.exports = { module.exports = {
parseType: parseType, parseType,
computeOffsets: computeOffsets, computeOffsets,
Uint: uint, Uint: uint,
Address: address, Address: address,
Bool: bool, Bool: bool,
......
...@@ -3,9 +3,4 @@ const stateDecoder = require('./stateDecoder') ...@@ -3,9 +3,4 @@ const stateDecoder = require('./stateDecoder')
const localDecoder = require('./localDecoder') const localDecoder = require('./localDecoder')
const InternalCallTree = require('./internalCallTree') const InternalCallTree = require('./internalCallTree')
module.exports = { module.exports = {SolidityProxy, stateDecoder, localDecoder, InternalCallTree}
SolidityProxy: SolidityProxy,
stateDecoder: stateDecoder,
localDecoder: localDecoder,
InternalCallTree: InternalCallTree
}
...@@ -35,6 +35,4 @@ function formatMemory (memory) { ...@@ -35,6 +35,4 @@ function formatMemory (memory) {
return memory return memory
} }
module.exports = { module.exports = {solidityLocals}
solidityLocals: solidityLocals
}
...@@ -6,11 +6,11 @@ const astHelper = require('./astHelper') ...@@ -6,11 +6,11 @@ const astHelper = require('./astHelper')
const util = remixLib.util const util = remixLib.util
class SolidityProxy { class SolidityProxy {
constructor (traceManager, codeManager) { constructor ({getCurrentCalledAddressAt, getCode}) {
this.cache = new Cache() this.cache = new Cache()
this.reset({}) this.reset({})
this.traceManager = traceManager this.getCurrentCalledAddressAt = getCurrentCalledAddressAt
this.codeManager = codeManager this.getCode = getCode
} }
/** /**
...@@ -40,11 +40,11 @@ class SolidityProxy { ...@@ -40,11 +40,11 @@ class SolidityProxy {
* @param {Function} cb - callback returns (error, contractName) * @param {Function} cb - callback returns (error, contractName)
*/ */
async contractNameAt (vmTraceIndex) { async contractNameAt (vmTraceIndex) {
const address = this.traceManager.getCurrentCalledAddressAt(vmTraceIndex) const address = this.getCurrentCalledAddressAt(vmTraceIndex)
if (this.cache.contractNameByAddress[address]) { if (this.cache.contractNameByAddress[address]) {
return this.cache.contractNameByAddress[address] return this.cache.contractNameByAddress[address]
} }
const code = await this.codeManager.getCode(address) const code = await this.getCode(address)
const contractName = contractNameFromCode(this.contracts, code.bytecode, address) const contractName = contractNameFromCode(this.contracts, code.bytecode, address)
this.cache.contractNameByAddress[address] = contractName this.cache.contractNameByAddress[address] = contractName
return contractName return contractName
......
const astHelper = require('./astHelper') const astHelper = require('./astHelper')
const decodeInfo = require('./decodeInfo') const {computeOffsets} = require('./decodeInfo')
/** /**
* decode the contract state storage * decode the contract state storage
...@@ -40,7 +40,7 @@ function extractStateVariables (contractName, sourcesList) { ...@@ -40,7 +40,7 @@ function extractStateVariables (contractName, sourcesList) {
return [] return []
} }
const types = states[contractName].stateVariables const types = states[contractName].stateVariables
const offsets = decodeInfo.computeOffsets(types, states, contractName, 'storage') const offsets = computeOffsets(types, states, contractName, 'storage')
if (!offsets) { if (!offsets) {
return [] // TODO should maybe return an error return [] // TODO should maybe return an error
} }
...@@ -64,8 +64,4 @@ async function solidityState (storageResolver, astList, contractName) { ...@@ -64,8 +64,4 @@ async function solidityState (storageResolver, astList, contractName) {
} }
} }
module.exports = { module.exports = {solidityState, extractStateVariables, decodeState}
solidityState: solidityState,
extractStateVariables: extractStateVariables,
decodeState: decodeState
}
...@@ -10,9 +10,8 @@ class Address extends ValueType { ...@@ -10,9 +10,8 @@ class Address extends ValueType {
decodeValue (value) { decodeValue (value) {
if (!value) { if (!value) {
return '0x0000000000000000000000000000000000000000' return '0x0000000000000000000000000000000000000000'
} else {
return '0x' + util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase()
} }
return '0x' + util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase()
} }
} }
......
...@@ -69,11 +69,7 @@ class ArrayType extends RefType { ...@@ -69,11 +69,7 @@ class ArrayType extends RefType {
currentLocation.offset = 0 currentLocation.offset = 0
} }
} }
return { return {value: ret, length: '0x' + size.toString(16), type: this.typeName}
value: ret,
length: '0x' + size.toString(16),
type: this.typeName
}
} }
decodeFromMemoryInternal (offset, memory) { decodeFromMemoryInternal (offset, memory) {
...@@ -89,11 +85,7 @@ class ArrayType extends RefType { ...@@ -89,11 +85,7 @@ class ArrayType extends RefType {
ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory)) ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory))
offset += 32 offset += 32
} }
return { return {value: ret, length: '0x' + length.toString(16), type: this.typeName}
value: ret,
length: '0x' + length.toString(16),
type: this.typeName
}
} }
} }
......
...@@ -16,10 +16,7 @@ class DynamicByteArray extends RefType { ...@@ -16,10 +16,7 @@ class DynamicByteArray extends RefType {
value = await util.extractHexValue(location, storageResolver, this.storageBytes) value = await util.extractHexValue(location, storageResolver, this.storageBytes)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {value: '<decoding failed - ' + e.message + '>', type: this.typeName}
value: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
} }
const bn = new BN(value, 16) const bn = new BN(value, 16)
if (bn.testn(0)) { if (bn.testn(0)) {
...@@ -31,10 +28,7 @@ class DynamicByteArray extends RefType { ...@@ -31,10 +28,7 @@ class DynamicByteArray extends RefType {
currentSlot = await util.readFromStorage(dataPos, storageResolver) currentSlot = await util.readFromStorage(dataPos, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {value: '<decoding failed - ' + e.message + '>', type: this.typeName}
value: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
} }
while (length.gt(ret.length) && ret.length < 32000) { while (length.gt(ret.length) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '') currentSlot = currentSlot.replace('0x', '')
...@@ -44,24 +38,13 @@ class DynamicByteArray extends RefType { ...@@ -44,24 +38,13 @@ class DynamicByteArray extends RefType {
currentSlot = await util.readFromStorage(dataPos, storageResolver) currentSlot = await util.readFromStorage(dataPos, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {value: '<decoding failed - ' + e.message + '>', type: this.typeName}
value: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
} }
} }
return { return {value: '0x' + ret.replace(/(00)+$/, ''), length: '0x' + length.toString(16), type: this.typeName}
value: '0x' + ret.replace(/(00)+$/, ''),
length: '0x' + length.toString(16),
type: this.typeName
}
} else { } else {
var size = parseInt(value.substr(value.length - 2, 2), 16) / 2 var size = parseInt(value.substr(value.length - 2, 2), 16) / 2
return { return {value: '0x' + value.substr(0, size * 2), length: '0x' + size.toString(16), type: this.typeName}
value: '0x' + value.substr(0, size * 2),
length: '0x' + size.toString(16),
type: this.typeName
}
} }
} }
...@@ -69,11 +52,7 @@ class DynamicByteArray extends RefType { ...@@ -69,11 +52,7 @@ class DynamicByteArray extends RefType {
offset = 2 * offset offset = 2 * offset
let length = memory.substr(offset, 64) let length = memory.substr(offset, 64)
length = 2 * parseInt(length, 16) length = 2 * parseInt(length, 16)
return { return {length: '0x' + length.toString(16), value: '0x' + memory.substr(offset + 64, length), type: this.typeName}
length: '0x' + length.toString(16),
value: '0x' + memory.substr(offset + 64, length),
type: this.typeName
}
} }
} }
......
...@@ -28,20 +28,13 @@ class Mapping extends RefType { ...@@ -28,20 +28,13 @@ class Mapping extends RefType {
const mappingPreimages = await storageResolver.mappingsLocation(corrections) const mappingPreimages = await storageResolver.mappingsLocation(corrections)
let ret = await this.decodeMappingsLocation(mappingPreimages, location, storageResolver) // fetch mapping storage changes let ret = await this.decodeMappingsLocation(mappingPreimages, location, storageResolver) // fetch mapping storage changes
ret = Object.assign({}, this.initialDecodedState, ret) // merge changes ret = Object.assign({}, this.initialDecodedState, ret) // merge changes
return { return {value: ret, type: this.typeName}
value: ret,
type: this.typeName
}
} }
decodeFromMemoryInternal (offset, memory) { decodeFromMemoryInternal (offset, memory) {
// mappings can only exist in storage and not in memory // mappings can only exist in storage and not in memory
// so this should never be called // so this should never be called
return { return {value: '<not implemented>', length: '0x', type: this.typeName}
value: '<not implemented>',
length: '0x',
type: this.typeName
}
} }
async decodeMappingsLocation (preimages, location, storageResolver) { async decodeMappingsLocation (preimages, location, storageResolver) {
......
...@@ -21,10 +21,7 @@ class RefType { ...@@ -21,10 +21,7 @@ class RefType {
*/ */
async decodeFromStack (stackDepth, stack, memory, storageResolver) { async decodeFromStack (stackDepth, stack, memory, storageResolver) {
if (stack.length - 1 < stackDepth) { if (stack.length - 1 < stackDepth) {
return { return {error: '<decoding failed - stack underflow ' + stackDepth + '>', type: this.typeName}
error: '<decoding failed - stack underflow ' + stackDepth + '>',
type: this.typeName
}
} }
let offset = stack[stack.length - 1 - stackDepth] let offset = stack[stack.length - 1 - stackDepth]
if (this.isInStorage()) { if (this.isInStorage()) {
...@@ -33,19 +30,13 @@ class RefType { ...@@ -33,19 +30,13 @@ class RefType {
return await this.decodeFromStorage({ offset: 0, slot: offset }, storageResolver) return await this.decodeFromStorage({ offset: 0, slot: offset }, storageResolver)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {error: '<decoding failed - ' + e.message + '>', type: this.typeName}
error: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
} }
} else if (this.isInMemory()) { } else if (this.isInMemory()) {
offset = parseInt(offset, 16) offset = parseInt(offset, 16)
return this.decodeFromMemoryInternal(offset, memory) return this.decodeFromMemoryInternal(offset, memory)
} else { } else {
return { return {error: '<decoding failed - no decoder for ' + this.location + '>', type: this.typeName}
error: '<decoding failed - no decoder for ' + this.location + '>',
type: this.typeName
}
} }
} }
......
...@@ -39,11 +39,7 @@ function format (decoded) { ...@@ -39,11 +39,7 @@ function format (decoded) {
} }
let value = decoded.value let value = decoded.value
value = value.replace('0x', '').replace(/(..)/g, '%$1') value = value.replace('0x', '').replace(/(..)/g, '%$1')
const ret = { const ret = {length: decoded.length, raw: decoded.value, type: 'string'}
length: decoded.length,
raw: decoded.value,
type: 'string'
}
try { try {
ret.value = decodeURIComponent(value) ret.value = decodeURIComponent(value)
} catch (e) { } catch (e) {
......
...@@ -22,10 +22,7 @@ class Struct extends RefType { ...@@ -22,10 +22,7 @@ class Struct extends RefType {
ret[item.name] = '<decoding failed - ' + e.message + '>' ret[item.name] = '<decoding failed - ' + e.message + '>'
} }
} }
return { return {value: ret, type: this.typeName}
value: ret,
type: this.typeName
}
} }
decodeFromMemoryInternal (offset, memory) { decodeFromMemoryInternal (offset, memory) {
...@@ -36,10 +33,7 @@ class Struct extends RefType { ...@@ -36,10 +33,7 @@ class Struct extends RefType {
ret[item.name] = member ret[item.name] = member
offset += 32 offset += 32
}) })
return { return {value: ret, type: this.typeName}
value: ret,
type: this.typeName
}
} }
} }
......
...@@ -19,16 +19,10 @@ class ValueType { ...@@ -19,16 +19,10 @@ class ValueType {
async decodeFromStorage (location, storageResolver) { async decodeFromStorage (location, storageResolver) {
try { try {
var value = await util.extractHexValue(location, storageResolver, this.storageBytes) var value = await util.extractHexValue(location, storageResolver, this.storageBytes)
return { return {value: this.decodeValue(value), type: this.typeName}
value: this.decodeValue(value),
type: this.typeName
}
} catch (e) { } catch (e) {
console.log(e) console.log(e)
return { return {value: '<decoding failed - ' + e.message + '>', type: this.typeName}
value: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
} }
} }
...@@ -47,10 +41,7 @@ class ValueType { ...@@ -47,10 +41,7 @@ class ValueType {
} else { } else {
value = this.decodeValue(stack[stack.length - 1 - stackDepth].replace('0x', '')) value = this.decodeValue(stack[stack.length - 1 - stackDepth].replace('0x', ''))
} }
return { return {value, type: this.typeName}
value: value,
type: this.typeName
}
} }
/** /**
...@@ -62,10 +53,7 @@ class ValueType { ...@@ -62,10 +53,7 @@ class ValueType {
*/ */
decodeFromMemory (offset, memory) { decodeFromMemory (offset, memory) {
let value = memory.substr(2 * offset, 64) let value = memory.substr(2 * offset, 64)
return { return {value: this.decodeValue(value), type: this.typeName}
value: this.decodeValue(value),
type: this.typeName
}
} }
} }
......
...@@ -2,20 +2,6 @@ ...@@ -2,20 +2,6 @@
const ethutil = require('ethereumjs-util') const ethutil = require('ethereumjs-util')
const BN = require('ethereumjs-util').BN const BN = require('ethereumjs-util').BN
module.exports = {
readFromStorage: readFromStorage,
decodeIntFromHex: decodeIntFromHex,
extractHexValue: extractHexValue,
extractHexByteSlice: extractHexByteSlice,
toBN: toBN,
add: add,
sub: sub,
extractLocation: extractLocation,
removeLocation: removeLocation,
normalizeHex: normalizeHex,
extractLocationFromAstVariable: extractLocationFromAstVariable
}
function decodeIntFromHex (value, byteLength, signed) { function decodeIntFromHex (value, byteLength, signed) {
let bigNumber = new BN(value, 16) let bigNumber = new BN(value, 16)
if (signed) { if (signed) {
...@@ -24,21 +10,17 @@ function decodeIntFromHex (value, byteLength, signed) { ...@@ -24,21 +10,17 @@ function decodeIntFromHex (value, byteLength, signed) {
return bigNumber.toString(10) return bigNumber.toString(10)
} }
function readFromStorage (slot, storageResolver) { function readFromStorage(slot, storageResolver) {
const hexSlot = '0x' + normalizeHex(ethutil.bufferToHex(slot)) const hexSlot = '0x' + normalizeHex(ethutil.bufferToHex(slot))
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
storageResolver.storageSlot(hexSlot, (error, slot) => { storageResolver.storageSlot(hexSlot, (error, slot) => {
if (error) { if (error) {
return reject(error) return reject(error)
} else {
if (!slot) {
slot = {
key: slot,
value: ''
}
}
return resolve(normalizeHex(slot.value))
} }
if (!slot) {
slot = { key: slot, value: '' }
}
return resolve(normalizeHex(slot.value))
}) })
}) })
} }
...@@ -120,3 +102,5 @@ function normalizeHex (hex) { ...@@ -120,3 +102,5 @@ function normalizeHex (hex) {
} }
return hex return hex
} }
module.exports = {readFromStorage, decodeIntFromHex, extractHexValue, extractHexByteSlice, toBN, add, sub, extractLocation, removeLocation, normalizeHex, extractLocationFromAstVariable}
\ No newline at end of file
...@@ -88,10 +88,9 @@ function extractSourceMap (self, codeManager, address, contracts) { ...@@ -88,10 +88,9 @@ function extractSourceMap (self, codeManager, address, contracts) {
const sourceMap = getSourceMap(address, result.bytecode, contracts) const sourceMap = getSourceMap(address, result.bytecode, contracts)
if (sourceMap) { if (sourceMap) {
if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap
resolve(sourceMap) return resolve(sourceMap)
} else {
reject('no sourcemap associated with the code ' + address)
} }
reject('no sourcemap associated with the code ' + address)
}).catch(reject) }).catch(reject)
}) })
} }
......
...@@ -94,12 +94,8 @@ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocat ...@@ -94,12 +94,8 @@ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocat
start: convertFromCharPosition(sourceLocation.start, lineBreakPositions), start: convertFromCharPosition(sourceLocation.start, lineBreakPositions),
end: convertFromCharPosition(sourceLocation.start + sourceLocation.length, lineBreakPositions) end: convertFromCharPosition(sourceLocation.start + sourceLocation.length, lineBreakPositions)
} }
} else {
return {
start: null,
end: null
}
} }
return {start: null, end: null}
} }
/** /**
...@@ -119,10 +115,7 @@ function convertFromCharPosition (pos, lineBreakPositions) { ...@@ -119,10 +115,7 @@ function convertFromCharPosition (pos, lineBreakPositions) {
} }
const beginColumn = line === 0 ? 0 : (lineBreakPositions[line - 1] + 1) const beginColumn = line === 0 ? 0 : (lineBreakPositions[line - 1] + 1)
const column = pos - beginColumn const column = pos - beginColumn
return { return {line, column}
line: line,
column: column
}
} }
function sourceLocationFromAstNode (astNode) { function sourceLocationFromAstNode (astNode) {
......
...@@ -51,10 +51,9 @@ function getPreimage (web3, key) { ...@@ -51,10 +51,9 @@ function getPreimage (web3, key) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
web3.debug.preimage(key.indexOf('0x') === 0 ? key : '0x' + key, (error, preimage) => { web3.debug.preimage(key.indexOf('0x') === 0 ? key : '0x' + key, (error, preimage) => {
if (error) { if (error) {
resolve(null) return resolve(null)
} else {
resolve(preimage)
} }
resolve(preimage)
}) })
}) })
} }
...@@ -273,8 +273,14 @@ function testDebugging (debugManager) { ...@@ -273,8 +273,14 @@ function testDebugging (debugManager) {
tape('breakPointManager', (t) => { tape('breakPointManager', (t) => {
t.plan(2) t.plan(2)
var sourceMappingDecoder = new SourceMappingDecoder() var sourceMappingDecoder = new SourceMappingDecoder()
var breakPointManager = new BreakpointManager(debugManager, (rawLocation) => { const {traceManager, callTree, solidityProxy} = debugManager
var breakPointManager = new BreakpointManager({traceManager, callTree, solidityProxy, locationToRowConverter: async (rawLocation) => {
return sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, sourceMappingDecoder.getLinebreakPositions(ballot)) return sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, sourceMappingDecoder.getLinebreakPositions(ballot))
}})
breakPointManager.event.register('managersChanged', () => {
const {traceManager, callTree, solidityProxy} = debugManager
breakPointManager.setManagers({traceManager, callTree, solidityProxy})
}) })
breakPointManager.add({fileName: 'test.sol', row: 38}) breakPointManager.add({fileName: 'test.sol', row: 38})
......
...@@ -25,13 +25,12 @@ function decodeLocal (st, index, traceManager, callTree, verifier) { ...@@ -25,13 +25,12 @@ function decodeLocal (st, index, traceManager, callTree, verifier) {
}], }],
index, index,
function (error, result) { function (error, result) {
if (!error) { if (error) {
localDecoder.solidityLocals(index, callTree, result[0].value, result[1].value, {}, {start: 5000}).then((locals) => { return st.fail(error)
verifier(locals)
})
} else {
st.fail(error)
} }
localDecoder.solidityLocals(index, callTree, result[0].value, result[1].value, {}, { start: 5000 }).then((locals) => {
verifier(locals)
})
}) })
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
......
...@@ -10,67 +10,65 @@ var TraceManager = require('../../../src/trace/traceManager') ...@@ -10,67 +10,65 @@ var TraceManager = require('../../../src/trace/traceManager')
var CodeManager = require('../../../src/code/codeManager') var CodeManager = require('../../../src/code/codeManager')
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) { module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) {
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, contractBytecode, function (error, txHash) { vmCall.sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, txHash) {
if (error) { if (error) {
st.fail(error) return st.fail(error)
} else { }
vm.web3.eth.getTransaction(txHash, function (error, tx) { vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
st.fail(error) return st.fail(error)
} else { }
tx.to = traceHelper.contractCreationToken('0') tx.to = traceHelper.contractCreationToken('0')
var traceManager = new TraceManager({web3: vm.web3}) var traceManager = new TraceManager({ web3: vm.web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy(traceManager, codeManager) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })
solidityProxy.reset(compilationResult) solidityProxy.reset(compilationResult)
var debuggerEvent = new EventManager() var debuggerEvent = new EventManager()
var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => { callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error) st.fail(error)
}) })
callTree.event.register('callTreeReady', (scopes, scopeStarts) => { callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 73, traceManager, callTree, function (locals) { helper.decodeLocals(st, 73, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['boolFalse'].value, false) st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'].value, true) st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'].value, 'three') st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB') st.equals(locals['sender'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
st.equals(locals['_bytes1'].value, '0x99') st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'].value, '0x99') st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'].value, '0x99AB') st.equals(locals['__bytes2'].value, '0x99AB')
st.equals(locals['__bytes4'].value, '0x99FA0000') st.equals(locals['__bytes4'].value, '0x99FA0000')
st.equals(locals['__bytes6'].value, '0x990000000000') st.equals(locals['__bytes6'].value, '0x990000000000')
st.equals(locals['__bytes7'].value, '0x99356700000000') st.equals(locals['__bytes7'].value, '0x99356700000000')
st.equals(locals['__bytes8'].value, '0x99ABD41700000000') st.equals(locals['__bytes8'].value, '0x99ABD41700000000')
st.equals(locals['__bytes9'].value, '0x99156744AF00000000') st.equals(locals['__bytes9'].value, '0x99156744AF00000000')
st.equals(locals['__bytes13'].value, '0x99123423425300000000000000') st.equals(locals['__bytes13'].value, '0x99123423425300000000000000')
st.equals(locals['__bytes16'].value, '0x99AFAD23432400000000000000000000') st.equals(locals['__bytes16'].value, '0x99AFAD23432400000000000000000000')
st.equals(locals['__bytes24'].value, '0x99AFAD234324000000000000000000000000000000000000') st.equals(locals['__bytes24'].value, '0x99AFAD234324000000000000000000000000000000000000')
st.equals(locals['__bytes32'].value, '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000') st.equals(locals['__bytes32'].value, '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000')
st.equals(Object.keys(locals).length, 16) st.equals(Object.keys(locals).length, 16)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }
}) })
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) { helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try { try {
// st.equals(Object.keys(locals).length, 0) // st.equals(Object.keys(locals).length, 0)
st.equals(0, 0) st.equals(0, 0)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }
cb() cb()
}) })
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
}
}) })
} traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
}) })
} }
...@@ -11,53 +11,51 @@ var TraceManager = require('../../../src/trace/traceManager') ...@@ -11,53 +11,51 @@ var TraceManager = require('../../../src/trace/traceManager')
var CodeManager = require('../../../src/code/codeManager') var CodeManager = require('../../../src/code/codeManager')
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) { module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) {
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, contractBytecode, function (error, txHash) { vmCall.sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, txHash) {
if (error) { if (error) {
st.fail(error) return st.fail(error)
} else { }
vm.web3.eth.getTransaction(txHash, function (error, tx) { vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
st.fail(error) return st.fail(error)
} else { }
tx.to = traceHelper.contractCreationToken('0') tx.to = traceHelper.contractCreationToken('0')
var traceManager = new TraceManager({web3: vm.web3}) var traceManager = new TraceManager({ web3: vm.web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy(traceManager, codeManager) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })
solidityProxy.reset(compilationResult) solidityProxy.reset(compilationResult)
var debuggerEvent = new EventManager() var debuggerEvent = new EventManager()
var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => { callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error) st.fail(error)
}) })
callTree.event.register('callTreeReady', (scopes, scopeStarts) => { callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 49, traceManager, callTree, function (locals) { helper.decodeLocals(st, 49, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['dynbytes'].value, '0x64796e616d69636279746573') st.equals(locals['dynbytes'].value, '0x64796e616d69636279746573')
st.equals(locals['smallstring'].value, 'test_test_test') st.equals(locals['smallstring'].value, 'test_test_test')
st.equals(Object.keys(locals).length, 2) st.equals(Object.keys(locals).length, 2)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }
}) })
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) { helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try { try {
// st.equals(Object.keys(locals).length, 0) // st.equals(Object.keys(locals).length, 0)
st.equals(0, 0) st.equals(0, 0)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }
cb() cb()
}) })
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
}
}) })
} traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
}) })
} }
...@@ -44,10 +44,7 @@ eventManager.prototype.register = function (eventName, obj, func) { ...@@ -44,10 +44,7 @@ eventManager.prototype.register = function (eventName, obj, func) {
func = obj func = obj
obj = this.anonymous obj = this.anonymous
} }
this.registered[eventName].push({ this.registered[eventName].push({obj, func})
obj: obj,
func: func
})
} }
/* /*
......
...@@ -7,8 +7,8 @@ const txHelper = require('./txHelper') ...@@ -7,8 +7,8 @@ const txHelper = require('./txHelper')
* *
*/ */
class EventsDecoder { class EventsDecoder {
constructor (opt = {}) { constructor ({resolveReceipt}) {
this._api = opt.api this.resolveReceipt = resolveReceipt
} }
/** /**
...@@ -20,7 +20,7 @@ class EventsDecoder { ...@@ -20,7 +20,7 @@ class EventsDecoder {
*/ */
parseLogs (tx, contractName, compiledContracts, cb) { parseLogs (tx, contractName, compiledContracts, cb) {
if (tx.isCall) return cb(null, { decoded: [], raw: [] }) if (tx.isCall) return cb(null, { decoded: [], raw: [] })
this._api.resolveReceipt(tx, (error, receipt) => { this.resolveReceipt(tx, (error, receipt) => {
if (error) return cb(error) if (error) return cb(error)
this._decodeLogs(tx, receipt, contractName, compiledContracts, cb) this._decodeLogs(tx, receipt, contractName, compiledContracts, cb)
}) })
......
...@@ -9,6 +9,16 @@ const defaultExecutionContext = require('./execution-context') ...@@ -9,6 +9,16 @@ const defaultExecutionContext = require('./execution-context')
const txFormat = require('./txFormat') const txFormat = require('./txFormat')
const txHelper = require('./txHelper') const txHelper = require('./txHelper')
function addExecutionCosts(txResult, tx) {
if (txResult && txResult.result) {
if (txResult.result.execResult) {
tx.returnValue = txResult.result.execResult.returnValue
if (txResult.result.execResult.gasUsed) tx.executionCost = txResult.result.execResult.gasUsed.toString(10)
}
if (txResult.result.gasUsed) tx.transactionCost = txResult.result.gasUsed.toString(10)
}
}
/** /**
* poll web3 each 2s if web3 * poll web3 each 2s if web3
* listen on transaction executed event if VM * listen on transaction executed event if VM
...@@ -80,16 +90,6 @@ class TxListener { ...@@ -80,16 +90,6 @@ class TxListener {
}) })
}) })
}) })
function addExecutionCosts (txResult, tx) {
if (txResult && txResult.result) {
if (txResult.result.execResult) {
tx.returnValue = txResult.result.execResult.returnValue
if (txResult.result.execResult.gasUsed) tx.executionCost = txResult.result.execResult.gasUsed.toString(10)
}
if (txResult.result.gasUsed) tx.transactionCost = txResult.result.gasUsed.toString(10)
}
}
} }
/** /**
......
...@@ -77,20 +77,19 @@ class TxRunner { ...@@ -77,20 +77,19 @@ class TxRunner {
} }
} }
execute (args, confirmationCb, gasEstimationForceSend, promptCb, callback) { execute(args, confirmationCb, gasEstimationForceSend, promptCb, callback) {
let data = args.data let data = args.data
if (data.slice(0, 2) !== '0x') { if (data.slice(0, 2) !== '0x') {
data = '0x' + data data = '0x' + data
} }
if (!this.executionContext.isVM()) { if (!this.executionContext.isVM()) {
this.runInNode(args.from, args.to, data, args.value, args.gasLimit, args.useCall, confirmationCb, gasEstimationForceSend, promptCb, callback) return this.runInNode(args.from, args.to, data, args.value, args.gasLimit, args.useCall, confirmationCb, gasEstimationForceSend, promptCb, callback)
} else { }
try { try {
this.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, args.timestamp, callback) this.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, args.timestamp, callback)
} catch (e) { } catch (e) {
callback(e, null) callback(e, null)
}
} }
} }
...@@ -228,9 +227,8 @@ async function tryTillReceiptAvailable (txhash, executionContext) { ...@@ -228,9 +227,8 @@ async function tryTillReceiptAvailable (txhash, executionContext) {
// Try again with a bit of delay if error or if result still null // Try again with a bit of delay if error or if result still null
await pause() await pause()
return resolve(await tryTillReceiptAvailable(txhash, executionContext)) return resolve(await tryTillReceiptAvailable(txhash, executionContext))
} else {
return resolve(receipt)
} }
return resolve(receipt)
}) })
}) })
} }
...@@ -242,29 +240,27 @@ async function tryTillTxAvailable (txhash, executionContext) { ...@@ -242,29 +240,27 @@ async function tryTillTxAvailable (txhash, executionContext) {
// Try again with a bit of delay if error or if result still null // Try again with a bit of delay if error or if result still null
await pause() await pause()
return resolve(await tryTillTxAvailable(txhash, executionContext)) return resolve(await tryTillTxAvailable(txhash, executionContext))
} else {
return resolve(tx)
} }
return resolve(tx)
}) })
}) })
} }
async function pause () { return new Promise((resolve, reject) => { setTimeout(resolve, 500) }) } async function pause () { return new Promise((resolve, reject) => { setTimeout(resolve, 500) }) }
function run (self, tx, stamp, confirmationCb, gasEstimationForceSend, promptCb, callback) { function run(self, tx, stamp, confirmationCb, gasEstimationForceSend, promptCb, callback) {
if (!self.runAsync && Object.keys(self.pendingTxs).length) { if (!self.runAsync && Object.keys(self.pendingTxs).length) {
self.queusTxs.push({ tx, stamp, callback }) return self.queusTxs.push({ tx, stamp, callback })
} else {
self.pendingTxs[stamp] = tx
self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, function(error, result) {
delete self.pendingTxs[stamp]
if (callback && typeof callback === 'function') callback(error, result)
if (self.queusTxs.length) {
const next = self.queusTxs.pop()
run(self, next.tx, next.stamp, next.callback)
}
})
} }
self.pendingTxs[stamp] = tx
self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, function (error, result) {
delete self.pendingTxs[stamp]
if (callback && typeof callback === 'function') callback(error, result)
if (self.queusTxs.length) {
const next = self.queusTxs.pop()
run(self, next.tx, next.stamp, next.callback)
}
})
} }
module.exports = TxRunner module.exports = TxRunner
...@@ -27,10 +27,8 @@ function Storage (prefix) { ...@@ -27,10 +27,8 @@ function Storage (prefix) {
this.remove = function (name) { this.remove = function (name) {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.localStorage.removeItem(prefix + name) window.localStorage.removeItem(prefix + name)
return true
} else {
return true
} }
return true
} }
this.rename = function (originalName, newName) { this.rename = function (originalName, newName) {
...@@ -46,9 +44,8 @@ function Storage (prefix) { ...@@ -46,9 +44,8 @@ function Storage (prefix) {
// NOTE: this is a workaround for some browsers // NOTE: this is a workaround for some browsers
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
return Object.keys(window.localStorage).filter(function (item) { return item !== null && item !== undefined }) return Object.keys(window.localStorage).filter(function (item) { return item !== null && item !== undefined })
} else {
return []
} }
return []
} }
this.keys = function () { this.keys = function () {
......
...@@ -91,17 +91,16 @@ module.exports = class UniversalDApp { ...@@ -91,17 +91,16 @@ module.exports = class UniversalDApp {
if (!this.config.get('settings/personal-mode')) { if (!this.config.get('settings/personal-mode')) {
return cb('Not running in personal mode') return cb('Not running in personal mode')
} }
passwordPromptCb((passphrase) => { return passwordPromptCb((passphrase) => {
this.executionContext.web3().personal.newAccount(passphrase, cb) this.executionContext.web3().personal.newAccount(passphrase, cb)
}) })
} else {
let privateKey
do {
privateKey = crypto.randomBytes(32)
} while (!isValidPrivate(privateKey))
this._addAccount(privateKey, '0x56BC75E2D63100000')
cb(null, '0x' + privateToAddress(privateKey).toString('hex'))
} }
let privateKey
do {
privateKey = crypto.randomBytes(32)
} while (!isValidPrivate(privateKey))
this._addAccount(privateKey, '0x56BC75E2D63100000')
cb(null, '0x' + privateToAddress(privateKey).toString('hex'))
} }
/** Add an account to the list of account (only for Javascript VM) */ /** Add an account to the list of account (only for Javascript VM) */
...@@ -110,22 +109,23 @@ module.exports = class UniversalDApp { ...@@ -110,22 +109,23 @@ module.exports = class UniversalDApp {
throw new Error('_addAccount() cannot be called in non-VM mode') throw new Error('_addAccount() cannot be called in non-VM mode')
} }
if (this.accounts) { if (!this.accounts) {
privateKey = Buffer.from(privateKey, 'hex') return
const address = privateToAddress(privateKey) }
privateKey = Buffer.from(privateKey, 'hex')
// FIXME: we don't care about the callback, but we should still make this proper const address = privateToAddress(privateKey)
let stateManager = this.executionContext.vm().stateManager
stateManager.getAccount(address, (error, account) => { // FIXME: we don't care about the callback, but we should still make this proper
if (error) return console.log(error) let stateManager = this.executionContext.vm().stateManager
account.balance = balance || '0xf00000000000000001' stateManager.getAccount(address, (error, account) => {
stateManager.putAccount(address, account, function cb (error) { if (error) return console.log(error)
if (error) console.log(error) account.balance = balance || '0xf00000000000000001'
}) stateManager.putAccount(address, account, function cb(error) {
if (error) console.log(error)
}) })
})
this.accounts[toChecksumAddress('0x' + address.toString('hex'))] = { privateKey, nonce: 0 } this.accounts[toChecksumAddress('0x' + address.toString('hex'))] = { privateKey, nonce: 0 }
}
} }
/** Return the list of accounts */ /** Return the list of accounts */
...@@ -171,40 +171,36 @@ module.exports = class UniversalDApp { ...@@ -171,40 +171,36 @@ module.exports = class UniversalDApp {
} }
/** Get the balance of an address */ /** Get the balance of an address */
getBalance (address, cb) { getBalance(address, cb) {
address = stripHexPrefix(address) address = stripHexPrefix(address)
if (!this.executionContext.isVM()) { if (!this.executionContext.isVM()) {
this.executionContext.web3().eth.getBalance(address, (err, res) => { return this.executionContext.web3().eth.getBalance(address, (err, res) => {
if (err) {
cb(err)
} else {
cb(null, res.toString(10))
}
})
} else {
if (!this.accounts) {
return cb('No accounts?')
}
this.executionContext.vm().stateManager.getAccount(Buffer.from(address, 'hex'), (err, res) => {
if (err) { if (err) {
cb('Account not found') return cb(err)
} else {
cb(null, new BN(res.balance).toString(10))
} }
cb(null, res.toString(10))
}) })
} }
if (!this.accounts) {
return cb('No accounts?')
}
this.executionContext.vm().stateManager.getAccount(Buffer.from(address, 'hex'), (err, res) => {
if (err) {
return cb('Account not found')
}
cb(null, new BN(res.balance).toString(10))
})
} }
/** Get the balance of an address, and convert wei to ether */ /** Get the balance of an address, and convert wei to ether */
getBalanceInEther (address, callback) { getBalanceInEther (address, callback) {
this.getBalance(address, (error, balance) => { this.getBalance(address, (error, balance) => {
if (error) { if (error) {
callback(error) return callback(error)
} else {
callback(null, this.executionContext.web3().utils.fromWei(balance, 'ether'))
} }
callback(null, this.executionContext.web3().utils.fromWei(balance, 'ether'))
}) })
} }
...@@ -219,10 +215,7 @@ module.exports = class UniversalDApp { ...@@ -219,10 +215,7 @@ module.exports = class UniversalDApp {
* @param {Function} callback - callback. * @param {Function} callback - callback.
*/ */
createContract (data, confirmationCb, continueCb, promptCb, callback) { createContract (data, confirmationCb, continueCb, promptCb, callback) {
this.runTx({data: data, useCall: false}, confirmationCb, continueCb, promptCb, (error, txResult) => { this.runTx({data: data, useCall: false}, confirmationCb, continueCb, promptCb, callback)
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback(error, txResult)
})
} }
/** /**
...@@ -235,10 +228,7 @@ module.exports = class UniversalDApp { ...@@ -235,10 +228,7 @@ module.exports = class UniversalDApp {
*/ */
callFunction (to, data, funAbi, confirmationCb, continueCb, promptCb, callback) { callFunction (to, data, funAbi, confirmationCb, continueCb, promptCb, callback) {
const useCall = funAbi.stateMutability === 'view' || funAbi.stateMutability === 'pure' const useCall = funAbi.stateMutability === 'view' || funAbi.stateMutability === 'pure'
this.runTx({to, data, useCall}, confirmationCb, continueCb, promptCb, (error, txResult) => { this.runTx({to, data, useCall}, confirmationCb, continueCb, promptCb, callback)
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback(error, txResult)
})
} }
/** /**
...@@ -249,10 +239,7 @@ module.exports = class UniversalDApp { ...@@ -249,10 +239,7 @@ module.exports = class UniversalDApp {
* @param {Function} callback - callback. * @param {Function} callback - callback.
*/ */
sendRawTransaction (to, data, confirmationCb, continueCb, promptCb, callback) { sendRawTransaction (to, data, confirmationCb, continueCb, promptCb, callback) {
this.runTx({to, data, useCall: false}, confirmationCb, continueCb, promptCb, (error, txResult) => { this.runTx({to, data, useCall: false}, confirmationCb, continueCb, promptCb, callback)
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback(error, txResult)
})
} }
context () { context () {
......
...@@ -19,10 +19,9 @@ Web3Providers.prototype.addProvider = function (type, obj) { ...@@ -19,10 +19,9 @@ Web3Providers.prototype.addProvider = function (type, obj) {
Web3Providers.prototype.get = function (type, cb) { Web3Providers.prototype.get = function (type, cb) {
if (this.modes[type]) { if (this.modes[type]) {
cb(null, this.modes[type]) return cb(null, this.modes[type])
} else {
cb('error: this provider has not been setup (' + type + ')', null)
} }
cb('error: this provider has not been setup (' + type + ')', null)
} }
Web3Providers.prototype.addWeb3 = function (type, web3) { Web3Providers.prototype.addWeb3 = function (type, web3) {
......
...@@ -211,10 +211,9 @@ web3VmProvider.prototype.traceTransaction = function (txHash, options, cb) { ...@@ -211,10 +211,9 @@ web3VmProvider.prototype.traceTransaction = function (txHash, options, cb) {
cb(null, this.vmTraces[txHash]) cb(null, this.vmTraces[txHash])
} }
return this.vmTraces[txHash] return this.vmTraces[txHash]
} else { }
if (cb) { if (cb) {
cb('unable to retrieve traces ' + txHash, null) cb('unable to retrieve traces ' + txHash, null)
}
} }
} }
...@@ -232,9 +231,8 @@ web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, addres ...@@ -232,9 +231,8 @@ web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, addres
storage: JSON.parse(JSON.stringify(storage)), storage: JSON.parse(JSON.stringify(storage)),
nextKey: null nextKey: null
}) })
} else {
cb('unable to retrieve storage ' + txIndex + ' ' + address)
} }
cb('unable to retrieve storage ' + txIndex + ' ' + address)
} }
web3VmProvider.prototype.getBlockNumber = function (cb) { cb(null, 'vm provider') } web3VmProvider.prototype.getBlockNumber = function (cb) { cb(null, 'vm provider') }
...@@ -245,10 +243,9 @@ web3VmProvider.prototype.getTransaction = function (txHash, cb) { ...@@ -245,10 +243,9 @@ web3VmProvider.prototype.getTransaction = function (txHash, cb) {
cb(null, this.txs[txHash]) cb(null, this.txs[txHash])
} }
return this.txs[txHash] return this.txs[txHash]
} else { }
if (cb) { if (cb) {
cb('unable to retrieve tx ' + txHash, null) cb('unable to retrieve tx ' + txHash, null)
}
} }
} }
...@@ -259,10 +256,9 @@ web3VmProvider.prototype.getTransactionReceipt = function (txHash, cb) { ...@@ -259,10 +256,9 @@ web3VmProvider.prototype.getTransactionReceipt = function (txHash, cb) {
cb(null, this.txsReceipt[txHash]) cb(null, this.txsReceipt[txHash])
} }
return this.txsReceipt[txHash] return this.txsReceipt[txHash]
} else { }
if (cb) { if (cb) {
cb('unable to retrieve txReceipt ' + txHash, null) cb('unable to retrieve txReceipt ' + txHash, null)
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment