use storageResolver

pull/7/head
yann300 8 years ago
parent 9004162563
commit 66a2bf8af4
  1. 4
      src/solidity/localDecoder.js
  2. 6
      src/solidity/stateDecoder.js
  3. 6
      src/solidity/types/ArrayType.js
  4. 8
      src/solidity/types/DynamicByteArray.js
  5. 2
      src/solidity/types/Mapping.js
  6. 9
      src/solidity/types/RefType.js
  7. 4
      src/solidity/types/StringType.js
  8. 4
      src/solidity/types/Struct.js
  9. 6
      src/solidity/types/ValueType.js
  10. 32
      src/solidity/types/util.js
  11. 11
      src/ui/SolidityLocals.js
  12. 7
      src/ui/SolidityState.js
  13. 10
      src/ui/VmDebugger.js

@ -1,6 +1,6 @@
'use strict' 'use strict'
function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory, storage, currentSourceLocation) { function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory, storageResolver, currentSourceLocation) {
var scope = internalTreeCall.findScope(vmtraceIndex) var scope = internalTreeCall.findScope(vmtraceIndex)
if (!scope) { if (!scope) {
var error = { 'message': 'Can\'t display locals. reason: compilation result might not have been provided' } var error = { 'message': 'Can\'t display locals. reason: compilation result might not have been provided' }
@ -17,7 +17,7 @@ function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory, storage,
name = '<' + anonymousIncr + '>' name = '<' + anonymousIncr + '>'
anonymousIncr++ anonymousIncr++
} }
locals[name] = variable.type.decodeFromStack(variable.stackDepth, stack, memory, storage) locals[name] = variable.type.decodeFromStack(variable.stackDepth, stack, memory, storageResolver)
} }
} }
return locals return locals

@ -5,14 +5,14 @@ var decodeInfo = require('./decodeInfo')
* decode the contract state storage * decode the contract state storage
* *
* @param {Array} storage location - location of all state variables * @param {Array} storage location - location of all state variables
* @param {Map} storageContent - storage * @param {Object} storageResolver - resolve storage queries
* @return {Map} - decoded state variable * @return {Map} - decoded state variable
*/ */
async function decodeState (stateVars, storageContent) { async function decodeState (stateVars, storageResolver) {
var ret = {} var ret = {}
for (var k in stateVars) { for (var k in stateVars) {
var stateVar = stateVars[k] var stateVar = stateVars[k]
ret[stateVar.name] = await stateVar.type.decodeFromStorage(stateVar.storagelocation, storageContent) ret[stateVar.name] = await stateVar.type.decodeFromStorage(stateVar.storagelocation, storageResolver)
} }
return ret return ret
} }

@ -24,10 +24,10 @@ class ArrayType extends RefType {
this.arraySize = arraySize this.arraySize = arraySize
} }
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
var ret = [] var ret = []
var size = null var size = null
var slotValue = await util.extractHexValue(location, storageContent, this.storageBytes) var slotValue = await util.extractHexValue(location, storageResolver, this.storageBytes)
var currentLocation = { var currentLocation = {
offset: 0, offset: 0,
slot: location.slot slot: location.slot
@ -40,7 +40,7 @@ class ArrayType extends RefType {
} }
var k = util.toBN(0) var k = util.toBN(0)
for (; k.lt(size) && k.ltn(300); k.iaddn(1)) { for (; k.lt(size) && k.ltn(300); k.iaddn(1)) {
var item = await this.underlyingType.decodeFromStorage(currentLocation, storageContent) var item = await this.underlyingType.decodeFromStorage(currentLocation, storageResolver)
ret.push(item) ret.push(item)
if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) { if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) {
currentLocation.offset += this.underlyingType.storageBytes currentLocation.offset += this.underlyingType.storageBytes

@ -9,19 +9,19 @@ class DynamicByteArray extends RefType {
super(1, 32, 'bytes', location) super(1, 32, 'bytes', location)
} }
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
var value = await util.extractHexValue(location, storageContent, this.storageBytes) var value = await util.extractHexValue(location, storageResolver, this.storageBytes)
var bn = new BN(value, 16) var bn = new BN(value, 16)
if (bn.testn(0)) { if (bn.testn(0)) {
var length = bn.div(new BN(2)) var length = bn.div(new BN(2))
var dataPos = new BN(helper.sha3(location.slot).replace('0x', ''), 16) var dataPos = new BN(helper.sha3(location.slot).replace('0x', ''), 16)
var ret = '' var ret = ''
var currentSlot = await util.readFromStorage(dataPos, storageContent) var currentSlot = await util.readFromStorage(dataPos, storageResolver)
while (length.gt(ret.length) && ret.length < 32000) { while (length.gt(ret.length) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '') currentSlot = currentSlot.replace('0x', '')
ret += currentSlot ret += currentSlot
dataPos = dataPos.add(new BN(1)) dataPos = dataPos.add(new BN(1))
currentSlot = await util.readFromStorage(dataPos, storageContent) currentSlot = await util.readFromStorage(dataPos, storageResolver)
} }
return { return {
value: '0x' + ret.replace(/(00)+$/, ''), value: '0x' + ret.replace(/(00)+$/, ''),

@ -6,7 +6,7 @@ class Mapping extends RefType {
super(1, 32, 'mapping', 'storage') super(1, 32, 'mapping', 'storage')
} }
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
return { return {
value: '<not implemented>', value: '<not implemented>',
length: '0x', length: '0x',

@ -16,23 +16,20 @@ class RefType {
* @param {Int} stackDepth - position of the type in the stack * @param {Int} stackDepth - position of the type in the stack
* @param {Array} stack - stack * @param {Array} stack - stack
* @param {String} - memory * @param {String} - memory
* @param {Object} - storage * @param {Object} - storageResolver
* @return {Object} decoded value * @return {Object} decoded value
*/ */
async decodeFromStack (stackDepth, stack, memory, storage) { async decodeFromStack (stackDepth, stack, memory, storageResolver) {
if (stack.length - 1 < stackDepth) { if (stack.length - 1 < stackDepth) {
return { return {
error: '<decoding failed - stack underflow ' + stackDepth + '>', error: '<decoding failed - stack underflow ' + stackDepth + '>',
type: this.typeName type: this.typeName
} }
} }
if (!storage) {
storage = {} // TODO this is a fallback, should manage properly locals store in storage
}
var offset = stack[stack.length - 1 - stackDepth] var offset = stack[stack.length - 1 - stackDepth]
if (this.isInStorage()) { if (this.isInStorage()) {
offset = util.toBN(offset) offset = util.toBN(offset)
return await this.decodeFromStorage({ offset: 0, slot: offset }, storage) return await this.decodeFromStorage({ offset: 0, slot: offset }, storageResolver)
} 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)

@ -7,8 +7,8 @@ class StringType extends DynamicBytes {
this.typeName = 'string' this.typeName = 'string'
} }
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
var decoded = await super.decodeFromStorage(location, storageContent) var decoded = await super.decodeFromStorage(location, storageResolver)
return format(decoded) return format(decoded)
} }

@ -8,14 +8,14 @@ class Struct extends RefType {
this.members = memberDetails.members this.members = memberDetails.members
} }
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
var ret = {} var ret = {}
this.members.map(async (item, i) => { this.members.map(async (item, i) => {
var globalLocation = { var globalLocation = {
offset: location.offset + item.storagelocation.offset, offset: location.offset + item.storagelocation.offset,
slot: util.add(location.slot, item.storagelocation.slot) slot: util.add(location.slot, item.storagelocation.slot)
} }
ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageContent) ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageResolver)
}) })
return { return {
value: ret, value: ret,

@ -13,11 +13,11 @@ class ValueType {
* decode the type with the @arg location from the storage * decode the type with the @arg location from the storage
* *
* @param {Object} location - containing offset and slot * @param {Object} location - containing offset and slot
* @param {Object} storageContent - storageContent (storage) * @param {Object} storageResolver - resolve storage queries
* @return {Object} - decoded value * @return {Object} - decoded value
*/ */
async decodeFromStorage (location, storageContent) { async decodeFromStorage (location, storageResolver) {
var value = await util.extractHexValue(location, storageContent, this.storageBytes) var value = await util.extractHexValue(location, storageResolver, this.storageBytes)
return { return {
value: this.decodeValue(value), value: this.decodeValue(value),
type: this.typeName type: this.typeName

@ -21,24 +21,26 @@ function decodeIntFromHex (value, byteLength, signed) {
return bigNumber.toString(10) return bigNumber.toString(10)
} }
async function readFromStorage (slot, storageContent) { function readFromStorage (slot, storageResolver) {
var ret
var hexSlot = ethutil.bufferToHex(slot) var hexSlot = ethutil.bufferToHex(slot)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (storageContent[hexSlot] !== undefined) { storageResolver.storageSlot(hexSlot, (error, slot) => {
ret = storageContent[hexSlot].replace(/^0x/, '') if (error) {
return reject(error)
} else { } else {
hexSlot = ethutil.bufferToHex(ethutil.setLengthLeft(slot, 32)) if (!slot) {
if (storageContent[hexSlot] !== undefined) { slot = {
ret = storageContent[hexSlot].replace(/^0x/, '') key: slot,
} else { value: ''
ret = '000000000000000000000000000000000000000000000000000000000000000' }
} }
slot.value = slot.value.replace('0x', '')
if (slot.value.length < 64) {
slot.value = (new Array(64 - slot.value.length + 1).join('0')) + slot.value
} }
if (ret.length < 64) { return resolve(slot.value)
ret = (new Array(64 - ret.length + 1).join('0')) + ret
} }
return resolve(ret) })
}) })
} }
@ -58,11 +60,11 @@ function extractHexByteSlice (slotValue, byteLength, offsetFromLSB) {
* @returns a hex encoded storage content at the given @arg location. it does not have Ox prefix but always has the full length. * @returns a hex encoded storage content at the given @arg location. it does not have Ox prefix but always has the full length.
* *
* @param {Object} location - object containing the slot and offset of the data to extract. * @param {Object} location - object containing the slot and offset of the data to extract.
* @param {Object} storageContent - full storage mapping. * @param {Object} storageResolver - storage resolver
* @param {Int} byteLength - Length of the byte slice to extract * @param {Int} byteLength - Length of the byte slice to extract
*/ */
async function extractHexValue (location, storageContent, byteLength) { async function extractHexValue (location, storageResolver, byteLength) {
var slotvalue = await readFromStorage(location.slot, storageContent) var slotvalue = await readFromStorage(location.slot, storageResolver)
return extractHexByteSlice(slotvalue, byteLength, location.offset) return extractHexByteSlice(slotvalue, byteLength, location.offset)
} }

@ -6,9 +6,10 @@ var yo = require('yo-yo')
class SolidityLocals { class SolidityLocals {
constructor (_parent, _traceManager, internalTreeCall) { constructor (_parent, _traceManager, _internalTreeCall, _storageResolver) {
this.parent = _parent this.parent = _parent
this.internalTreeCall = internalTreeCall this.internalTreeCall = _internalTreeCall
this.storageResolver = _storageResolver
this.traceManager = _traceManager this.traceManager = _traceManager
this.basicPanel = new DropdownPanel('Solidity Locals', { this.basicPanel = new DropdownPanel('Solidity Locals', {
json: true, json: true,
@ -40,12 +41,8 @@ class SolidityLocals {
var stack = result[0].value var stack = result[0].value
var memory = result[1].value var memory = result[1].value
try { try {
this.traceManager.getStorageAt(this.parent.currentStepIndex, this.parent.tx, (error, storage) => { var locals = localDecoder.solidityLocals(this.parent.currentStepIndex, this.internalTreeCall, stack, memory, this.storageResolver, sourceLocation)
if (!error) {
var locals = localDecoder.solidityLocals(this.parent.currentStepIndex, this.internalTreeCall, stack, memory, storage, sourceLocation)
this.basicPanel.update(locals) this.basicPanel.update(locals)
}
})
} catch (e) { } catch (e) {
warningDiv.innerHTML = e.message warningDiv.innerHTML = e.message
} }

@ -4,7 +4,8 @@ var stateDecoder = require('../solidity/stateDecoder')
var solidityTypeFormatter = require('./SolidityTypeFormatter') var solidityTypeFormatter = require('./SolidityTypeFormatter')
var yo = require('yo-yo') var yo = require('yo-yo')
function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy, _storageResolver) {
this.storageResolver = _storageResolver
this.parent = _parent this.parent = _parent
this.traceManager = _traceManager this.traceManager = _traceManager
this.codeManager = _codeManager this.codeManager = _codeManager
@ -42,7 +43,7 @@ SolidityState.prototype.init = function () {
return return
} }
self.traceManager.getStorageAt(index, this.parent.tx, function (error, storage) { self.traceManager.getCurrentCalledAddressAt(self.parent.currentStepIndex, (error, result) => {
if (error) { if (error) {
self.basicPanel.update({}) self.basicPanel.update({})
console.log(error) console.log(error)
@ -52,7 +53,7 @@ SolidityState.prototype.init = function () {
self.basicPanel.update({}) self.basicPanel.update({})
console.log(error) console.log(error)
} else { } else {
stateDecoder.decodeState(stateVars, storage).then((result) => { stateDecoder.decodeState(stateVars, self.storageResolver).then((result) => {
if (!result.error) { if (!result.error) {
self.basicPanel.update(result) self.basicPanel.update(result)
} }

@ -10,18 +10,20 @@ var StepDetail = require('./StepDetail')
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var SolidityState = require('./SolidityState') var SolidityState = require('./SolidityState')
var SolidityLocals = require('./SolidityLocals') var SolidityLocals = require('./SolidityLocals')
var StorageResolver = require('../storage/storageResolver.js')
var yo = require('yo-yo') var yo = require('yo-yo')
function VmDebugger (_parent, _traceManager, _codeManager, _solidityProxy, _callTree) { function VmDebugger (_parent, _traceManager, _codeManager, _solidityProxy, _callTree) {
var storageResolver = new StorageResolver(_parent, _traceManager)
this.asmCode = new CodeListView(_parent, _codeManager) this.asmCode = new CodeListView(_parent, _codeManager)
this.stackPanel = new StackPanel(_parent, _traceManager) this.stackPanel = new StackPanel(_parent, _traceManager)
this.storagePanel = new StoragePanel(_parent, _traceManager) this.storagePanel = new StoragePanel(_parent, _traceManager, storageResolver)
this.memoryPanel = new MemoryPanel(_parent, _traceManager) this.memoryPanel = new MemoryPanel(_parent, _traceManager)
this.calldataPanel = new CalldataPanel(_parent, _traceManager) this.calldataPanel = new CalldataPanel(_parent, _traceManager)
this.callstackPanel = new CallstackPanel(_parent, _traceManager) this.callstackPanel = new CallstackPanel(_parent, _traceManager)
this.stepDetail = new StepDetail(_parent, _traceManager) this.stepDetail = new StepDetail(_parent, _traceManager)
this.solidityState = new SolidityState(_parent, _traceManager, _codeManager, _solidityProxy) this.solidityState = new SolidityState(_parent, _traceManager, _codeManager, _solidityProxy, storageResolver)
this.solidityLocals = new SolidityLocals(_parent, _traceManager, _callTree) this.solidityLocals = new SolidityLocals(_parent, _traceManager, _callTree, storageResolver)
/* Return values - */ /* Return values - */
this.returnValuesPanel = new DropdownPanel('Return Value', {json: true}) this.returnValuesPanel = new DropdownPanel('Return Value', {json: true})
@ -38,7 +40,7 @@ function VmDebugger (_parent, _traceManager, _codeManager, _solidityProxy, _call
}) })
/* Return values - */ /* Return values - */
this.fullStoragesChangesPanel = new FullStoragesChangesPanel(_parent, _traceManager) this.fullStoragesChangesPanel = new FullStoragesChangesPanel(_parent, _traceManager, storageResolver)
this.view this.view
var self = this var self = this

Loading…
Cancel
Save