mirror of https://github.com/poanetwork/quorum.git
Merge pull request #4 from bas-vk/staterpc
core, eth: add support for storage root retrieval for accounts
This commit is contained in:
commit
b11a387c95
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
29
eth/api.go
29
eth/api.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue