Skip to content

Commit 627bef0

Browse files
authored
Merge pull request #63 from ethereum/refactor_remix_debug4
Refactor remix debug4
2 parents f2b4694 + f8f965e commit 627bef0

File tree

16 files changed

+191
-328
lines changed

16 files changed

+191
-328
lines changed

libs/remix-debug/src/Ethdebugger.js

Lines changed: 46 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
'use strict'
22

3-
const StorageViewer = require('./storage/storageViewer')
4-
const StorageResolver = require('./storage/storageResolver')
5-
6-
const SolidityDecoder = require('./solidity-decoder')
7-
const SolidityProxy = SolidityDecoder.SolidityProxy
8-
const stateDecoder = SolidityDecoder.stateDecoder
9-
const localDecoder = SolidityDecoder.localDecoder
10-
const InternalCallTree = SolidityDecoder.InternalCallTree
11-
123
const remixLib = require('@remix-project/remix-lib')
134
const TraceManager = remixLib.trace.TraceManager
145
const CodeManager = remixLib.code.CodeManager
156
const traceHelper = remixLib.helpers.trace
167
const EventManager = remixLib.EventManager
178

9+
const {SolidityProxy, stateDecoder, localDecoder, InternalCallTree} = require('./solidity-decoder')
10+
11+
const StorageViewer = require('./storage/storageViewer')
12+
const StorageResolver = require('./storage/storageResolver')
13+
1814
/**
1915
* Ethdebugger is a wrapper around a few classes that helps debugging a transaction
2016
*
@@ -58,23 +54,15 @@ Ethdebugger.prototype.resolveStep = function (index) {
5854
}
5955

6056
Ethdebugger.prototype.setCompilationResult = function (compilationResult) {
61-
if (compilationResult && compilationResult.data) {
62-
this.solidityProxy.reset(compilationResult.data)
63-
} else {
64-
this.solidityProxy.reset({})
65-
}
57+
this.solidityProxy.reset((compilationResult && compilationResult.data) || {})
6658
}
6759

68-
Ethdebugger.prototype.sourceLocationFromVMTraceIndex = function (address, stepIndex, callback) {
69-
this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts).then((rawLocation) => {
70-
callback(null, rawLocation)
71-
}).catch(callback)
60+
Ethdebugger.prototype.sourceLocationFromVMTraceIndex = async function (address, stepIndex) {
61+
return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts)
7262
}
7363

74-
Ethdebugger.prototype.sourceLocationFromInstructionIndex = function (address, instIndex, callback) {
75-
this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts).then((rawLocation) => {
76-
callback(null, rawLocation)
77-
}).catch(callback)
64+
Ethdebugger.prototype.sourceLocationFromInstructionIndex = async function (address, instIndex, callback) {
65+
return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts)
7866
}
7967

8068
/* breakpoint */
@@ -83,98 +71,48 @@ Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) {
8371
}
8472

8573
/* decode locals */
86-
Ethdebugger.prototype.extractLocalsAt = function (step, callback) {
87-
callback(null, this.callTree.findScope(step))
74+
Ethdebugger.prototype.extractLocalsAt = function (step) {
75+
return this.callTree.findScope(step)
8876
}
8977

90-
Ethdebugger.prototype.decodeLocalsAt = function (step, sourceLocation, callback) {
91-
const self = this
92-
this.traceManager.waterfall([
93-
function getStackAt (stepIndex, callback) {
94-
try {
95-
const result = self.traceManager.getStackAt(stepIndex)
96-
callback(null, result)
97-
} catch (error) {
98-
callback(error)
99-
}
100-
},
101-
function getMemoryAt (stepIndex, callback) {
102-
try {
103-
const result = self.traceManager.getMemoryAt(stepIndex)
104-
callback(null, result)
105-
} catch (error) {
106-
callback(error)
107-
}
108-
},
109-
110-
function getCurrentCalledAddressAt (stepIndex, next) {
111-
try {
112-
const address = self.traceManager.getCurrentCalledAddressAt(stepIndex)
113-
next(null, address)
114-
} catch (error) {
115-
next(error)
116-
}
117-
}],
118-
step,
119-
(error, result) => {
120-
if (!error) {
121-
const stack = result[0].value
122-
const memory = result[1].value
123-
try {
124-
const storageViewer = new StorageViewer({
125-
stepIndex: step,
126-
tx: this.tx,
127-
address: result[2].value
128-
}, this.storageResolver, this.traceManager)
129-
localDecoder.solidityLocals(step, this.callTree, stack, memory, storageViewer, sourceLocation).then((locals) => {
130-
if (!locals.error) {
131-
callback(null, locals)
132-
} else {
133-
callback(locals.error)
134-
}
135-
})
136-
} catch (e) {
137-
callback(e.message)
138-
}
139-
} else {
140-
callback(error)
78+
Ethdebugger.prototype.decodeLocalsAt = async function (step, sourceLocation, callback) {
79+
try {
80+
const stack = this.traceManager.getStackAt(step)
81+
const memory = this.traceManager.getMemoryAt(step)
82+
const address = this.traceManager.getCurrentCalledAddressAt(step)
83+
try {
84+
const storageViewer = new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager)
85+
const locals = await localDecoder.solidityLocals(step, this.callTree, stack, memory, storageViewer, sourceLocation)
86+
if (locals.error) {
87+
return callback(locals.error)
14188
}
142-
})
89+
return callback(null, locals)
90+
} catch (e) {
91+
callback(e.message)
92+
}
93+
} catch (error) {
94+
callback(error)
95+
}
14396
}
14497

14598
/* decode state */
146-
Ethdebugger.prototype.extractStateAt = function (step, callback) {
147-
this.solidityProxy.extractStateVariablesAt(step).then((stateVars) => {
148-
callback(null, stateVars)
149-
}).catch(callback)
99+
Ethdebugger.prototype.extractStateAt = async function (step) {
100+
return this.solidityProxy.extractStateVariablesAt(step)
150101
}
151102

152-
Ethdebugger.prototype.decodeStateAt = function (step, stateVars, callback) {
103+
Ethdebugger.prototype.decodeStateAt = async function (step, stateVars, callback) {
153104
try {
154105
const address = this.traceManager.getCurrentCalledAddressAt(step)
155-
const storageViewer = new StorageViewer({
156-
stepIndex: step,
157-
tx: this.tx,
158-
address: address
159-
}, this.storageResolver, this.traceManager)
160-
stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
161-
if (!result.error) {
162-
callback(null, result)
163-
} else {
164-
callback(result.error)
165-
}
166-
})
106+
const storageViewer = new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager)
107+
const result = await stateDecoder.decodeState(stateVars, storageViewer)
108+
return result
167109
} catch (error) {
168110
callback(error)
169111
}
170112
}
171113

172114
Ethdebugger.prototype.storageViewAt = function (step, address) {
173-
return new StorageViewer({
174-
stepIndex: step,
175-
tx: this.tx,
176-
address: address
177-
}, this.storageResolver, this.traceManager)
115+
return new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager)
178116
}
179117

180118
Ethdebugger.prototype.updateWeb3 = function (web3) {
@@ -192,21 +130,18 @@ Ethdebugger.prototype.debug = function (tx) {
192130
if (this.traceManager.isLoading) {
193131
return
194132
}
195-
if (!tx.to) {
196-
tx.to = traceHelper.contractCreationToken('0')
197-
}
133+
tx.to = tx.to || traceHelper.contractCreationToken('0')
198134
this.tx = tx
199-
this.traceManager.resolveTrace(tx, async (error, result) => {
200-
if (result) {
201-
this.setCompilationResult(await this.compilationResult(tx.to))
202-
this.event.trigger('newTraceLoaded', [this.traceManager.trace])
203-
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
204-
this.breakpointManager.jumpNextBreakpoint(false)
205-
}
206-
this.storageResolver = new StorageResolver({web3: this.traceManager.web3})
207-
} else {
208-
this.statusMessage = error ? error.message : 'Trace not loaded'
135+
136+
this.traceManager.resolveTrace(tx).then(async (result) => {
137+
this.setCompilationResult(await this.compilationResult(tx.to))
138+
this.event.trigger('newTraceLoaded', [this.traceManager.trace])
139+
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
140+
this.breakpointManager.jumpNextBreakpoint(false)
209141
}
142+
this.storageResolver = new StorageResolver({web3: this.traceManager.web3})
143+
}).catch((error) => {
144+
this.statusMessage = error ? error.message : 'Trace not loaded'
210145
})
211146
}
212147

libs/remix-debug/src/solidity-decoder/internalCallTree.js

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,15 @@ class InternalCallTree {
124124
return functions
125125
}
126126

127-
extractSourceLocation (step) {
128-
return new Promise((resolve, reject) => {
129-
try {
130-
const address = this.traceManager.getCurrentCalledAddressAt(step)
131-
try {
132-
this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts).then(resolve).catch((error) => {
133-
return reject('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error)
134-
})
135-
} catch (error) {
136-
return reject('InternalCallTree - Cannot retrieve address for step ' + step + ' ' + error)
137-
}
138-
} catch (error) {
139-
return reject('InternalCallTree - Cannot retrieve address for step ' + step + ' ' + error)
140-
}
141-
})
127+
async extractSourceLocation (step) {
128+
try {
129+
const address = this.traceManager.getCurrentCalledAddressAt(step)
130+
const location = await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts)
131+
return location
132+
} catch (error) {
133+
throw new Error('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error)
134+
}
142135
}
143-
144136
}
145137

146138
async function buildTree (tree, step, scopeId, isExternalCall) {

libs/remix-debug/src/solidity-decoder/solidityProxy.js

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,15 @@ class SolidityProxy {
3939
* @param {Int} vmTraceIndex - index in the vm trave where to resolve the executed contract name
4040
* @param {Function} cb - callback returns (error, contractName)
4141
*/
42-
contractNameAt (vmTraceIndex) {
43-
return new Promise((resolve, reject) => {
44-
try {
45-
const address = this.traceManager.getCurrentCalledAddressAt(vmTraceIndex)
46-
if (this.cache.contractNameByAddress[address]) {
47-
return resolve(this.cache.contractNameByAddress[address])
48-
}
49-
this.codeManager.getCode(address, (error, code) => {
50-
if (error) {
51-
return reject(error)
52-
}
53-
const contractName = contractNameFromCode(this.contracts, code.bytecode, address)
54-
this.cache.contractNameByAddress[address] = contractName
55-
resolve(contractName)
56-
})
57-
} catch (error) {
58-
reject(error)
59-
}
60-
})
42+
async contractNameAt (vmTraceIndex) {
43+
const address = this.traceManager.getCurrentCalledAddressAt(vmTraceIndex)
44+
if (this.cache.contractNameByAddress[address]) {
45+
return this.cache.contractNameByAddress[address]
46+
}
47+
const code = await this.codeManager.getCode(address)
48+
const contractName = contractNameFromCode(this.contracts, code.bytecode, address)
49+
this.cache.contractNameByAddress[address] = contractName
50+
return contractName
6151
}
6252

6353
/**
@@ -95,12 +85,9 @@ class SolidityProxy {
9585
* @param {Int} vmTraceIndex - index in the vm trave where to resolve the state variables
9686
* @return {Object} - returns state variables of @args vmTraceIndex
9787
*/
98-
extractStateVariablesAt (vmtraceIndex) {
99-
return new Promise((resolve, reject) => {
100-
this.contractNameAt(vmtraceIndex).then((contractName) => {
101-
resolve(this.extractStateVariables(contractName))
102-
}).catch(reject)
103-
})
88+
async extractStateVariablesAt (vmtraceIndex) {
89+
const contractName = await this.contractNameAt(vmtraceIndex)
90+
return this.extractStateVariables(contractName)
10491
}
10592

10693
/**
@@ -113,10 +100,8 @@ class SolidityProxy {
113100
const file = this.fileNameFromIndex(sourceLocation.file)
114101
if (this.sources[file]) {
115102
return this.sources[file].legacyAST
116-
} else {
117-
// console.log('AST not found for file id ' + sourceLocation.file)
118-
return null
119103
}
104+
return null
120105
}
121106

122107
/**

libs/remix-debug/src/storage/storageResolver.js

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,14 @@ class StorageResolver {
3939
* @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
4040
* @return {Function} - callback
4141
*/
42-
initialPreimagesMappings (tx, stepIndex, address, corrections) {
43-
return new Promise((resolve, reject) => {
44-
if (this.preimagesMappingByAddress[address]) {
45-
return resolve(this.preimagesMappingByAddress[address])
46-
}
47-
this.storageRange(tx, stepIndex, address).then((storage) => {
48-
const mappings = mappingPreimages.decodeMappingsKeys(this.web3, storage, corrections)
49-
this.preimagesMappingByAddress[address] = mappings
50-
resolve(mappings)
51-
}).catch(reject)
52-
})
42+
async initialPreimagesMappings (tx, stepIndex, address, corrections) {
43+
if (this.preimagesMappingByAddress[address]) {
44+
return this.preimagesMappingByAddress[address]
45+
}
46+
const storage = await this.storageRange(tx, stepIndex, address)
47+
const mappings = mappingPreimages.decodeMappingsKeys(this.web3, storage, corrections)
48+
this.preimagesMappingByAddress[address] = mappings
49+
return mappings
5350
}
5451

5552
/**
@@ -61,12 +58,9 @@ class StorageResolver {
6158
* @param {String} - address - lookup address
6259
* @param {Function} - callback - {key, hashedKey, value} -
6360
*/
64-
storageSlot (slot, tx, stepIndex, address) {
65-
return new Promise((resolve, reject) => {
66-
this.storageRangeInternal(this, slot, tx, stepIndex, address).then((storage) => {
67-
resolve(storage[slot] !== undefined ? storage[slot] : null)
68-
}).catch(reject)
69-
})
61+
async storageSlot (slot, tx, stepIndex, address) {
62+
const storage = await this.storageRangeInternal(this, slot, tx, stepIndex, address)
63+
return (storage[slot] !== undefined ? storage[slot] : null)
7064
}
7165

7266
/**
@@ -85,27 +79,21 @@ class StorageResolver {
8579
* even if the next 1000 items are not in the cache.
8680
* - If @arg slot is not cached, the corresponding value will be resolved and the next 1000 slots.
8781
*/
88-
storageRangeInternal (self, slotKey, tx, stepIndex, address) {
89-
return new Promise((resolve, reject) => {
90-
var cached = this.fromCache(self, address)
91-
if (cached && cached.storage[slotKey]) { // we have the current slot in the cache and maybe the next 1000...
92-
return resolve(cached.storage)
93-
}
94-
this.storageRangeWeb3Call(tx, address, slotKey, self.maxSize).then((result) => {
95-
const [storage, nextKey] = result
96-
if (!storage[slotKey] && slotKey !== self.zeroSlot) { // we don't cache the zero slot (could lead to inconsistency)
97-
storage[slotKey] = {
98-
key: slotKey,
99-
value: self.zeroSlot
100-
}
101-
}
102-
self.toCache(self, address, storage)
103-
if (slotKey === self.zeroSlot && !nextKey) { // only working if keys are sorted !!
104-
self.storageByAddress[address].complete = true
105-
}
106-
return resolve(storage)
107-
}).catch(reject)
108-
})
82+
async storageRangeInternal (self, slotKey, tx, stepIndex, address) {
83+
var cached = this.fromCache(self, address)
84+
if (cached && cached.storage[slotKey]) { // we have the current slot in the cache and maybe the next 1000...
85+
return cached.storage
86+
}
87+
const result = await this.storageRangeWeb3Call(tx, address, slotKey, self.maxSize)
88+
const [storage, nextKey] = result
89+
if (!storage[slotKey] && slotKey !== self.zeroSlot) { // we don't cache the zero slot (could lead to inconsistency)
90+
storage[slotKey] = {key: slotKey, value: self.zeroSlot}
91+
}
92+
self.toCache(self, address, storage)
93+
if (slotKey === self.zeroSlot && !nextKey) { // only working if keys are sorted !!
94+
self.storageByAddress[address].complete = true
95+
}
96+
return storage
10997
}
11098

11199
/**

0 commit comments

Comments
 (0)