mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
core, trie: expose batch trie getters into the statedb
This commit is contained in:
parent
8fedd9f9e0
commit
9a4e5db197
3 changed files with 110 additions and 0 deletions
|
|
@ -87,11 +87,21 @@ type Trie interface {
|
||||||
// be returned.
|
// be returned.
|
||||||
GetAccount(address common.Address) (*types.StateAccount, error)
|
GetAccount(address common.Address) (*types.StateAccount, error)
|
||||||
|
|
||||||
|
// GetAccountBatch is a batched version of GetAccount that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. the singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
GetAccountBatch(addrs []common.Address) ([]*types.StateAccount, error)
|
||||||
|
|
||||||
// GetStorage returns the value for key stored in the trie. The value bytes
|
// GetStorage returns the value for key stored in the trie. The value bytes
|
||||||
// must not be modified by the caller. If a node was not found in the database,
|
// must not be modified by the caller. If a node was not found in the database,
|
||||||
// a trie.MissingNodeError is returned.
|
// a trie.MissingNodeError is returned.
|
||||||
GetStorage(addr common.Address, key []byte) ([]byte, error)
|
GetStorage(addr common.Address, key []byte) ([]byte, error)
|
||||||
|
|
||||||
|
// GetStorageBatch is a batched version of GetStorage that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. teh singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
GetStorageBatch(addrs []common.Address, keys [][]byte) ([][]byte, error)
|
||||||
|
|
||||||
// UpdateAccount abstracts an account write to the trie. It encodes the
|
// UpdateAccount abstracts an account write to the trie. It encodes the
|
||||||
// provided account object with associated algorithm and then updates it
|
// provided account object with associated algorithm and then updates it
|
||||||
// in the trie with provided address.
|
// in the trie with provided address.
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,30 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
|
||||||
return content, err
|
return content, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStorageBatch is a batched version of GetStorage that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. the singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
func (t *StateTrie) GetStorageBatch(_ []common.Address, keys [][]byte) ([][]byte, error) {
|
||||||
|
hashes := make([][]byte, len(keys))
|
||||||
|
for i, key := range keys {
|
||||||
|
hashes[i] = t.hashKey(key)
|
||||||
|
}
|
||||||
|
encs, err := t.trie.GetBatch(hashes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
content := make([][]byte, len(keys))
|
||||||
|
for i, enc := range encs {
|
||||||
|
if len(enc) > 0 {
|
||||||
|
_, content[i], _, err = rlp.Split(enc)
|
||||||
|
if err != nil {
|
||||||
|
return content, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetAccount attempts to retrieve an account with provided account address.
|
// GetAccount attempts to retrieve an account with provided account address.
|
||||||
// If the specified account is not in the trie, nil will be returned.
|
// If the specified account is not in the trie, nil will be returned.
|
||||||
// If a trie node is not found in the database, a MissingNodeError is returned.
|
// If a trie node is not found in the database, a MissingNodeError is returned.
|
||||||
|
|
@ -108,6 +132,29 @@ func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, err
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountBatch is a batched version of GetAccount that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. the singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
func (t *StateTrie) GetAccountBatch(addrs []common.Address) ([]*types.StateAccount, error) {
|
||||||
|
hashes := make([][]byte, len(addrs))
|
||||||
|
for i, addr := range addrs {
|
||||||
|
hashes[i] = t.hashKey(addr.Bytes())
|
||||||
|
}
|
||||||
|
encs, err := t.trie.GetBatch(hashes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
content := make([]*types.StateAccount, len(addrs))
|
||||||
|
for i, enc := range encs {
|
||||||
|
if len(enc) > 0 {
|
||||||
|
if err = rlp.DecodeBytes(enc, content[i]); err != nil {
|
||||||
|
return content, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetAccountByHash does the same thing as GetAccount, however it expects an
|
// GetAccountByHash does the same thing as GetAccount, however it expects an
|
||||||
// account hash that is the hash of address. This constitutes an abstraction
|
// account hash that is the hash of address. This constitutes an abstraction
|
||||||
// leak, since the client code needs to know the key format.
|
// leak, since the client code needs to know the key format.
|
||||||
|
|
@ -121,6 +168,29 @@ func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount,
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountBatchByHash does the same thing as GetAccountBatch, however it
|
||||||
|
// expects account hashes that are the hashes of addresses. This constitutes
|
||||||
|
// an abstraction leak, since the client code needs to know the key format.
|
||||||
|
func (t *StateTrie) GetAccountBatchByHash(addrHashes []common.Hash) ([]*types.StateAccount, error) {
|
||||||
|
hashes := make([][]byte, len(addrHashes))
|
||||||
|
for i, hash := range addrHashes {
|
||||||
|
hashes[i] = hash.Bytes()
|
||||||
|
}
|
||||||
|
encs, err := t.trie.GetBatch(hashes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
content := make([]*types.StateAccount, len(addrHashes))
|
||||||
|
for i, enc := range encs {
|
||||||
|
if len(enc) > 0 {
|
||||||
|
if err = rlp.DecodeBytes(enc, content[i]); err != nil {
|
||||||
|
return content, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetNode attempts to retrieve a trie node by compact-encoded path. It is not
|
// GetNode attempts to retrieve a trie node by compact-encoded path. It is not
|
||||||
// possible to use keybyte-encoding as the path might contain odd nibbles.
|
// possible to use keybyte-encoding as the path might contain odd nibbles.
|
||||||
// If the specified trie node is not in the trie, nil will be returned.
|
// If the specified trie node is not in the trie, nil will be returned.
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,21 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error
|
||||||
return acc, nil
|
return acc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountBatch is a batched version of GetAccount that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. the singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
func (t *VerkleTrie) GetAccountBatch(addrs []common.Address) ([]*types.StateAccount, error) {
|
||||||
|
results := make([]*types.StateAccount, len(addrs))
|
||||||
|
for i, addr := range addrs {
|
||||||
|
acc, err := t.GetAccount(addr)
|
||||||
|
if err != nil {
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
results[i] = acc
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetStorage implements state.Trie, retrieving the storage slot with the specified
|
// GetStorage implements state.Trie, retrieving the storage slot with the specified
|
||||||
// account address and storage key. If the specified slot is not in the verkle tree,
|
// account address and storage key. If the specified slot is not in the verkle tree,
|
||||||
// nil will be returned. If the tree is corrupted, an error will be returned.
|
// nil will be returned. If the tree is corrupted, an error will be returned.
|
||||||
|
|
@ -127,6 +142,21 @@ func (t *VerkleTrie) GetStorage(addr common.Address, key []byte) ([]byte, error)
|
||||||
return common.TrimLeftZeroes(val), nil
|
return common.TrimLeftZeroes(val), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStorageBatch is a batched version of GetStorage that simultaneously looks
|
||||||
|
// up multiple slots. The advantage vs. the singleton version is the potential
|
||||||
|
// for concurrent disk lookups.
|
||||||
|
func (t *VerkleTrie) GetStorageBatch(addrs []common.Address, keys [][]byte) ([][]byte, error) {
|
||||||
|
results := make([][]byte, len(keys))
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
val, err := t.GetStorage(addrs[i], keys[i])
|
||||||
|
if err != nil {
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
results[i] = val
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateAccount implements state.Trie, writing the provided account into the tree.
|
// UpdateAccount implements state.Trie, writing the provided account into the tree.
|
||||||
// If the tree is corrupted, an error will be returned.
|
// If the tree is corrupted, an error will be returned.
|
||||||
func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) error {
|
func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) error {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue