refactor storageResolver

pull/7/head
yann300 8 years ago
parent ada5dc3356
commit 0d3a26a54b
  1. 138
      src/storage/storageResolver.js

@ -7,28 +7,31 @@ class StorageResolver {
constructor (_traceManager) { constructor (_traceManager) {
this.traceManager = _traceManager this.traceManager = _traceManager
this.storageByAddress = {} this.storageByAddress = {}
this.maxSize = 100
} }
/** /**
* return the storage for the current context (address and vm trace index) * return the storage for the given context (address and vm trace index)
* by default now returns the range 0 => 1000 * returns the range 0 => this.maxSize
*
* @param {Object} - tx - transaction * @param {Object} - tx - transaction
* @param {Int} - stepIndex - Index of the stop in the vm trace * @param {Int} - stepIndex - Index of the stop in the vm trace
* @param {Function} - callback - contains a map: [hashedKey] = {key, hashedKey, value} * @param {Function} - callback - contains a map: [hashedKey] = {key, hashedKey, value}
*/ */
storageRange (tx, stepIndex, callback) { storageRange (tx, stepIndex, callback) {
storageRangeInternal(this, '0x0', true, tx, stepIndex, callback) storageRangeInternal(this, '0x0', tx, stepIndex, true, callback)
} }
/** /**
* return a slot value for the current context (address and vm trace index) * return a slot value for the given context (address and vm trace index)
*
* @param {String} - slot - slot key * @param {String} - slot - slot key
* @param {Object} - tx - transaction * @param {Object} - tx - transaction
* @param {Int} - stepIndex - Index of the stop in the vm trace * @param {Int} - stepIndex - Index of the stop in the vm trace
* @param {Function} - callback - {key, hashedKey, value} - * @param {Function} - callback - {key, hashedKey, value} -
*/ */
storageSlot (slot, tx, stepIndex, callback) { storageSlot (slot, tx, stepIndex, callback) {
storageRangeInternal(this, slot, false, tx, stepIndex, function (error, storage) { storageRangeInternal(this, slot, tx, stepIndex, false, function (error, storage) {
if (error) { if (error) {
callback(error) callback(error)
} else { } else {
@ -49,71 +52,49 @@ class StorageResolver {
} }
} }
function resolveAddress (self, stepIndex, callback) { /**
self.traceManager.getCurrentCalledAddressAt(stepIndex, (error, result) => { * retrieve the storage and ensure at least @arg slot is cached.
* - If @arg slot is already cached, the storage will be returned from the cache
* even if the next 1000 items are not in the cache.
* - If @arg slot is not cached, the corresponding value will be resolved and the next 1000 slots.
*/
function storageRangeInternal (self, slot, tx, stepIndex, fullStorage, callback) {
resolveAddress(self, stepIndex, (error, address) => {
if (error) { if (error) {
callback(error) return callback(error)
} else {
callback(null, result)
} }
}) self.traceManager.accumulateStorageChanges(stepIndex, address, {}, (error, storageChanges) => {
}
function storageRangeWeb3Call (tx, address, start, fullStorage, callback) {
var maxSize = fullStorage ? 1000 : 100
util.web3.debug.storageRangeAt(
tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex,
address,
start,
maxSize,
(error, result) => {
if (error) { if (error) {
callback(error) return callback(error)
} else if (result.storage) {
callback(null, result.storage, result.complete)
} else {
callback('the storage has not been provided')
} }
}) if (!fullStorage && storageChanges[slot]) {
} return callback(null, storageChanges)
function storageRangeInternal (self, start, fullStorage, tx, stepIndex, callback) {
resolveAddress(self, stepIndex, (error, address) => {
if (error) {
callback(error)
} else {
if (traceHelper.isContractCreation(address)) {
callback(null, {})
} else {
if (!util.web3.debug.storageRangeAt) {
callback('no storageRangeAt endpoint found')
} else {
var cached = fromCache(self, address, start)
if (cached) {
self.traceManager.accumulateStorageChanges(stepIndex, address, cached, callback)
} else {
storageRangeWeb3Call(tx, address, start, fullStorage, (error, storage, complete) => {
if (error) {
callback(error)
} else {
toCache(self, address, storage, fullStorage, complete)
self.traceManager.accumulateStorageChanges(stepIndex, address, storage, callback)
}
})
}
}
} }
} var cached = fromCache(self, address, slot)
if (cached && cached[slot]) { // we have the current slot in the cache and maybe the next 1000 ...
return callback(null, Object.assign(cached, storageChanges))
}
storageRangeWeb3Call(tx, address, slot, self.maxSize, (error, storage, complete) => {
if (error) {
return callback(error)
}
toCache(self, address, storage)
if (slot === '0x0' && Object.keys(storage).length < self.maxSize) {
self.storageByAddress[address].complete = true
}
callback(null, Object.assign(storage, storageChanges))
})
})
}) })
} }
/** /**
* retrieve the storage from the cache. if @arg slot is defined, return only the desired slot, if not return the entire known storage * retrieve the storage from the cache. if @arg slot is defined, return only the desired slot, if not return the entire known storage
* *
* @param {String} address - contract address * @param {String} address - contract address
* @param {String} slotKey - key of the value to return * @param {String} slotKey - key of the value to return
* @return {String} - either the entire known storage or a single value * @return {String} - either the entire known storage or a single value
*/ */
function fromCache (self, address, hashedKey) { function fromCache (self, address, hashedKey) {
if (!self.storageByAddress[address]) { if (!self.storageByAddress[address]) {
return null return null
@ -126,16 +107,43 @@ function fromCache (self, address, hashedKey) {
* *
* @param {String} address - contract address * @param {String} address - contract address
* @param {Object} storage - result of `storageRangeAtInternal`, contains {key, hashedKey, value} * @param {Object} storage - result of `storageRangeAtInternal`, contains {key, hashedKey, value}
* @param {Bool} complete - True if the storage is complete
*/ */
function toCache (self, address, storage, fullStorageRequest, complete) { function toCache (self, address, storage) {
if (!self.storageByAddress[address]) { if (!self.storageByAddress[address]) {
self.storageByAddress[address] = {} self.storageByAddress[address] = {}
} }
self.storageByAddress[address].storage = Object.assign(self.storageByAddress[address].storage || {}, storage) self.storageByAddress[address].storage = Object.assign(self.storageByAddress[address].storage || {}, storage)
if (Object.keys(storage).length < 1000 && fullStorageRequest && complete) { }
self.storageByAddress[address].complete = complete
function storageRangeWeb3Call (tx, address, start, maxSize, callback) {
if (traceHelper.isContractCreation(address)) {
callback(null, {}, true)
} else {
util.web3.debug.storageRangeAt(
tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex,
address,
start,
maxSize,
(error, result) => {
if (error) {
callback(error)
} else if (result.storage) {
callback(null, result.storage, result.complete)
} else {
callback('the storage has not been provided')
}
})
} }
} }
function resolveAddress (self, stepIndex, callback) {
self.traceManager.getCurrentCalledAddressAt(stepIndex, (error, result) => {
if (error) {
callback(error)
} else {
callback(null, result)
}
})
}
module.exports = StorageResolver module.exports = StorageResolver

Loading…
Cancel
Save