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  }