github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/triedb/pathdb/reader.go (about) 1 // Copyright 2024 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/> 16 17 package pathdb 18 19 import ( 20 "fmt" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/common/hexutil" 24 "github.com/ethereum/go-ethereum/log" 25 "github.com/ethereum/go-ethereum/triedb/database" 26 ) 27 28 // The types of locations where the node is found. 29 const ( 30 locDirtyCache = "dirty" // dirty cache 31 locCleanCache = "clean" // clean cache 32 locDiskLayer = "disk" // persistent state 33 locDiffLayer = "diff" // diff layers 34 ) 35 36 // nodeLoc is a helpful structure that contains the location where the node 37 // is found, as it's useful for debugging purposes. 38 type nodeLoc struct { 39 loc string 40 depth int 41 } 42 43 // string returns the string representation of node location. 44 func (loc *nodeLoc) string() string { 45 return fmt.Sprintf("loc: %s, depth: %d", loc.loc, loc.depth) 46 } 47 48 // reader implements the database.Reader interface, providing the functionalities to 49 // retrieve trie nodes by wrapping the internal state layer. 50 type reader struct { 51 layer layer 52 noHashCheck bool 53 } 54 55 // Node implements database.Reader interface, retrieving the node with specified 56 // node info. Don't modify the returned byte slice since it's not deep-copied 57 // and still be referenced by database. 58 func (r *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) { 59 blob, got, loc, err := r.layer.node(owner, path, 0) 60 if err != nil { 61 return nil, err 62 } 63 // Error out if the local one is inconsistent with the target. 64 if !r.noHashCheck && got != hash { 65 // Location is always available even if the node 66 // is not found. 67 switch loc.loc { 68 case locCleanCache: 69 cleanFalseMeter.Mark(1) 70 case locDirtyCache: 71 dirtyFalseMeter.Mark(1) 72 case locDiffLayer: 73 diffFalseMeter.Mark(1) 74 case locDiskLayer: 75 diskFalseMeter.Mark(1) 76 } 77 blobHex := "nil" 78 if len(blob) > 0 { 79 blobHex = hexutil.Encode(blob) 80 } 81 log.Error("Unexpected trie node", "location", loc.loc, "owner", owner, "path", path, "expect", hash, "got", got, "blob", blobHex) 82 return nil, fmt.Errorf("unexpected node: (%x %v), %x!=%x, %s, blob: %s", owner, path, hash, got, loc.string(), blobHex) 83 } 84 return blob, nil 85 } 86 87 // Reader retrieves a layer belonging to the given state root. 88 func (db *Database) Reader(root common.Hash) (database.Reader, error) { 89 layer := db.tree.get(root) 90 if layer == nil { 91 return nil, fmt.Errorf("state %#x is not available", root) 92 } 93 return &reader{layer: layer, noHashCheck: db.isVerkle}, nil 94 }