eth - Storage root retrieval for accounts (#436)

re-enabling eth_storagRoot call
This commit is contained in:
Sai V 2018-07-27 20:37:29 +08:00 committed by Samer Falah
parent e8f0ee9162
commit ad7c031e85
5 changed files with 77 additions and 0 deletions

View File

@ -169,6 +169,10 @@ func (c *stateObject) getTrie(db Database) Trie {
return c.trie
}
func (so *stateObject) storageRoot(db Database) common.Hash {
return so.getTrie(db).Hash()
}
// GetState returns a value in account storage.
func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
value, exists := self.cachedStorage[key]

View File

@ -255,6 +255,15 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
return false
}
// GetStorageRoot returns the root of the storage associated with the given address.
func (self *StateDB) GetStorageRoot(addr common.Address) (common.Hash, error) {
so := self.getStateObject(addr)
if so == nil {
return common.Hash{}, fmt.Errorf("can't find state object")
}
return so.storageRoot(self.db), nil
}
/*
* SETTERS
*/

View File

@ -117,6 +117,37 @@ func TestIntermediateLeaks(t *testing.T) {
}
}
func TestStorageRoot(t *testing.T) {
var (
mem, _ = ethdb.NewMemDatabase()
db = NewDatabase(mem)
state, _ = New(common.Hash{}, db)
addr = common.Address{1}
key = common.Hash{1}
value = common.Hash{42}
empty = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
)
so := state.GetOrNewStateObject(addr)
emptyRoot := so.storageRoot(db)
if emptyRoot != empty {
t.Errorf("Invalid empty storage root, expected %x, got %x", empty, emptyRoot)
}
// add a bit of state
so.SetState(db, key, value)
state.CommitTo(mem, false)
root := so.storageRoot(db)
expected := common.HexToHash("63511abd258fa907afa30cb118b53744a4f49055bb3f531da512c6b866fc2ffb")
if expected != root {
t.Errorf("Invalid storage root, expected %x, got %x", expected, root)
}
}
func TestSnapshotRandom(t *testing.T) {
config := &quick.Config{MaxCount: 1000}
err := quick.Check((*snapshotTest).run, config)

View File

@ -66,6 +66,33 @@ func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
return api.Etherbase()
}
// StorageRoot returns the storage root of an account on the the given (optional) block height.
// If block number is not given the latest block is used.
func (s *PublicEthereumAPI) StorageRoot(addr common.Address, blockNr *rpc.BlockNumber) (common.Hash, error) {
var (
pub, priv *state.StateDB
err error
)
if blockNr == nil || blockNr.Int64() == rpc.LatestBlockNumber.Int64() {
pub, priv, err = s.e.blockchain.State()
} else {
if ch := s.e.blockchain.GetHeaderByNumber(uint64(blockNr.Int64())); ch != nil {
pub, priv, err = s.e.blockchain.StateAt(ch.Root)
} else {
return common.Hash{}, fmt.Errorf("invalid block number")
}
}
if err != nil {
return common.Hash{}, err
}
if priv.Exist(addr) {
return priv.GetStorageRoot(addr)
}
return pub.GetStorageRoot(addr)
}
// Hashrate returns the POW hashrate
func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
return hexutil.Uint64(api.e.Miner().HashRate())

View File

@ -402,6 +402,12 @@ web3._extend({
params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.utils.toHex]
}),
new web3._extend.Method({
name: 'storageRoot',
call: 'eth_storageRoot',
params: 2,
inputFormatter: [web3._extend.formatters.inputAddressFormatter, null]
})
],
properties: [
new web3._extend.Property({