From e3a8710d5613dbd9a19c9bb3cf6ff6925ee7ba8c Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 11:18:49 +0200 Subject: [PATCH 1/5] remove console.log --- src/solidity/types/Mapping.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solidity/types/Mapping.js b/src/solidity/types/Mapping.js index 17ddd3373b..2cf2383cb1 100644 --- a/src/solidity/types/Mapping.js +++ b/src/solidity/types/Mapping.js @@ -21,7 +21,6 @@ class Mapping extends RefType { } } var mapSlot = util.normalizeHex(ethutil.bufferToHex(location.slot)) - console.log(mapSlot, mappingsPreimages) var mappingPreimages = mappingsPreimages[mapSlot] var ret = {} for (var i in mappingPreimages) { From e40d76efb29d58831d86bf58efdac5a94087047c Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 11:19:54 +0200 Subject: [PATCH 2/5] do not reextract state vars if context is the same --- src/ui/SolidityState.js | 44 +++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/ui/SolidityState.js b/src/ui/SolidityState.js index ed684f1b01..97c8ca10b0 100644 --- a/src/ui/SolidityState.js +++ b/src/ui/SolidityState.js @@ -18,6 +18,7 @@ function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { }) this.init() this.view + this.stateVariablesByAddresses = {} } SolidityState.prototype.render = function () { @@ -54,26 +55,35 @@ SolidityState.prototype.init = function () { self.basicPanel.update({}) console.log(error) } else { - self.solidityProxy.extractStateVariablesAt(index, function (error, stateVars) { - if (error) { - self.basicPanel.update({}) - console.log(error) - } else { - var storageViewer = new StorageViewer({ - stepIndex: self.parent.currentStepIndex, - tx: self.parent.tx, - address: address - }, self.storageResolver, self.traceManager) - stateDecoder.decodeState(stateVars, storageViewer).then((result) => { - if (!result.error) { - self.basicPanel.update(result) - } - }) - } - }) + if (self.stateVariablesByAddresses[address]) { + extractStateVariables(self, self.stateVariablesByAddresses[address], address) + } else { + self.solidityProxy.extractStateVariablesAt(index, function (error, stateVars) { + if (error) { + self.basicPanel.update({}) + console.log(error) + } else { + self.stateVariablesByAddresses[address] = stateVars + extractStateVariables(self, stateVars) + } + }) + } } }) }) } +function extractStateVariables (self, stateVars, address) { + var storageViewer = new StorageViewer({ + stepIndex: self.parent.currentStepIndex, + tx: self.parent.tx, + address: address + }, self.storageResolver, self.traceManager) + stateDecoder.decodeState(stateVars, storageViewer).then((result) => { + if (!result.error) { + self.basicPanel.update(result) + } + }) +} + module.exports = SolidityState From 8eab1ca4e65da5f7e1b06b6f7152aa4c0479b1ca Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 14:16:56 +0200 Subject: [PATCH 3/5] mapping: cache the initial decoded state --- src/solidity/types/Mapping.js | 51 ++++++++++++++++++++++------------- src/storage/storageViewer.js | 50 +++++++++++++++++++--------------- src/ui/SolidityState.js | 2 +- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/solidity/types/Mapping.js b/src/solidity/types/Mapping.js index 2cf2383cb1..274807c751 100644 --- a/src/solidity/types/Mapping.js +++ b/src/solidity/types/Mapping.js @@ -8,30 +8,25 @@ class Mapping extends RefType { super(1, 32, fullType, 'storage') this.keyType = underlyingTypes.keyType this.valueType = underlyingTypes.valueType + this.initialDecodedState = null } async decodeFromStorage (location, storageResolver) { - var mappingsPreimages - try { - mappingsPreimages = await storageResolver.mappingsLocation() - } catch (e) { - return { - value: e.message, - type: this.typeName + if (!this.initialDecodedState) { // cache the decoded initial storage + var mappingsInitialPreimages + try { + mappingsInitialPreimages = await storageResolver.initialMappingsLocation() + this.initialDecodedState = await this.decodeMappingsLocation(mappingsInitialPreimages, location, storageResolver) + } catch (e) { + return { + value: e.message, + type: this.typeName + } } } - var mapSlot = util.normalizeHex(ethutil.bufferToHex(location.slot)) - var mappingPreimages = mappingsPreimages[mapSlot] - var ret = {} - for (var i in mappingPreimages) { - var mapLocation = getMappingLocation(i, location.slot) - var globalLocation = { - offset: location.offset, - slot: mapLocation - } - ret[i] = await this.valueType.decodeFromStorage(globalLocation, storageResolver) - } - + var mappingPreimages = await storageResolver.mappingsLocation() + var ret = await this.decodeMappingsLocation(mappingPreimages, location, storageResolver) // fetch mapping storage changes + ret = Object.assign({}, this.initialDecodedState, ret) // merge changes return { value: ret, type: this.typeName @@ -47,6 +42,24 @@ class Mapping extends RefType { type: this.typeName } } + + async decodeMappingsLocation (preimages, location, storageResolver) { + var mapSlot = util.normalizeHex(ethutil.bufferToHex(location.slot)) + if (!preimages[mapSlot]) { + return {} + } + var ret = {} + for (var i in preimages[mapSlot]) { + var mapLocation = getMappingLocation(i, location.slot) + var globalLocation = { + offset: location.offset, + slot: mapLocation + } + ret[i] = await this.valueType.decodeFromStorage(globalLocation, storageResolver) + console.log('global location', globalLocation, i, ret[i]) + } + return ret + } } function getMappingLocation (key, position) { diff --git a/src/storage/storageViewer.js b/src/storage/storageViewer.js index 5aeeece5fb..b5ed61e0e5 100644 --- a/src/storage/storageViewer.js +++ b/src/storage/storageViewer.js @@ -11,7 +11,8 @@ class StorageViewer { constructor (_context, _storageResolver, _traceManager) { this.context = _context this.storageResolver = _storageResolver - this.completeMapingsLocationPromise = null + this.initialMappingsLocationPromise = null + this.currentMappingsLocationPromise = null _traceManager.accumulateStorageChanges(this.context.stepIndex, this.context.address, {}, (error, storageChanges) => { if (!error) { this.storageChanges = storageChanges @@ -67,38 +68,43 @@ class StorageViewer { } /** - * return all the possible mappings locations for the current context (cached) + * return all the possible mappings locations for the current context (cached) do not return state changes during the current transaction * * @param {Function} callback */ - async mappingsLocation () { - if (!this.completeMapingsLocationPromise) { - this.completeMapingsLocationPromise = new Promise((resolve, reject) => { - if (this.completeMappingsLocation) { - return this.completeMappingsLocation - } + async initialMappingsLocation () { + if (!this.initialMappingsLocationPromise) { + this.initialMappingsLocationPromise = new Promise((resolve, reject) => { this.storageResolver.initialPreimagesMappings(this.context.tx, this.context.stepIndex, this.context.address, (error, initialMappingsLocation) => { if (error) { reject(error) } else { - this.extractMappingsLocationChanges(this.storageChanges, (error, mappingsLocationChanges) => { - if (error) { - return reject(error) - } - this.completeMappingsLocation = Object.assign({}, initialMappingsLocation) - for (var key in mappingsLocationChanges) { - if (!initialMappingsLocation[key]) { - initialMappingsLocation[key] = {} - } - this.completeMappingsLocation[key] = Object.assign({}, initialMappingsLocation[key], mappingsLocationChanges[key]) - } - resolve(this.completeMappingsLocation) - }) + resolve(initialMappingsLocation) + } + }) + }) + } + return this.initialMappingsLocationPromise + } + + /** + * return all the possible mappings locations for the current context (cached) and current mapping slot. returns state changes during the current transaction + * + * @param {Function} callback + */ + async mappingsLocation () { + if (!this.currentMappingsLocationPromise) { + this.currentMappingsLocationPromise = new Promise((resolve, reject) => { + this.extractMappingsLocationChanges(this.storageChanges, (error, mappingsLocationChanges) => { + if (error) { + reject(error) + } else { + resolve(mappingsLocationChanges) } }) }) } - return this.completeMapingsLocationPromise + return this.currentMappingsLocationPromise } /** diff --git a/src/ui/SolidityState.js b/src/ui/SolidityState.js index 97c8ca10b0..a2199b3ef1 100644 --- a/src/ui/SolidityState.js +++ b/src/ui/SolidityState.js @@ -64,7 +64,7 @@ SolidityState.prototype.init = function () { console.log(error) } else { self.stateVariablesByAddresses[address] = stateVars - extractStateVariables(self, stateVars) + extractStateVariables(self, stateVars, address) } }) } From 960086ee19bd036740d24f4ba01c49fb256cd4d2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 14:36:00 +0200 Subject: [PATCH 4/5] fix using debug_preimage with geth --- src/storage/mappingPreimages.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storage/mappingPreimages.js b/src/storage/mappingPreimages.js index 5a70a92ec3..d9a5416406 100644 --- a/src/storage/mappingPreimages.js +++ b/src/storage/mappingPreimages.js @@ -43,9 +43,9 @@ async function decodeMappingsKeys (storage, callback) { */ function getPreimage (key) { return new Promise((resolve, reject) => { - global.web3.debug.preimage(key, function (error, preimage) { + global.web3.debug.preimage(key.indexOf('0x') === 0 ? key : '0x' + key, function (error, preimage) { if (error) { - reject(error) + resolve(null) } else { resolve(preimage) } From 21bf712b3774c4f46e27928e6d784bffcee14215 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 14:36:37 +0200 Subject: [PATCH 5/5] standard --- src/storage/storageViewer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/storage/storageViewer.js b/src/storage/storageViewer.js index b5ed61e0e5..aa50b9d93f 100644 --- a/src/storage/storageViewer.js +++ b/src/storage/storageViewer.js @@ -127,6 +127,4 @@ class StorageViewer { } } - - module.exports = StorageViewer