diff --git a/libs/remix-debug/src/Ethdebugger.js b/libs/remix-debug/src/Ethdebugger.js index 4c4f071e69..2cebaeb149 100644 --- a/libs/remix-debug/src/Ethdebugger.js +++ b/libs/remix-debug/src/Ethdebugger.js @@ -90,8 +90,23 @@ Ethdebugger.prototype.extractLocalsAt = function (step, callback) { Ethdebugger.prototype.decodeLocalsAt = function (step, sourceLocation, callback) { const self = this this.traceManager.waterfall([ - this.traceManager.getStackAt, - this.traceManager.getMemoryAt, + function getStackAt (stepIndex, callback) { + try { + const result = self.traceManager.getStackAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }, + function getMemoryAt (stepIndex, callback) { + try { + const result = self.traceManager.getMemoryAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }, + function getCurrentCalledAddressAt (stepIndex, next) { try { const address = self.traceManager.getCurrentCalledAddressAt(stepIndex) diff --git a/libs/remix-debug/src/debugger/VmDebugger.js b/libs/remix-debug/src/debugger/VmDebugger.js index f9dda12c3e..8892f76b57 100644 --- a/libs/remix-debug/src/debugger/VmDebugger.js +++ b/libs/remix-debug/src/debugger/VmDebugger.js @@ -60,23 +60,23 @@ class VmDebuggerLogic { this.event.trigger('functionsStackUpdate', [this._callTree.retrieveFunctionsStack(index)]) - this._traceManager.getCallDataAt(index, (error, calldata) => { - if (error) { - // console.log(error) - this.event.trigger('traceManagerCallDataUpdate', [{}]) - } else if (this.stepManager.currentStepIndex === index) { + try { + const calldata = this._traceManager.getCallDataAt(index) + if (this.stepManager.currentStepIndex === index) { this.event.trigger('traceManagerCallDataUpdate', [calldata]) } - }) + } catch (error) { + this.event.trigger('traceManagerCallDataUpdate', [{}]) + } - this._traceManager.getMemoryAt(index, (error, memory) => { - if (error) { - // console.log(error) - this.event.trigger('traceManagerMemoryUpdate', [{}]) - } else if (this.stepManager.currentStepIndex === index) { + try { + const memory = this._traceManager.getMemoryAt(index) + if (this.stepManager.currentStepIndex === index) { this.event.trigger('traceManagerMemoryUpdate', [ui.formatMemory(memory, 16)]) } - }) + } catch (error) { + this.event.trigger('traceManagerMemoryUpdate', [{}]) + } try { const callstack = this._traceManager.getCallStackAt(index) @@ -87,14 +87,14 @@ class VmDebuggerLogic { this.event.trigger('traceManagerCallStackUpdate', [{}]) } - this._traceManager.getStackAt(index, (error, callstack) => { - if (error) { - // console.log(error) - this.event.trigger('traceManagerStackUpdate', [{}]) - } else if (this.stepManager.currentStepIndex === index) { + try { + const callstack = this._traceManager.getStackAt(index) + if (this.stepManager.currentStepIndex === index) { this.event.trigger('traceManagerStackUpdate', [callstack]) } - }) + } catch (error) { + this.event.trigger('traceManagerStackUpdate', [{}]) + } try { const address = this._traceManager.getCurrentCalledAddressAt(index) @@ -102,21 +102,24 @@ class VmDebuggerLogic { var storageViewer = new StorageViewer({ stepIndex: this.stepManager.currentStepIndex, tx: this.tx, address: address }, this.storageResolver, this._traceManager) - storageViewer.storageRange((error, storage) => { - if (error) { - this.event.trigger('traceManagerStorageUpdate', [{}]) - } else if (this.stepManager.currentStepIndex === index) { + storageViewer.storageRange().then((storage) => { + if (this.stepManager.currentStepIndex === index) { var header = storageViewer.isComplete(address) ? '[Completely Loaded]' : '[Partially Loaded]' this.event.trigger('traceManagerStorageUpdate', [storage, header]) } + }).catch((_error) => { + this.event.trigger('traceManagerStorageUpdate', [{}]) }) } catch (error) { - console.log(error) + this.event.trigger('traceManagerStorageUpdate', [{}]) } - this._traceManager.getCurrentStep(index, (error, step) => { - this.event.trigger('traceCurrentStepUpdate', [error, step]) - }) + try { + const step = this._traceManager.getCurrentStep(index) + this.event.trigger('traceCurrentStepUpdate', [null, step]) + } catch (error) { + this.event.trigger('traceCurrentStepUpdate', [error]) + } try { const addmem = this._traceManager.getMemExpand(index) @@ -146,13 +149,14 @@ class VmDebuggerLogic { this.event.trigger('traceRemainingGasUpdate', [error]) } - this._traceManager.getReturnValue(index, (error, returnValue) => { - if (error) { - this.event.trigger('traceReturnValueUpdate', [[error]]) - } else if (this.stepManager.currentStepIndex === index) { + try { + const returnValue = this._traceManager.getReturnValue(index) + if (this.stepManager.currentStepIndex === index) { this.event.trigger('traceReturnValueUpdate', [[returnValue]]) } - }) + } catch (error) { + this.event.trigger('traceReturnValueUpdate', [[error]]) + } }) } @@ -161,11 +165,9 @@ class VmDebuggerLogic { this.traceLength = 0 this.debugger.event.register('newTraceLoaded', (length) => { - this._traceManager.getAddresses((error, addresses) => { - if (error) return - this.event.trigger('traceAddressesUpdate', [addresses]) - this.addresses = addresses - }) + const addresses = this._traceManager.getAddresses() + this.event.trigger('traceAddressesUpdate', [addresses]) + this.addresses = addresses this._traceManager.getLength((error, length) => { if (error) return @@ -186,11 +188,9 @@ class VmDebuggerLogic { for (var k in this.addresses) { var address = this.addresses[k] var storageViewer = new StorageViewer({ stepIndex: this.stepManager.currentStepIndex, tx: this.tx, address: address }, this.storageResolver, this._traceManager) - storageViewer.storageRange((error, result) => { - if (!error) { - storageJSON[address] = result - this.event.trigger('traceStorageUpdate', [storageJSON]) - } + storageViewer.storageRange().then((result) => { + storageJSON[address] = result + this.event.trigger('traceStorageUpdate', [storageJSON]) }) } }) diff --git a/libs/remix-debug/src/debugger/solidityLocals.js b/libs/remix-debug/src/debugger/solidityLocals.js index f88d74249b..9368172da2 100644 --- a/libs/remix-debug/src/debugger/solidityLocals.js +++ b/libs/remix-debug/src/debugger/solidityLocals.js @@ -30,13 +30,28 @@ class DebuggerSolidityLocals { } decode (sourceLocation) { + const self = this this.event.trigger('solidityLocalsMessage', ['']) this.traceManager.waterfall([ - this.traceManager.getStackAt, - this.traceManager.getMemoryAt, - (stepIndex, next) => { + function getStackAt (stepIndex, callback) { try { - const address = this.traceManager.getCurrentCalledAddressAt(stepIndex) + const result = self.traceManager.getStackAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }, + function getMemoryAt (stepIndex, callback) { + try { + const result = self.traceManager.getMemoryAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }, + function getCurrentCalledAddressAt (stepIndex, next) { + try { + const address = self.traceManager.getCurrentCalledAddressAt(stepIndex) next(null, address) } catch (error) { next(error) diff --git a/libs/remix-debug/src/debugger/stepManager.js b/libs/remix-debug/src/debugger/stepManager.js index 9abf54a0ca..824bb3c7b1 100644 --- a/libs/remix-debug/src/debugger/stepManager.js +++ b/libs/remix-debug/src/debugger/stepManager.js @@ -41,11 +41,7 @@ class DebuggerStepManager { if (index < 0) return if (this.currentStepIndex !== index) return - this.traceManager.buildCallPath(index, (error, callsPath) => { - if (error) { - console.log(error) - return this.event.trigger('revertWarning', ['']) - } + this.traceManager.buildCallPath(index).then((callsPath) => { this.currentCall = callsPath[callsPath.length - 1] if (this.currentCall.reverted) { let revertedReason = this.currentCall.outofgas ? 'outofgas' : '' @@ -59,6 +55,9 @@ class DebuggerStepManager { this.event.trigger('revertWarning', ['parenthasthrown']) } this.event.trigger('revertWarning', ['']) + }).catch((error) => { + console.log(error) + this.event.trigger('revertWarning', ['']) }) }) } diff --git a/libs/remix-debug/src/solidity-decoder/astHelper.js b/libs/remix-debug/src/solidity-decoder/astHelper.js index 3713154d9b..2ac023bcc7 100644 --- a/libs/remix-debug/src/solidity-decoder/astHelper.js +++ b/libs/remix-debug/src/solidity-decoder/astHelper.js @@ -51,27 +51,24 @@ function extractStateDefinitions (contractName, sourcesList, contracts) { contracts = extractContractDefinitions(sourcesList) } const node = contracts.contractsByName[contractName] - if (node) { - const stateItems = [] - const stateVar = [] - const baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById) - baseContracts.reverse() - for (let k in baseContracts) { - const ctr = baseContracts[k] - for (let i in ctr.children) { - const item = ctr.children[i] - stateItems.push(item) - if (item.name === 'VariableDeclaration') { - stateVar.push(item) - } + if (!node) { + return null + } + const stateItems = [] + const stateVar = [] + const baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById) + baseContracts.reverse() + for (let k in baseContracts) { + const ctr = baseContracts[k] + for (let i in ctr.children) { + const item = ctr.children[i] + stateItems.push(item) + if (item.name === 'VariableDeclaration') { + stateVar.push(item) } } - return { - stateDefinitions: stateItems, - stateVariables: stateVar - } } - return null + return {stateDefinitions: stateItems, stateVariables: stateVar} } /** diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.js b/libs/remix-debug/src/solidity-decoder/internalCallTree.js index a1c9da1969..b9c6872b45 100644 --- a/libs/remix-debug/src/solidity-decoder/internalCallTree.js +++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.js @@ -224,26 +224,27 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc // we check if the current vm trace step target a new ast node of type VariableDeclaration // that way we know that there is a new local variable from here. if (variableDeclaration && !tree.scopes[scopeId].locals[variableDeclaration.attributes.name]) { - tree.traceManager.getStackAt(step, (error, stack) => { + try { + const stack = tree.traceManager.getStackAt(step) // the stack length at this point is where the value of the new local variable will be stored. // so, either this is the direct value, or the offset in memory. That depends on the type. - if (!error) { - tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached - if (!error && variableDeclaration.attributes.name !== '') { - var states = tree.solidityProxy.extractStatesDefinitions() - var location = typesUtil.extractLocationFromAstVariable(variableDeclaration) - location = location === 'default' ? 'storage' : location + tree.solidityProxy.contractNameAt(step).then((contractName) => { + if (variableDeclaration.attributes.name !== '') { + var states = tree.solidityProxy.extractStatesDefinitions() + var location = typesUtil.extractLocationFromAstVariable(variableDeclaration) + location = location === 'default' ? 'storage' : location // we push the new local variable in our tree - tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = { - name: variableDeclaration.attributes.name, - type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName, location), - stackDepth: stack.length, - sourceLocation: sourceLocation - } + tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = { + name: variableDeclaration.attributes.name, + type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName, location), + stackDepth: stack.length, + sourceLocation: sourceLocation } - }) - } - }) + } + }) + } catch (error) { + console.log(error) + } } // we check here if we are at the beginning inside a new function. // if that is the case, we have to add to locals tree the inputs and output params @@ -253,34 +254,35 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc const functionDefinitionAndInputs = {functionDefinition, inputs: []} // means: the previous location was a function definition && JUMPDEST // => we are at the beginning of the function and input/output are setup - tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached - if (!error) { - tree.traceManager.getStackAt(step, (error, stack) => { - if (!error) { - var states = tree.solidityProxy.extractStatesDefinitions() - if (functionDefinition.children && functionDefinition.children.length) { - let inputs - let outputs - for (const element of functionDefinition.children) { - if (element.name === 'ParameterList') { - if (!inputs) inputs = element - else { - outputs = element - break - } - } - } - // input params - if (inputs) { - functionDefinitionAndInputs.inputs = addParams(inputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, inputs.children.length, -1) + + tree.solidityProxy.contractNameAt(step).then((contractName) => { // cached + try { + const stack = tree.traceManager.getStackAt(step) + var states = tree.solidityProxy.extractStatesDefinitions() + if (functionDefinition.children && functionDefinition.children.length) { + let inputs + let outputs + for (const element of functionDefinition.children) { + if (element.name === 'ParameterList') { + if (!inputs) inputs = element + else { + outputs = element + break } - // output params - if (outputs) addParams(outputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, 0, 1) } } - }) + // input params + if (inputs) { + functionDefinitionAndInputs.inputs = addParams(inputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, inputs.children.length, -1) + } + // output params + if (outputs) addParams(outputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, 0, 1) + } + } catch (error) { + console.log(error) } }) + tree.functionDefinitionsByScope[scopeId] = functionDefinitionAndInputs } } diff --git a/libs/remix-debug/src/solidity-decoder/solidityProxy.js b/libs/remix-debug/src/solidity-decoder/solidityProxy.js index e6640fae7c..ee3fd5beac 100644 --- a/libs/remix-debug/src/solidity-decoder/solidityProxy.js +++ b/libs/remix-debug/src/solidity-decoder/solidityProxy.js @@ -39,26 +39,25 @@ class SolidityProxy { * @param {Int} vmTraceIndex - index in the vm trave where to resolve the executed contract name * @param {Function} cb - callback returns (error, contractName) */ - contractNameAt (vmTraceIndex, cb) { - try { - const address = this.traceManager.getCurrentCalledAddressAt(vmTraceIndex) - - if (this.cache.contractNameByAddress[address]) { - cb(null, this.cache.contractNameByAddress[address]) - } else { + contractNameAt (vmTraceIndex) { + return new Promise((resolve, reject) => { + try { + const address = this.traceManager.getCurrentCalledAddressAt(vmTraceIndex) + if (this.cache.contractNameByAddress[address]) { + return resolve(this.cache.contractNameByAddress[address]) + } this.codeManager.getCode(address, (error, code) => { if (error) { - cb(error) - } else { - const contractName = contractNameFromCode(this.contracts, code.bytecode, address) - this.cache.contractNameByAddress[address] = contractName - cb(null, contractName) + return reject(error) } + const contractName = contractNameFromCode(this.contracts, code.bytecode, address) + this.cache.contractNameByAddress[address] = contractName + resolve(contractName) }) + } catch (error) { + reject(error) } - } catch (error) { - cb(error) - } + }) } /** @@ -98,12 +97,9 @@ class SolidityProxy { */ extractStateVariablesAt (vmtraceIndex) { return new Promise((resolve, reject) => { - this.contractNameAt(vmtraceIndex, (error, contractName) => { - if (error) { - return reject(error) - } - return resolve(this.extractStateVariables(contractName)) - }) + this.contractNameAt(vmtraceIndex).then((contractName) => { + resolve(this.extractStateVariables(contractName)) + }).catch(reject) }) } diff --git a/libs/remix-debug/src/solidity-decoder/types/Bool.js b/libs/remix-debug/src/solidity-decoder/types/Bool.js index 659ac12d44..da8c47c3fa 100644 --- a/libs/remix-debug/src/solidity-decoder/types/Bool.js +++ b/libs/remix-debug/src/solidity-decoder/types/Bool.js @@ -10,10 +10,9 @@ class Bool extends ValueType { decodeValue (value) { if (!value) { return false - } else { - value = util.extractHexByteSlice(value, this.storageBytes, 0) - return value !== '00' } + value = util.extractHexByteSlice(value, this.storageBytes, 0) + return value !== '00' } } diff --git a/libs/remix-debug/src/solidity-decoder/types/Enum.js b/libs/remix-debug/src/solidity-decoder/types/Enum.js index 3c384e6084..d6e558bfeb 100644 --- a/libs/remix-debug/src/solidity-decoder/types/Enum.js +++ b/libs/remix-debug/src/solidity-decoder/types/Enum.js @@ -16,14 +16,12 @@ class Enum extends ValueType { decodeValue (value) { if (!value) { return this.enumDef.children[0].attributes.name - } else { - value = parseInt(value, 16) - if (this.enumDef.children.length > value) { - return this.enumDef.children[value].attributes.name - } else { - return 'INVALID_ENUM<' + value + '>' - } } + value = parseInt(value, 16) + if (this.enumDef.children.length > value) { + return this.enumDef.children[value].attributes.name + } + return 'INVALID_ENUM<' + value + '>' } } diff --git a/libs/remix-debug/src/solidity-decoder/types/util.js b/libs/remix-debug/src/solidity-decoder/types/util.js index c338114fb5..719f082dc5 100644 --- a/libs/remix-debug/src/solidity-decoder/types/util.js +++ b/libs/remix-debug/src/solidity-decoder/types/util.js @@ -100,9 +100,8 @@ function extractLocation (type) { let match = type.match(/( storage ref| storage pointer| memory| calldata)?$/) if (match[1] !== '') { return match[1].trim() - } else { - return null } + return null } function extractLocationFromAstVariable (node) { @@ -110,9 +109,8 @@ function extractLocationFromAstVariable (node) { return node.attributes.storageLocation } else if (node.attributes.stateVariable) { return 'storage' - } else { - return 'default' // local variables => storage, function parameters & return values => memory, state => storage } + return 'default' // local variables => storage, function parameters & return values => memory, state => storage } function normalizeHex (hex) { diff --git a/libs/remix-debug/src/storage/mappingPreimages.js b/libs/remix-debug/src/storage/mappingPreimages.js index 513bdbf58f..94f95ae973 100644 --- a/libs/remix-debug/src/storage/mappingPreimages.js +++ b/libs/remix-debug/src/storage/mappingPreimages.js @@ -13,7 +13,7 @@ module.exports = { * @param {Function} callback - calback * @return {Map} - solidity mapping location (e.g { "" : { "": preimageOf1 }, { "": preimageOf2 }, ... }) */ -async function decodeMappingsKeys (web3, storage, corrections, callback) { +async function decodeMappingsKeys (web3, storage, corrections) { const ret = {} if (!corrections.length) corrections.push({offset: 0, slot: 0}) for (let hashedLoc in storage) { @@ -38,7 +38,7 @@ async function decodeMappingsKeys (web3, storage, corrections, callback) { ret[mappingSlot][mappingKey] = preimage } } - callback(null, ret) + return ret } /** diff --git a/libs/remix-debug/src/storage/storageResolver.js b/libs/remix-debug/src/storage/storageResolver.js index 4cedf4fa69..0de8fbd161 100644 --- a/libs/remix-debug/src/storage/storageResolver.js +++ b/libs/remix-debug/src/storage/storageResolver.js @@ -25,8 +25,8 @@ class StorageResolver { * @param {String} - address - lookup address * @param {Function} - callback - contains a map: [hashedKey] = {key, hashedKey, value} */ - storageRange (tx, stepIndex, address, callback) { - this.storageRangeInternal(this, this.zeroSlot, tx, stepIndex, address, callback) + storageRange (tx, stepIndex, address) { + return this.storageRangeInternal(this, this.zeroSlot, tx, stepIndex, address) } /** @@ -39,22 +39,16 @@ class StorageResolver { * @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping). * @return {Function} - callback */ - initialPreimagesMappings (tx, stepIndex, address, corrections, callback) { - if (this.preimagesMappingByAddress[address]) { - return callback(null, this.preimagesMappingByAddress[address]) - } - this.storageRange(tx, stepIndex, address, (error, storage) => { - if (error) { - return callback(error) + initialPreimagesMappings (tx, stepIndex, address, corrections) { + return new Promise((resolve, reject) => { + if (this.preimagesMappingByAddress[address]) { + return resolve(this.preimagesMappingByAddress[address]) } - mappingPreimages.decodeMappingsKeys(this.web3, storage, corrections, (error, mappings) => { - if (error) { - callback(error) - } else { - this.preimagesMappingByAddress[address] = mappings - callback(null, mappings) - } - }) + this.storageRange(tx, stepIndex, address).then((storage) => { + const mappings = mappingPreimages.decodeMappingsKeys(this.web3, storage, corrections) + this.preimagesMappingByAddress[address] = mappings + resolve(mappings) + }).catch(reject) }) } @@ -67,13 +61,11 @@ class StorageResolver { * @param {String} - address - lookup address * @param {Function} - callback - {key, hashedKey, value} - */ - storageSlot (slot, tx, stepIndex, address, callback) { - this.storageRangeInternal(this, slot, tx, stepIndex, address, (error, storage) => { - if (error) { - callback(error) - } else { - callback(null, storage[slot] !== undefined ? storage[slot] : null) - } + storageSlot (slot, tx, stepIndex, address) { + return new Promise((resolve, reject) => { + this.storageRangeInternal(this, slot, tx, stepIndex, address).then((storage) => { + resolve(storage[slot] !== undefined ? storage[slot] : null) + }).catch(reject) }) } @@ -93,26 +85,26 @@ class StorageResolver { * even if the next 1000 items are not in the cache. * - If @arg slot is not cached, the corresponding value will be resolved and the next 1000 slots. */ - storageRangeInternal (self, slotKey, tx, stepIndex, address, callback) { - var cached = this.fromCache(self, address) - if (cached && cached.storage[slotKey]) { // we have the current slot in the cache and maybe the next 1000... - return callback(null, cached.storage) - } - this.storageRangeWeb3Call(tx, address, slotKey, self.maxSize, (error, storage, nextKey) => { - if (error) { - return callback(error) + storageRangeInternal (self, slotKey, tx, stepIndex, address) { + return new Promise((resolve, reject) => { + var cached = this.fromCache(self, address) + if (cached && cached.storage[slotKey]) { // we have the current slot in the cache and maybe the next 1000... + return resolve(cached.storage) } - if (!storage[slotKey] && slotKey !== self.zeroSlot) { // we don't cache the zero slot (could lead to inconsistency) - storage[slotKey] = { - key: slotKey, - value: self.zeroSlot + this.storageRangeWeb3Call(tx, address, slotKey, self.maxSize).then((result) => { + const [storage, nextKey] = result + if (!storage[slotKey] && slotKey !== self.zeroSlot) { // we don't cache the zero slot (could lead to inconsistency) + storage[slotKey] = { + key: slotKey, + value: self.zeroSlot + } } - } - self.toCache(self, address, storage) - if (slotKey === self.zeroSlot && !nextKey) { // only working if keys are sorted !! - self.storageByAddress[address].complete = true - } - callback(null, storage) + self.toCache(self, address, storage) + if (slotKey === self.zeroSlot && !nextKey) { // only working if keys are sorted !! + self.storageByAddress[address].complete = true + } + return resolve(storage) + }).catch(reject) }) } @@ -142,25 +134,27 @@ class StorageResolver { self.storageByAddress[address].storage = Object.assign(self.storageByAddress[address].storage || {}, storage) } - storageRangeWeb3Call (tx, address, start, maxSize, callback) { - if (traceHelper.isContractCreation(address)) { - callback(null, {}, null) - } else { - this.web3.debug.storageRangeAt( - tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex, - address, - start, - maxSize, - (error, result) => { - if (error) { - callback(error) - } else if (result.storage) { - callback(null, result.storage, result.nextKey) - } else { - callback('the storage has not been provided') - } - }) - } + storageRangeWeb3Call (tx, address, start, maxSize) { + return new Promise((resolve, reject) => { + if (traceHelper.isContractCreation(address)) { + resolve([{}, null]) + } else { + this.web3.debug.storageRangeAt( + tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex, + address, + start, + maxSize, + (error, result) => { + if (error) { + reject(error) + } else if (result.storage) { + resolve([result.storage, result.nextKey]) + } else { + reject('the storage has not been provided') + } + }) + } + }) } } diff --git a/libs/remix-debug/src/storage/storageViewer.js b/libs/remix-debug/src/storage/storageViewer.js index 3f7aaec6b9..206701a637 100644 --- a/libs/remix-debug/src/storage/storageViewer.js +++ b/libs/remix-debug/src/storage/storageViewer.js @@ -15,13 +15,7 @@ class StorageViewer { this.web3 = this.storageResolver.web3 this.initialMappingsLocationPromise = null this.currentMappingsLocationPromise = null - _traceManager.accumulateStorageChanges(this.context.stepIndex, this.context.address, {}, (error, storageChanges) => { - if (!error) { - this.storageChanges = storageChanges - } else { - console.log(error) - } - }) + this.storageChanges = _traceManager.accumulateStorageChanges(this.context.stepIndex, this.context.address, {}) } /** @@ -30,13 +24,11 @@ class StorageViewer { * * @param {Function} - callback - contains a map: [hashedKey] = {key, hashedKey, value} */ - storageRange (callback) { - this.storageResolver.storageRange(this.context.tx, this.context.stepIndex, this.context.address, (error, storage) => { - if (error) { - callback(error) - } else { - callback(null, Object.assign({}, storage, this.storageChanges)) - } + storageRange () { + return new Promise((resolve, reject) => { + this.storageResolver.storageRange(this.context.tx, this.context.stepIndex, this.context.address).then((storage) => { + resolve(Object.assign({}, storage, this.storageChanges)) + }).catch(reject) }) } @@ -50,13 +42,9 @@ class StorageViewer { if (this.storageChanges[hashed]) { return callback(null, this.storageChanges[hashed]) } - this.storageResolver.storageSlot(hashed, this.context.tx, this.context.stepIndex, this.context.address, (error, storage) => { - if (error) { - callback(error) - } else { - callback(null, storage) - } - }) + this.storageResolver.storageSlot(hashed, this.context.tx, this.context.stepIndex, this.context.address).then((storage) => { + callback(null, storage) + }).catch(callback) } /** @@ -76,15 +64,7 @@ class StorageViewer { */ async initialMappingsLocation (corrections) { if (!this.initialMappingsLocationPromise) { - this.initialMappingsLocationPromise = new Promise((resolve, reject) => { - this.storageResolver.initialPreimagesMappings(this.context.tx, this.context.stepIndex, this.context.address, corrections, (error, initialMappingsLocation) => { - if (error) { - reject(error) - } else { - resolve(initialMappingsLocation) - } - }) - }) + this.initialMappingsLocationPromise = this.storageResolver.initialPreimagesMappings(this.context.tx, this.context.stepIndex, this.context.address, corrections) } return this.initialMappingsLocationPromise } @@ -118,14 +98,9 @@ class StorageViewer { if (this.mappingsLocationChanges) { return callback(null, this.mappingsLocationChanges) } - mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, corrections, (error, mappings) => { - if (!error) { - this.mappingsLocationChanges = mappings - return callback(null, this.mappingsLocationChanges) - } else { - callback(error) - } - }) + const mappings = mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, corrections) + this.mappingsLocationChanges = mappings + return callback(null, this.mappingsLocationChanges) } } diff --git a/libs/remix-debug/test/debugger.js b/libs/remix-debug/test/debugger.js index 946e21b43d..81a800ee09 100644 --- a/libs/remix-debug/test/debugger.js +++ b/libs/remix-debug/test/debugger.js @@ -193,23 +193,27 @@ function testDebugging (debugManager) { // stack tape('traceManager.getStackAt 4', (t) => { t.plan(1) - debugManager.traceManager.getStackAt(4, (error, callstack) => { - if (error) return t.end(error) - t.equal(JSON.stringify(callstack), JSON.stringify([ '0x0000000000000000000000000000000000000000000000000000000000000000' ])) - }) + try { + const callstack = debugManager.traceManager.getStackAt(4) + t.equal(JSON.stringify(callstack), JSON.stringify(['0x0000000000000000000000000000000000000000000000000000000000000000'])) + } catch (error) { + return t.end(error) + } }) tape('traceManager.getStackAt 41', (t) => { t.plan(1) - debugManager.traceManager.getStackAt(41, (error, callstack) => { - if (error) return t.end(error) + try { + const callstack = debugManager.traceManager.getStackAt(41) t.equal(JSON.stringify(callstack), JSON.stringify([ '0x0000000000000000000000000000000000000000000000000000000000000080', '0x0000000000000000000000000000000000000000000000000000000000000020', '0x0000000000000000000000000000000000000000000000000000000000000080', '0x00000000000000000000000000000000000000000000000000000000000000e0', '0x00000000000000000000000000000000000000000000000000000000000000e0'])) - }) + } catch (error) { + return t.end(error) + } }) // storage @@ -220,9 +224,11 @@ function testDebugging (debugManager) { const address = debugManager.traceManager.getCurrentCalledAddressAt(38) console.log(address) var storageView = debugManager.storageViewAt(196, address) - storageView.storageRange((error, storage) => { - if (error) return t.end(error) + + storageView.storageRange().then((storage) => { t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000004b0897b0513fdc7c541b6d9d7e929c4e5364d2db' } })) + }).catch((error) => { + if (error) return t.end(error) }) } catch (error) { return t.end(error) diff --git a/libs/remix-debug/test/decoder/localsTests/helper.js b/libs/remix-debug/test/decoder/localsTests/helper.js index b30c39cb21..ac22436b9c 100644 --- a/libs/remix-debug/test/decoder/localsTests/helper.js +++ b/libs/remix-debug/test/decoder/localsTests/helper.js @@ -7,8 +7,22 @@ var localDecoder = require('../../../src/solidity-decoder/localDecoder') function decodeLocal (st, index, traceManager, callTree, verifier) { try { traceManager.waterfall([ - traceManager.getStackAt, - traceManager.getMemoryAt], + function getStackAt (stepIndex, callback) { + try { + const result = traceManager.getStackAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }, + function getMemoryAt (stepIndex, callback) { + try { + const result = traceManager.getMemoryAt(stepIndex) + callback(null, result) + } catch (error) { + callback(error) + } + }], index, function (error, result) { if (!error) { diff --git a/libs/remix-lib/src/code/codeManager.js b/libs/remix-lib/src/code/codeManager.js index d19b2800ef..d665192a28 100644 --- a/libs/remix-lib/src/code/codeManager.js +++ b/libs/remix-lib/src/code/codeManager.js @@ -63,12 +63,9 @@ CodeManager.prototype.getCode = function (address, cb) { if (codes) { return cb(null, codes) } - this.traceManager.getContractCreationCode(address, (error, hexCode) => { - if (!error) { - codes = this.codeResolver.cacheExecutingCode(address, hexCode) - cb(null, codes) - } - }) + const hexCode = this.traceManager.getContractCreationCode(address) + codes = this.codeResolver.cacheExecutingCode(address, hexCode) + cb(null, codes) } /** @@ -82,16 +79,11 @@ CodeManager.prototype.getCode = function (address, cb) { CodeManager.prototype.getFunctionFromStep = function (stepIndex, sourceMap, ast) { try { const address = this.traceManager.getCurrentCalledAddressAt(stepIndex) - this.traceManager.getCurrentPC(stepIndex, (error, pc) => { - if (error) { - console.log(error) - return { error: 'Cannot retrieve current PC for ' + stepIndex } - } - return this.getFunctionFromPC(address, pc, sourceMap, ast) - }) + const pc = this.traceManager.getCurrentPC(stepIndex) + return this.getFunctionFromPC(address, pc, sourceMap, ast) } catch (error) { console.log(error) - return { error: 'Cannot retrieve current address for ' + stepIndex } + return { error: 'Cannot retrieve current address or PC for ' + stepIndex } } } @@ -103,14 +95,14 @@ CodeManager.prototype.getFunctionFromStep = function (stepIndex, sourceMap, ast) * @param {Function} callback - instruction index */ CodeManager.prototype.getInstructionIndex = function (address, step, callback) { - this.traceManager.getCurrentPC(step, (error, pc) => { - if (error) { - console.log(error) - return callback('Cannot retrieve current PC for ' + step, null) - } + try { + const pc = this.traceManager.getCurrentPC(step) const itemIndex = this.codeResolver.getInstructionIndex(address, pc) callback(null, itemIndex) - }) + } catch (error) { + console.log(error) + return callback('Cannot retrieve current PC for ' + step, null) + } } /** diff --git a/libs/remix-lib/src/sourceLocationTracker.js b/libs/remix-lib/src/sourceLocationTracker.js index 487bdd1a58..79c5a82357 100644 --- a/libs/remix-lib/src/sourceLocationTracker.js +++ b/libs/remix-lib/src/sourceLocationTracker.js @@ -40,19 +40,15 @@ SourceLocationTracker.prototype.getSourceLocationFromInstructionIndex = function */ SourceLocationTracker.prototype.getSourceLocationFromVMTraceIndex = function (address, vmtraceStepIndex, contracts) { return new Promise((resolve, reject) => { - extractSourceMap(this, this.codeManager, address, contracts, (error, sourceMap) => { - if (!error) { - this.codeManager.getInstructionIndex(address, vmtraceStepIndex, (error, index) => { - if (error) { - reject(error) - } else { - resolve(this.sourceMappingDecoder.atIndex(index, sourceMap)) - } - }) - } else { - reject(error) - } - }) + extractSourceMap(this, this.codeManager, address, contracts).then((sourceMap) => { + this.codeManager.getInstructionIndex(address, vmtraceStepIndex, (error, index) => { + if (error) { + reject(error) + } else { + resolve(this.sourceMappingDecoder.atIndex(index, sourceMap)) + } + }) + }).catch(reject) }) } @@ -78,21 +74,23 @@ function getSourceMap (address, code, contracts) { return null } -function extractSourceMap (self, codeManager, address, contracts, cb) { - if (self.sourceMapByAddress[address]) return cb(null, self.sourceMapByAddress[address]) +function extractSourceMap (self, codeManager, address, contracts) { + return new Promise((resolve, reject) => { + if (self.sourceMapByAddress[address]) return resolve(self.sourceMapByAddress[address]) - codeManager.getCode(address, (error, result) => { - if (!error) { - const sourceMap = getSourceMap(address, result.bytecode, contracts) - if (sourceMap) { - if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap - cb(null, sourceMap) + codeManager.getCode(address, (error, result) => { + if (!error) { + const sourceMap = getSourceMap(address, result.bytecode, contracts) + if (sourceMap) { + if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap + resolve(sourceMap) + } else { + reject('no sourcemap associated with the code ' + address) + } } else { - cb('no sourcemap associated with the code ' + address) + reject(error) } - } else { - cb(error) - } + }) }) } diff --git a/libs/remix-lib/src/trace/traceManager.js b/libs/remix-lib/src/trace/traceManager.js index 7065f76cf5..386ec78e25 100644 --- a/libs/remix-lib/src/trace/traceManager.js +++ b/libs/remix-lib/src/trace/traceManager.js @@ -80,35 +80,36 @@ TraceManager.prototype.getLength = function (callback) { } } -TraceManager.prototype.accumulateStorageChanges = function (index, address, storageOrigin, callback) { - const storage = this.traceCache.accumulateStorageChanges(index, address, storageOrigin) - callback(null, storage) +TraceManager.prototype.accumulateStorageChanges = function (index, address, storageOrigin) { + return this.traceCache.accumulateStorageChanges(index, address, storageOrigin) } -TraceManager.prototype.getAddresses = function (callback) { - callback(null, this.traceCache.addresses) +TraceManager.prototype.getAddresses = function () { + return this.traceCache.addresses } -TraceManager.prototype.getCallDataAt = function (stepIndex, callback) { +TraceManager.prototype.getCallDataAt = function (stepIndex) { try { this.checkRequestedStep(stepIndex) } catch (check) { - return callback(check, null) + throw new Error(check) } const callDataChange = util.findLowerBoundValue(stepIndex, this.traceCache.callDataChanges) - if (callDataChange === null) return callback('no calldata found', null) - callback(null, [this.traceCache.callsData[callDataChange]]) + if (callDataChange === null) { + throw new Error('no calldata found') + } + return [this.traceCache.callsData[callDataChange]] } -TraceManager.prototype.buildCallPath = function (stepIndex, callback) { +TraceManager.prototype.buildCallPath = async function (stepIndex) { try { this.checkRequestedStep(stepIndex) } catch (check) { - return callback(check, null) + throw new Error(check) } const callsPath = util.buildCallPath(stepIndex, this.traceCache.callsTree.call) - if (callsPath === null) return callback('no call path built', null) - callback(null, callsPath) + if (callsPath === null) throw new Error('no call path built') + return callsPath } TraceManager.prototype.getCallStackAt = function (stepIndex) { @@ -124,19 +125,14 @@ TraceManager.prototype.getCallStackAt = function (stepIndex) { return call.callStack } -TraceManager.prototype.getStackAt = function (stepIndex, callback) { - try { - this.checkRequestedStep(stepIndex) - } catch (check) { - return callback(check, null) - } - let stack +TraceManager.prototype.getStackAt = function (stepIndex) { + this.checkRequestedStep(stepIndex) if (this.trace[stepIndex] && this.trace[stepIndex].stack) { // there's always a stack - stack = this.trace[stepIndex].stack.slice(0) + let stack = this.trace[stepIndex].stack.slice(0) stack.reverse() - callback(null, stack) + return stack } else { - callback('no stack found', null) + throw new Error('no stack found') } } @@ -167,54 +163,50 @@ TraceManager.prototype.getCurrentCalledAddressAt = function (stepIndex) { } } -TraceManager.prototype.getContractCreationCode = function (token, callback) { - if (this.traceCache.contractCreation[token]) { - callback(null, this.traceCache.contractCreation[token]) - } else { - callback('no contract creation named ' + token, null) +TraceManager.prototype.getContractCreationCode = function (token) { + if (!this.traceCache.contractCreation[token]) { + throw new Error('no contract creation named ' + token) } + return this.traceCache.contractCreation[token] } -TraceManager.prototype.getMemoryAt = function (stepIndex, callback) { - try { - this.checkRequestedStep(stepIndex) - } catch (check) { - return callback(check, null) - } +TraceManager.prototype.getMemoryAt = function (stepIndex) { + this.checkRequestedStep(stepIndex) const lastChanges = util.findLowerBoundValue(stepIndex, this.traceCache.memoryChanges) - if (lastChanges === null) return callback('no memory found', null) - callback(null, this.trace[lastChanges].memory) + if (lastChanges === null) { + throw new Error('no memory found') + } + return this.trace[lastChanges].memory } -TraceManager.prototype.getCurrentPC = function (stepIndex, callback) { +TraceManager.prototype.getCurrentPC = function (stepIndex) { try { this.checkRequestedStep(stepIndex) } catch (check) { - return callback(check, null) + throw new Error(check) } - callback(null, this.trace[stepIndex].pc) + return this.trace[stepIndex].pc } -TraceManager.prototype.getReturnValue = function (stepIndex, callback) { +TraceManager.prototype.getReturnValue = function (stepIndex) { try { this.checkRequestedStep(stepIndex) } catch (check) { - return callback(check, null) + throw new Error(check) } if (!this.traceCache.returnValues[stepIndex]) { - callback('current step is not a return step') - } else { - callback(null, this.traceCache.returnValues[stepIndex]) + throw new Error('current step is not a return step') } + return this.traceCache.returnValues[stepIndex] } -TraceManager.prototype.getCurrentStep = function (stepIndex, callback) { +TraceManager.prototype.getCurrentStep = function (stepIndex) { try { this.checkRequestedStep(stepIndex) } catch (check) { - return callback(check, null) + throw new Error(check) } - callback(null, this.traceCache.steps[stepIndex]) + return this.traceCache.steps[stepIndex] } TraceManager.prototype.getMemExpand = function (stepIndex) { diff --git a/libs/remix-lib/test/traceManager.js b/libs/remix-lib/test/traceManager.js index 818582761f..83f12b31d6 100644 --- a/libs/remix-lib/test/traceManager.js +++ b/libs/remix-lib/test/traceManager.js @@ -55,25 +55,19 @@ tape('TraceManager', function (t) { }) t.test('TraceManager.accumulateStorageChanges', function (st) { - traceManager.accumulateStorageChanges(110, '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', {}, function (error, result) { - if (error) { - st.fail(error) - } else { - st.ok(result['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'].value === '0x38') - st.end() - } - }) + const result = traceManager.accumulateStorageChanges(110, '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', {}) + st.ok(result['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'].value === '0x38') + st.end() }) t.test('TraceManager.getCallData', function (st) { - traceManager.getCallDataAt(0, function (error, result) { - if (error) { - st.fail(error) - } else { - st.ok(result[0] === '0x60fe47b10000000000000000000000000000000000000000000000000000000000000038') - st.end() - } - }) + try { + const result = traceManager.getCallDataAt(0) + st.ok(result[0] === '0x60fe47b10000000000000000000000000000000000000000000000000000000000000038') + st.end() + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getCallStackAt', function (st) { @@ -96,24 +90,22 @@ tape('TraceManager', function (t) { t.test('TraceManager.getStackAt', function (st) { st.plan(3) - traceManager.getStackAt(0, function (error, result) { + try { + const result = traceManager.getStackAt(0) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result.length === 0) - } - }) + st.ok(result.length === 0) + } catch (error) { + st.fail(error) + } - traceManager.getStackAt(28, function (error, result) { + try { + const result = traceManager.getStackAt(28) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result.length === 4) - st.ok(result[3] === '0x60fe47b1') - } - }) + st.ok(result.length === 4) + st.ok(result[3] === '0x60fe47b1') + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getLastCallChangeSince', function (st) { @@ -175,61 +167,56 @@ tape('TraceManager', function (t) { }) t.test('TraceManager.getContractCreationCode', function (st) { // contract code has been retrieved from the memory - traceManager.getContractCreationCode('(Contract Creation - Step 63)', function (error, result) { + try { + const result = traceManager.getContractCreationCode('(Contract Creation - Step 63)') console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result === '0x60606040526040516020806045833981016040528080519060200190919050505b806001016000600050819055505b50600a80603b6000396000f360606040526008565b00000000000000000000000000000000000000000000000000000000000000002d') - st.end() - } - }) + st.ok(result === '0x60606040526040516020806045833981016040528080519060200190919050505b806001016000600050819055505b50600a80603b6000396000f360606040526008565b00000000000000000000000000000000000000000000000000000000000000002d') + st.end() + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getMemoryAt', function (st) { st.plan(3) - traceManager.getMemoryAt(0, function (error, result) { + try { + const result = traceManager.getMemoryAt(0) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result.length === 0) - } - }) + st.ok(result.length === 0) + } catch (error) { + st.fail(error) + } - traceManager.getMemoryAt(34, function (error, result) { + try { + const result = traceManager.getMemoryAt(34) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result.length === 3) - st.ok(result[2] === '0000000000000000000000000000000000000000000000000000000000000060') - } - }) + st.ok(result.length === 3) + st.ok(result[2] === '0000000000000000000000000000000000000000000000000000000000000060') + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getCurrentPC', function (st) { - traceManager.getCurrentPC(13, function (error, result) { + try { + const result = traceManager.getCurrentPC(13) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result === '65') - st.end() - } - }) + st.ok(result === '65') + st.end() + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getCurrentStep', function (st) { - traceManager.getCurrentStep(66, function (error, result) { + try { + const result = traceManager.getCurrentStep(66) console.log(result) - if (error) { - st.fail(error) - } else { - st.ok(result === 2) - st.end() - } - }) + st.ok(result === 2) + st.end() + } catch (error) { + st.fail(error) + } }) t.test('TraceManager.getMemExpand', function (st) { @@ -287,25 +274,19 @@ tape('TraceManager', function (t) { }) t.test('TraceManager.getAddresses', function (st) { - traceManager.getAddresses(function (error, result) { - if (error) { - st.fail(error) - } else { - st.ok(result[0] === '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') - st.ok(result[1] === '(Contract Creation - Step 63)') - st.end() - } - }) + const result = traceManager.getAddresses() + st.ok(result[0] === '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + st.ok(result[1] === '(Contract Creation - Step 63)') + st.end() }) t.test('TraceManager.getReturnValue', function (st) { - traceManager.getReturnValue(108, function (error, result) { - if (error) { - st.fail(error) - } else { - st.ok(result[0] === '0x60606040526008565b0000000000000000000000000000000000000000000000') - st.end() - } - }) + try { + const result = traceManager.getReturnValue(108) + st.ok(result[0] === '0x60606040526008565b0000000000000000000000000000000000000000000000') + st.end() + } catch (error) { + st.fail(error) + } }) })