diff --git a/trie/archive/archive.go b/trie/archive/archive.go index 857634b75e..e1129b65fc 100644 --- a/trie/archive/archive.go +++ b/trie/archive/archive.go @@ -71,18 +71,20 @@ func ArchivedNodeResolver(offset, size uint64) ([]*Record, error) { } var records []*Record + stream := rlp.NewStream(bytes.NewReader(data), uint64(len(data))) for len(data) > 0 { - stream := rlp.NewStream(bytes.NewReader(data), uint64(len(data))) _, size, err := stream.Kind() + if err == io.EOF { + break + } if err != nil { return nil, fmt.Errorf("error getting rlp kind from archive data: %w", err) } var record Record - err = rlp.DecodeBytes(data[:size], &record) + err = stream.Decode(&record) if err != nil { return nil, fmt.Errorf("error decoding rlp record from archive data: %w", err) } - data = data[size:] records = append(records, &record) } return records, nil diff --git a/trie/archiver.go b/trie/archiver.go index 0814da10e8..b24ac18c4a 100644 --- a/trie/archiver.go +++ b/trie/archiver.go @@ -83,18 +83,11 @@ func NewArchiver(db ethdb.Database, triedb database.NodeDatabase, func (a *Archiver) ProcessState(root common.Hash) error { a.stateRoot = root - // Process account trie (owner = zero hash) - log.Info("Processing account trie", "root", root) accountTrie, err := New(StateTrieID(root), a.triedb) if err != nil { return fmt.Errorf("failed to open account trie: %w", err) } - if err := a.processTrie(common.Hash{}, accountTrie); err != nil { - return fmt.Errorf("failed to process account trie: %w", err) - } - - // Process storage tries for accounts with storage log.Info("Processing storage tries") iter, err := accountTrie.NodeIterator(nil) if err != nil { @@ -131,6 +124,11 @@ func (a *Archiver) ProcessState(root common.Hash) error { return fmt.Errorf("account iteration error: %w", kvIter.Err) } + log.Info("Processing account trie", "root", root) + if err := a.processTrie(common.Hash{}, accountTrie); err != nil { + return fmt.Errorf("failed to process account trie: %w", err) + } + return nil } diff --git a/trie/trie.go b/trie/trie.go index 1c9c372b58..5f2cdcdcfe 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -230,30 +230,33 @@ func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, newnode no value, newnode, _, err := t.get(child, key, pos) return value, newnode, true, err case *expiredNode: - if t.archiveResolver == nil { - return nil, n, false, archive.ErrNoResolver - } - records, err := t.archiveResolver(n.offset, n.size) + records, err := archive.ArchivedNodeResolver(n.offset, n.size) if err != nil { return nil, n, false, fmt.Errorf("failed to resolve expired node: %w", err) } newnode, err := archiveRecordsToNode(records) - for _, record := range records { - // make sure that the path up to the node matches - if bytes.HasPrefix(key[pos:], record.Path) { - resolved, err := decodeNodeUnsafe(nil, record.Value) - if err != nil { - return nil, n, false, fmt.Errorf("failed to deserialize RLP node: %w", err) - } - if leaf, ok := resolved.(*shortNode); ok { - // make sure that the key to the leaf also matches - if bytes.Equal(key[pos+len(record.Path):], leaf.Key) { - return leaf.Val.(valueNode), newnode, true, nil - } - } - } + // alternative: don't rebuild, just find the value + // for _, record := range records { + // // make sure that the path up to the node matches + // if bytes.HasPrefix(key[pos:], record.Path) { + // resolved, err := decodeNodeUnsafe(nil, record.Value) + // if err != nil { + // fmt.Printf("%v %x\n", record.Path, record.Value) + // return nil, n, false, fmt.Errorf("failed to deserialize RLP node: %w", err) + // } + // if leaf, ok := resolved.(*shortNode); ok { + // // make sure that the key to the leaf also matches + // if bytes.Equal(key[pos+len(record.Path):], leaf.Key) { + // return leaf.Val.(valueNode), newnode, true, nil + // } + // } + // } + // } + if err != nil { + return nil, n, false, err } - return value, newnode, false, err + value, _, _, err = t.get(newnode, key, pos+1) + return value, newnode, true, err default: panic(fmt.Sprintf("%T: invalid node: %v", origNode, origNode)) } @@ -389,10 +392,7 @@ func (t *Trie) getNode(origNode node, path []byte, pos int) (item []byte, newnod return item, newnode, resolved + 1, err case *expiredNode: - if t.archiveResolver == nil { - return nil, n, 0, archive.ErrNoResolver - } - records, err := t.archiveResolver(n.offset, n.size) + records, err := archive.ArchivedNodeResolver(n.offset, n.size) if err != nil { return nil, n, 0, fmt.Errorf("failed to resolve expired node: %w", err) } @@ -524,10 +524,7 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error return true, nn, nil case *expiredNode: - if t.archiveResolver == nil { - return false, nil, archive.ErrNoResolver - } - records, err := t.archiveResolver(n.offset, n.size) + records, err := archive.ArchivedNodeResolver(n.offset, n.size) if err != nil { return false, nil, fmt.Errorf("failed to resolve expired node: %w", err) } @@ -700,10 +697,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { return true, nn, nil case *expiredNode: - if t.archiveResolver == nil { - return false, nil, archive.ErrNoResolver - } - records, err := t.archiveResolver(n.offset, n.size) + records, err := archive.ArchivedNodeResolver(n.offset, n.size) if err != nil { return false, nil, fmt.Errorf("failed to resolve expired node: %w", err) } @@ -748,7 +742,7 @@ func copyNode(n node) node { return &expiredNode{ offset: n.offset, size: n.size, - archiveResolver: n.archiveResolver, + archiveResolver: archive.ArchivedNodeResolver, } default: panic(fmt.Sprintf("%T: unknown node type", n)) diff --git a/triedb/pathdb/reader.go b/triedb/pathdb/reader.go index e087ef26ed..845667b578 100644 --- a/triedb/pathdb/reader.go +++ b/triedb/pathdb/reader.go @@ -69,7 +69,7 @@ func (r *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, return nil, err } // Error out if the local one is inconsistent with the target. - if !r.noHashCheck && got != hash { + if !r.noHashCheck && (len(blob) > 0 && blob[0] != 0) && got != hash { // Location is always available even if the node // is not found. switch loc.loc {