Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: use TryGetAccount to read what TryUpdateAccount has written #25458

Merged
merged 8 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ type Trie interface {
// trie.MissingNodeError is returned.
TryGet(key []byte) ([]byte, error)

// TryUpdateAccount abstract an account write in the trie.
TryGetAccount(key []byte) (*types.StateAccount, error)
rjl493456442 marked this conversation as resolved.
Show resolved Hide resolved

// TryUpdateAccount abstract an account write to the trie.
TryUpdateAccount(key []byte, account *types.StateAccount) error

// TryUpdate associates key with value in the trie. If value has length zero, any
Expand Down
12 changes: 4 additions & 8 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,20 +537,16 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
// If snapshot unavailable or reading from it failed, load from the database
if data == nil {
start := time.Now()
enc, err := s.trie.TryGet(addr.Bytes())
var err error
data, err = s.trie.TryGetAccount(addr.Bytes())
if metrics.EnabledExpensive {
s.AccountReads += time.Since(start)
}
if err != nil {
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %v", addr.Bytes(), err))
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %w", addr.Bytes(), err))
return nil
}
if len(enc) == 0 {
return nil
}
data = new(types.StateAccount)
if err := rlp.DecodeBytes(enc, data); err != nil {
log.Error("Failed to decode state object", "addr", addr, "err", err)
if data == nil {
return nil
}
}
Expand Down
6 changes: 5 additions & 1 deletion core/state/trie_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,11 @@ func (sf *subfetcher) loop() {
if _, ok := sf.seen[string(task)]; ok {
sf.dups++
} else {
sf.trie.TryGet(task)
if len(task) == len(common.Address{}) {
sf.trie.TryGetAccount(task)
} else {
sf.trie.TryGet(task)
}
sf.seen[string(task)] = struct{}{}
}
}
Expand Down
6 changes: 3 additions & 3 deletions eth/protocols/snap/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)

Expand Down Expand Up @@ -419,8 +418,9 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
if err != nil {
return nil, nil
}
var acc types.StateAccount
if err := rlp.DecodeBytes(accTrie.Get(account[:]), &acc); err != nil {
var acc *types.StateAccount
gballet marked this conversation as resolved.
Show resolved Hide resolved
acc, err = accTrie.TryGetAccount(account[:])
if err != nil {
return nil, nil
}
stTrie, err := trie.New(account, acc.Root, chain.StateCache().TrieDB())
Expand Down
10 changes: 10 additions & 0 deletions light/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ func (t *odrTrie) TryGet(key []byte) ([]byte, error) {
return res, err
}

func (t *odrTrie) TryGetAccount(key []byte) (*types.StateAccount, error) {
key = crypto.Keccak256(key)
var res *types.StateAccount
err := t.do(key, func() (err error) {
res, err = t.trie.TryGetAccount(key)
return err
})
return res, err
}

func (t *odrTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
key = crypto.Keccak256(key)
value, err := rlp.EncodeToBytes(acc)
Expand Down
6 changes: 5 additions & 1 deletion trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func (t *SecureTrie) TryGet(key []byte) ([]byte, error) {
return t.trie.TryGet(t.hashKey(key))
}

func (t *SecureTrie) TryGetAccount(key []byte) (*types.StateAccount, error) {
return t.trie.TryGetAccount(t.hashKey(key))
}

// TryGetNode 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.
func (t *SecureTrie) TryGetNode(path []byte) ([]byte, int, error) {
Expand All @@ -96,7 +100,7 @@ func (t *SecureTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error
if err != nil {
return err
}
if err := t.trie.TryUpdate(hk, data); err != nil {
if err := t.trie.tryUpdate(hk, data); err != nil {
rjl493456442 marked this conversation as resolved.
Show resolved Hide resolved
return err
}
t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
Expand Down
27 changes: 26 additions & 1 deletion trie/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,23 @@ func (t *Trie) Get(key []byte) []byte {
return res
}

func (t *Trie) TryGetAccount(key []byte) (*types.StateAccount, error) {
res, newroot, didResolve, err := t.tryGet(t.root, keybytesToHex(key), 0)
if err != nil {
log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
return &types.StateAccount{}, err
}
if didResolve {
gballet marked this conversation as resolved.
Show resolved Hide resolved
t.root = newroot
}
if res == nil {
return nil, nil
}
var ret types.StateAccount
err = rlp.DecodeBytes(res, &ret)
return &ret, err
}

// TryGet 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, a MissingNodeError is returned.
Expand Down Expand Up @@ -295,7 +312,9 @@ func (t *Trie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
if err != nil {
return fmt.Errorf("can't encode object at %x: %w", key[:], err)
}
return t.TryUpdate(key, data)
// Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(data[:]))
gballet marked this conversation as resolved.
Show resolved Hide resolved
return t.tryUpdate(key, v)
}

// TryUpdate associates key with value in the trie. Subsequent calls to
Expand All @@ -307,6 +326,12 @@ func (t *Trie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
//
// If a node was not found in the database, a MissingNodeError is returned.
func (t *Trie) TryUpdate(key, value []byte) error {
return t.tryUpdate(key, value)
}

// tryUpdate expects an RLP-encoded value and performs the core function
// for TryUpdate and TryUpdateAccount.
func (t *Trie) tryUpdate(key, value []byte) error {
t.unhashed++
k := keybytesToHex(key)
if len(value) != 0 {
Expand Down