Commit 30f2c0c6 authored by chriseth's avatar chriseth Committed by GitHub

Merge pull request #143 from ethereum/decodeArrayStruct

Decode Array/Struct [WIP]
parents d1453f88 9ab63997
'use strict' 'use strict'
var util = require('./util')
var BN = require('ethereumjs-util').BN
function ArrayType (underlyingType, arraySize) { function ArrayType (underlyingType, arraySize) {
this.typeName = 'array' this.typeName = 'array'
...@@ -19,7 +21,37 @@ function ArrayType (underlyingType, arraySize) { ...@@ -19,7 +21,37 @@ function ArrayType (underlyingType, arraySize) {
} }
ArrayType.prototype.decodeFromStorage = function (location, storageContent) { ArrayType.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>' var ret = []
var size = null
var slotValue = util.extractHexValue(location, storageContent, this.storageBytes)
var currentLocation = {
offset: 0,
slot: location.slot
}
if (this.arraySize === 'dynamic') {
size = util.toBN('0x' + slotValue)
currentLocation.slot = util.sha3(location.slot)
} else {
size = new BN(this.arraySize)
}
var k = util.toBN(0)
for (; k.lt(size) && k.ltn(300); k.iaddn(1)) {
ret.push(this.underlyingType.decodeFromStorage(currentLocation, storageContent))
if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) {
currentLocation.offset += this.underlyingType.storageBytes
if (currentLocation.offset + this.underlyingType.storageBytes > 32) {
currentLocation.offset = 0
currentLocation.slot = '0x' + util.add(currentLocation.slot, 1).toString(16)
}
} else {
currentLocation.slot = '0x' + util.add(currentLocation.slot, this.underlyingType.storageSlots).toString(16)
currentLocation.offset = 0
}
}
return {
value: ret,
length: '0x' + size.toString(16)
}
} }
module.exports = ArrayType module.exports = ArrayType
'use strict' 'use strict'
var util = require('./util')
function Struct (memberDetails) { function Struct (memberDetails) {
this.storageSlots = memberDetails.storageSlots this.storageSlots = memberDetails.storageSlots
...@@ -8,7 +9,15 @@ function Struct (memberDetails) { ...@@ -8,7 +9,15 @@ function Struct (memberDetails) {
} }
Struct.prototype.decodeFromStorage = function (location, storageContent) { Struct.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>' var ret = {}
this.members.map(function (item, i) {
var globalLocation = {
offset: location.offset + item.location.offset,
slot: util.add(location.slot, item.location.slot)
}
ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent)
})
return ret
} }
module.exports = Struct module.exports = Struct
...@@ -6,7 +6,9 @@ module.exports = { ...@@ -6,7 +6,9 @@ module.exports = {
readFromStorage: readFromStorage, readFromStorage: readFromStorage,
decodeInt: decodeInt, decodeInt: decodeInt,
extractHexValue: extractHexValue, extractHexValue: extractHexValue,
sha3: sha3 sha3: sha3,
toBN: toBN,
add: add
} }
function decodeInt (location, storageContent, byteLength, signed) { function decodeInt (location, storageContent, byteLength, signed) {
...@@ -67,3 +69,19 @@ function sha3 (slot) { ...@@ -67,3 +69,19 @@ function sha3 (slot) {
var key = ethutil.sha3(remoteSlot) var key = ethutil.sha3(remoteSlot)
return ethutil.bufferToHex(key) return ethutil.bufferToHex(key)
} }
function toBN (value) {
if (value instanceof BN) {
return value
} else if (value.indexOf && value.indexOf('0x') === 0) {
value = ethutil.unpad(value.replace('Ox', ''))
value = new BN(value === '' ? '0' : value, 16)
} else if (!isNaN(value)) {
value = new BN(value)
}
return value
}
function add (value1, value2) {
return toBN(value1).add(toBN(value2))
}
This diff is collapsed.
...@@ -7,6 +7,7 @@ tape('solidity', function (t) { ...@@ -7,6 +7,7 @@ tape('solidity', function (t) {
t.test('storage decoder', function (st) { t.test('storage decoder', function (st) {
testIntStorage(st) testIntStorage(st)
testByteStorage(st) testByteStorage(st)
testStructArrayStorage(st)
st.end() st.end()
}) })
}) })
...@@ -156,3 +157,100 @@ function shrinkStorage (storage) { ...@@ -156,3 +157,100 @@ function shrinkStorage (storage) {
} }
return shrinkedStorage return shrinkedStorage
} }
function testStructArrayStorage (st) {
var structArrayStorage = require('./contracts/structArrayStorage')
var output = compiler.compile(structArrayStorage.contract, 0)
var decoded = stateDecoder.solidityState(structArrayStorage.storage, output.sources, 'structArrayStorage')
st.equal(decoded['intStructDec']['i8'], '32')
st.equal(decoded['intStructDec']['i16'], '-54')
st.equal(decoded['intStructDec']['ui32'], '128')
st.equal(decoded['intStructDec']['i256'], '-1243565465756')
st.equal(decoded['intStructDec']['ui16'], '34556')
st.equal(decoded['intStructDec']['i32'], '-345446546')
st.equal(decoded['i5'].length, '0x7')
st.equal(decoded['i5'].value[0], '-2134')
st.equal(decoded['i5'].value[1], '345')
st.equal(decoded['i5'].value[2], '-3246')
st.equal(decoded['i5'].value[3], '4357')
st.equal(decoded['i5'].value[4], '324')
st.equal(decoded['i5'].value[5], '-2344')
st.equal(decoded['i5'].value[6], '3254')
st.equal(decoded['idyn5'].length, '0x9')
st.equal(decoded['idyn5'].value[0], '-2134')
st.equal(decoded['idyn5'].value[1], '345')
st.equal(decoded['idyn5'].value[2], '-3246')
st.equal(decoded['idyn5'].value[3], '4357')
st.equal(decoded['idyn5'].value[4], '324')
st.equal(decoded['idyn5'].value[5], '-2344')
st.equal(decoded['idyn5'].value[6], '3254')
st.equal(decoded['idyn5'].value[7], '-254')
st.equal(decoded['idyn5'].value[8], '-2354')
st.equal(decoded['dyn1'].length, '0x4')
st.equal(decoded['dyn1'].value[0].length, '0x1')
st.equal(decoded['dyn1'].value[0].value[0], '3')
st.equal(decoded['dyn1'].value[1].length, '0x3')
st.equal(decoded['dyn1'].value[1].value[0], '12')
st.equal(decoded['dyn1'].value[1].value[1], '-12')
st.equal(decoded['dyn1'].value[1].value[2], '-1234')
st.equal(decoded['dyn1'].value[2].length, '0xa')
st.equal(decoded['dyn1'].value[2].value[0], '1')
st.equal(decoded['dyn1'].value[2].value[1], '12')
st.equal(decoded['dyn1'].value[2].value[2], '1235')
st.equal(decoded['dyn1'].value[2].value[3], '-12')
st.equal(decoded['dyn1'].value[2].value[4], '-123456')
st.equal(decoded['dyn1'].value[2].value[5], '-23435435')
st.equal(decoded['dyn1'].value[2].value[6], '543543')
st.equal(decoded['dyn1'].value[2].value[7], '2')
st.equal(decoded['dyn1'].value[2].value[8], '-1')
st.equal(decoded['dyn1'].value[2].value[9], '232432')
st.equal(decoded['dyn1'].value[3].length, '0x2')
st.equal(decoded['dyn1'].value[3].value[0], '232432')
st.equal(decoded['dyn1'].value[3].value[0], '232432')
st.equal(decoded['dyn2'].length, '0x2')
st.equal(decoded['dyn2'].value[0].length, '0x4')
st.equal(decoded['dyn2'].value[0].value[0].value[0], '23')
st.equal(decoded['dyn2'].value[0].value[0].value[1], '-23')
st.equal(decoded['dyn2'].value[0].value[0].value[2], '-28')
st.equal(decoded['dyn2'].value[0].value[1].value[0], '23')
st.equal(decoded['dyn2'].value[0].value[1].value[1], '-23')
st.equal(decoded['dyn2'].value[0].value[1].value[2], '-28')
st.equal(decoded['dyn2'].value[0].value[2].value[0], '23')
st.equal(decoded['dyn2'].value[0].value[2].value[1], '-23')
st.equal(decoded['dyn2'].value[0].value[2].value[2], '-28')
st.equal(decoded['dyn2'].value[0].value[3].value[0], '23')
st.equal(decoded['dyn2'].value[0].value[3].value[1], '-23')
st.equal(decoded['dyn2'].value[0].value[3].value[2], '-28')
st.equal(decoded['dyn2'].value[1].length, '0x4')
st.equal(decoded['dyn2'].value[1].value[0].value[0], '23')
st.equal(decoded['dyn2'].value[1].value[0].value[1], '-23')
st.equal(decoded['dyn2'].value[1].value[0].value[2], '-28')
st.equal(decoded['dyn2'].value[1].value[1].value[0], '23')
st.equal(decoded['dyn2'].value[1].value[1].value[1], '-23')
st.equal(decoded['dyn2'].value[1].value[1].value[2], '-28')
st.equal(decoded['dyn2'].value[1].value[2].value[0], '23')
st.equal(decoded['dyn2'].value[1].value[2].value[1], '-23')
st.equal(decoded['dyn2'].value[1].value[2].value[2], '-28')
st.equal(decoded['dyn2'].value[1].value[3].value[0], '23')
st.equal(decoded['dyn2'].value[1].value[3].value[1], '-23')
st.equal(decoded['dyn2'].value[1].value[3].value[2], '-28')
st.equal(decoded['arrayStruct'].value[0].value[0].i8, '34')
st.equal(decoded['arrayStruct'].value[0].value[0].str.value, 'test_str_short')
st.equal(decoded['arrayStruct'].value[0].value[1].i8, '-123')
st.equal(decoded['arrayStruct'].value[0].value[1].str.value, 'test_str_long test_str_lo ngtest_str_longtest_str_ longtest_str_longtest_ str_longtest_str_l ongtest_str_long')
st.equal(decoded['arrayStruct'].value[1].value[0].i8, '50')
st.equal(decoded['arrayStruct'].value[1].value[0].str.value, 'test_str_short')
st.equal(decoded['arrayStruct'].value[2].value[0].i8, '60')
st.equal(decoded['arrayStruct'].value[2].value[0].str.value, 'test_str_short')
st.equal(decoded['arrayStruct'].value[2].value[1].i8, '84')
st.equal(decoded['arrayStruct'].value[2].value[1].str.value, 'test_str_long test_str_lo ngtest_str_longtest_str_ longtest_str_longtest_ str_longtest_str_l ongtest_str_long')
st.equal(decoded['arrayStruct'].value[2].value[2].i8, '-34')
st.equal(decoded['arrayStruct'].value[2].value[2].str.value, 'test_str_short')
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment