mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
trie: add Path to MissingNodeError
The light client trie iterator needs to know the path of the node that's missing so it can retrieve a proof for it. NodeIterator.Path is not sufficient because it is updated when the node is resolved and actually visited by the iterator. Also remove unused fields. They were added a long time ago before we knew which fields would be needed for the light client.
This commit is contained in:
parent
0b210b11e3
commit
3a2fceedb9
4 changed files with 20 additions and 36 deletions
|
|
@ -23,24 +23,13 @@ import (
|
|||
)
|
||||
|
||||
// MissingNodeError is returned by the trie functions (TryGet, TryUpdate, TryDelete)
|
||||
// in the case where a trie node is not present in the local database. Contains
|
||||
// information necessary for retrieving the missing node through an ODR service.
|
||||
//
|
||||
// NodeHash is the hash of the missing node
|
||||
//
|
||||
// RootHash is the original root of the trie that contains the node
|
||||
//
|
||||
// PrefixLen is the nibble length of the key prefix that leads from the root to
|
||||
// the missing node
|
||||
//
|
||||
// SuffixLen is the nibble length of the remaining part of the key that hints on
|
||||
// which further nodes should also be retrieved (can be zero when there are no
|
||||
// such hints in the error message)
|
||||
// in the case where a trie node is not present in the local database. It contains
|
||||
// information necessary for retrieving the missing node.
|
||||
type MissingNodeError struct {
|
||||
RootHash, NodeHash common.Hash
|
||||
PrefixLen, SuffixLen int
|
||||
NodeHash common.Hash // hash of the missing node
|
||||
Path []byte // hex-encoded path to the missing node
|
||||
}
|
||||
|
||||
func (err *MissingNodeError) Error() string {
|
||||
return fmt.Sprintf("Missing trie node %064x", err.NodeHash)
|
||||
return fmt.Sprintf("missing trie node %x (path %x)", err.NodeHash, err.Path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
|
|||
if root != emptyRoot {
|
||||
state.hash = root
|
||||
}
|
||||
err := state.resolve(it.trie)
|
||||
err := state.resolve(it.trie, nil)
|
||||
return state, nil, nil, err
|
||||
}
|
||||
if !descend {
|
||||
|
|
@ -238,8 +238,8 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
|
|||
}
|
||||
state, path, ok := it.nextChild(parent, ancestor)
|
||||
if ok {
|
||||
if err := state.resolve(it.trie); err != nil {
|
||||
return parent, &parent.index, it.path, err
|
||||
if err := state.resolve(it.trie, path); err != nil {
|
||||
return parent, &parent.index, path, err
|
||||
}
|
||||
return state, &parent.index, path, nil
|
||||
}
|
||||
|
|
@ -249,9 +249,9 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
|
|||
return nil, nil, nil, iteratorEnd
|
||||
}
|
||||
|
||||
func (st *nodeIteratorState) resolve(tr *Trie) error {
|
||||
func (st *nodeIteratorState) resolve(tr *Trie, path []byte) error {
|
||||
if hash, ok := st.node.(hashNode); ok {
|
||||
resolved, err := tr.resolveHash(hash, nil, nil)
|
||||
resolved, err := tr.resolveHash(hash, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (t *Trie) Prove(key []byte) []rlp.RawValue {
|
|||
nodes = append(nodes, n)
|
||||
case hashNode:
|
||||
var err error
|
||||
tn, err = t.resolveHash(n, nil, nil)
|
||||
tn, err = t.resolveHash(n, nil)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
|
||||
return nil
|
||||
|
|
|
|||
23
trie/trie.go
23
trie/trie.go
|
|
@ -116,7 +116,7 @@ func New(root common.Hash, db Database) (*Trie, error) {
|
|||
if db == nil {
|
||||
panic("trie.New: cannot use existing root without a database")
|
||||
}
|
||||
rootnode, err := trie.resolveHash(root[:], nil, nil)
|
||||
rootnode, err := trie.resolveHash(root[:], nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode
|
|||
}
|
||||
return value, n, didResolve, err
|
||||
case hashNode:
|
||||
child, err := t.resolveHash(n, key[:pos], key[pos:])
|
||||
child, err := t.resolveHash(n, key[:pos])
|
||||
if err != nil {
|
||||
return nil, n, true, err
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
|
|||
// We've hit a part of the trie that isn't loaded yet. Load
|
||||
// the node and insert into it. This leaves all child nodes on
|
||||
// the path to the value in the trie.
|
||||
rn, err := t.resolveHash(n, prefix, key)
|
||||
rn, err := t.resolveHash(n, prefix)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
|
@ -388,7 +388,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
|
|||
// shortNode{..., shortNode{...}}. Since the entry
|
||||
// might not be loaded yet, resolve it just for this
|
||||
// check.
|
||||
cnode, err := t.resolve(n.Children[pos], prefix, []byte{byte(pos)})
|
||||
cnode, err := t.resolve(n.Children[pos], prefix)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
|
@ -414,7 +414,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
|
|||
// We've hit a part of the trie that isn't loaded yet. Load
|
||||
// the node and delete from it. This leaves all child nodes on
|
||||
// the path to the value in the trie.
|
||||
rn, err := t.resolveHash(n, prefix, key)
|
||||
rn, err := t.resolveHash(n, prefix)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
|
@ -436,24 +436,19 @@ func concat(s1 []byte, s2 ...byte) []byte {
|
|||
return r
|
||||
}
|
||||
|
||||
func (t *Trie) resolve(n node, prefix, suffix []byte) (node, error) {
|
||||
func (t *Trie) resolve(n node, prefix []byte) (node, error) {
|
||||
if n, ok := n.(hashNode); ok {
|
||||
return t.resolveHash(n, prefix, suffix)
|
||||
return t.resolveHash(n, prefix)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (t *Trie) resolveHash(n hashNode, prefix, suffix []byte) (node, error) {
|
||||
func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
|
||||
cacheMissCounter.Inc(1)
|
||||
|
||||
enc, err := t.db.Get(n)
|
||||
if err != nil || enc == nil {
|
||||
return nil, &MissingNodeError{
|
||||
RootHash: t.originalRoot,
|
||||
NodeHash: common.BytesToHash(n),
|
||||
PrefixLen: len(prefix),
|
||||
SuffixLen: len(suffix),
|
||||
}
|
||||
return nil, &MissingNodeError{NodeHash: common.BytesToHash(n), Path: prefix}
|
||||
}
|
||||
dec := mustDecodeNode(n, enc, t.cachegen)
|
||||
return dec, nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue