Merge pull request #4 from bas-vk/staterpc

core, eth: add support for storage root retrieval for accounts
This commit is contained in:
Jeffrey Wilcke 2016-11-02 00:33:26 +01:00 committed by GitHub
commit b11a387c95
4 changed files with 72 additions and 0 deletions

View File

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

View File

@ -286,6 +286,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

@ -115,6 +115,36 @@ func TestIntermediateLeaks(t *testing.T) {
}
}
func TestStorageRoot(t *testing.T) {
var (
db, _ = ethdb.NewMemDatabase()
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 storate root, expected %x, got %x", empty, emptyRoot)
}
// add a bit of state
so.SetState(db, key, value)
state.Commit()
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

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/net/context"
)
@ -59,6 +60,34 @@ func (s *PublicEthereumAPI) Coinbase() (common.Address, error) {
return s.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)
}
// PrivateAdminAPI is the collection of Etheruem full node-related APIs
// exposed over the private admin endpoint.
type PrivateAdminAPI struct {