From 8eab1ca4e65da5f7e1b06b6f7152aa4c0479b1ca Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 May 2017 14:16:56 +0200 Subject: [PATCH] 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) } }) }