github.com/RobustRoundRobin/quorum@v20.10.0+incompatible/core/state/database.go (about)

     1  // Copyright 2017 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 state
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/core/rawdb"
    24  	"github.com/ethereum/go-ethereum/ethdb"
    25  	"github.com/ethereum/go-ethereum/trie"
    26  	lru "github.com/hashicorp/golang-lru"
    27  )
    28  
    29  const (
    30  	// Number of codehash->size associations to keep.
    31  	codeSizeCacheSize = 100000
    32  )
    33  
    34  // Database wraps access to tries and contract code.
    35  type Database interface {
    36  	// OpenTrie opens the main account trie.
    37  	OpenTrie(root common.Hash) (Trie, error)
    38  
    39  	// OpenStorageTrie opens the storage trie of an account.
    40  	OpenStorageTrie(addrHash, root common.Hash) (Trie, error)
    41  
    42  	// CopyTrie returns an independent copy of the given trie.
    43  	CopyTrie(Trie) Trie
    44  
    45  	// ContractCode retrieves a particular contract's code.
    46  	ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
    47  
    48  	// ContractCodeSize retrieves a particular contracts code's size.
    49  	ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
    50  
    51  	// TrieDB retrieves the low level trie database used for data storage.
    52  	TrieDB() *trie.Database
    53  
    54  	// Privacy metadata linker
    55  	PrivacyMetadataLinker() rawdb.PrivacyMetadataLinker
    56  }
    57  
    58  // Trie is a Ethereum Merkle Patricia trie.
    59  type Trie interface {
    60  	// GetKey returns the sha3 preimage of a hashed key that was previously used
    61  	// to store a value.
    62  	//
    63  	// TODO(fjl): remove this when SecureTrie is removed
    64  	GetKey([]byte) []byte
    65  
    66  	// TryGet returns the value for key stored in the trie. The value bytes must
    67  	// not be modified by the caller. If a node was not found in the database, a
    68  	// trie.MissingNodeError is returned.
    69  	TryGet(key []byte) ([]byte, error)
    70  
    71  	// TryUpdate associates key with value in the trie. If value has length zero, any
    72  	// existing value is deleted from the trie. The value bytes must not be modified
    73  	// by the caller while they are stored in the trie. If a node was not found in the
    74  	// database, a trie.MissingNodeError is returned.
    75  	TryUpdate(key, value []byte) error
    76  
    77  	// TryDelete removes any existing value for key from the trie. If a node was not
    78  	// found in the database, a trie.MissingNodeError is returned.
    79  	TryDelete(key []byte) error
    80  
    81  	// Hash returns the root hash of the trie. It does not write to the database and
    82  	// can be used even if the trie doesn't have one.
    83  	Hash() common.Hash
    84  
    85  	// Commit writes all nodes to the trie's memory database, tracking the internal
    86  	// and external (for account tries) references.
    87  	Commit(onleaf trie.LeafCallback) (common.Hash, error)
    88  
    89  	// NodeIterator returns an iterator that returns nodes of the trie. Iteration
    90  	// starts at the key after the given start key.
    91  	NodeIterator(startKey []byte) trie.NodeIterator
    92  
    93  	// Prove constructs a Merkle proof for key. The result contains all encoded nodes
    94  	// on the path to the value at key. The value itself is also included in the last
    95  	// node and can be retrieved by verifying the proof.
    96  	//
    97  	// If the trie does not contain a value for key, the returned proof contains all
    98  	// nodes of the longest existing prefix of the key (at least the root), ending
    99  	// with the node that proves the absence of the key.
   100  	Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error
   101  }
   102  
   103  // NewDatabase creates a backing store for state. The returned database is safe for
   104  // concurrent use, but does not retain any recent trie nodes in memory. To keep some
   105  // historical state in memory, use the NewDatabaseWithCache constructor.
   106  func NewDatabase(db ethdb.Database) Database {
   107  	return NewDatabaseWithCache(db, 0)
   108  }
   109  
   110  // NewDatabaseWithCache creates a backing store for state. The returned database
   111  // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
   112  // large memory cache.
   113  func NewDatabaseWithCache(db ethdb.Database, cache int) Database {
   114  	csc, _ := lru.New(codeSizeCacheSize)
   115  	return &cachingDB{
   116  		db: trie.NewDatabaseWithCache(db, cache),
   117  		// Quorum - Privacy Enhancements
   118  		privacyMetadataLinker: rawdb.NewPrivacyMetadataLinker(db),
   119  		codeSizeCache:         csc,
   120  	}
   121  }
   122  
   123  type cachingDB struct {
   124  	db *trie.Database
   125  	// Quorum:  Privacy enhacements introducing privacyMetadataLinker which maintains mapping between private state root and privacy metadata root. As this struct is the backing store for state, this gives the reference to the linker when needed.
   126  	privacyMetadataLinker rawdb.PrivacyMetadataLinker
   127  	codeSizeCache         *lru.Cache
   128  }
   129  
   130  // Quorum - Privacy Enhancements
   131  func (db *cachingDB) PrivacyMetadataLinker() rawdb.PrivacyMetadataLinker {
   132  	return db.privacyMetadataLinker
   133  }
   134  
   135  // OpenTrie opens the main account trie at a specific root hash.
   136  func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
   137  	return trie.NewSecure(root, db.db)
   138  }
   139  
   140  // OpenStorageTrie opens the storage trie of an account.
   141  func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
   142  	return trie.NewSecure(root, db.db)
   143  }
   144  
   145  // CopyTrie returns an independent copy of the given trie.
   146  func (db *cachingDB) CopyTrie(t Trie) Trie {
   147  	switch t := t.(type) {
   148  	case *trie.SecureTrie:
   149  		return t.Copy()
   150  	default:
   151  		panic(fmt.Errorf("unknown trie type %T", t))
   152  	}
   153  }
   154  
   155  // ContractCode retrieves a particular contract's code.
   156  func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
   157  	code, err := db.db.Node(codeHash)
   158  	if err == nil {
   159  		db.codeSizeCache.Add(codeHash, len(code))
   160  	}
   161  	return code, err
   162  }
   163  
   164  // ContractCodeSize retrieves a particular contracts code's size.
   165  func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
   166  	if cached, ok := db.codeSizeCache.Get(codeHash); ok {
   167  		return cached.(int), nil
   168  	}
   169  	code, err := db.ContractCode(addrHash, codeHash)
   170  	return len(code), err
   171  }
   172  
   173  // TrieDB retrieves any intermediate trie-node caching layer.
   174  func (db *cachingDB) TrieDB() *trie.Database {
   175  	return db.db
   176  }