github.com/klaytn/klaytn@v1.12.1/node/cn/snap/nodeset.go (about)

     1  // Modifications Copyright 2022 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from light/nodeset.go (2022/06/29).
    19  // Modified and improved for the klaytn development.
    20  
    21  package snap
    22  
    23  import (
    24  	"errors"
    25  	"sync"
    26  
    27  	"github.com/klaytn/klaytn/common"
    28  	"github.com/klaytn/klaytn/crypto"
    29  	"github.com/klaytn/klaytn/rlp"
    30  	"github.com/klaytn/klaytn/storage/database"
    31  )
    32  
    33  // NodeSet stores a set of trie nodes. It implements trie.Database and can also
    34  // act as a cache for another trie.Database.
    35  type NodeSet struct {
    36  	nodes map[string][]byte
    37  	order []string
    38  
    39  	dataSize int
    40  	lock     sync.RWMutex
    41  }
    42  
    43  // NewNodeSet creates an empty node set
    44  func NewNodeSet() *NodeSet {
    45  	return &NodeSet{
    46  		nodes: make(map[string][]byte),
    47  	}
    48  }
    49  
    50  func (db *NodeSet) ReadTrieNode(hash common.ExtHash) ([]byte, error) {
    51  	return db.Get(database.TrieNodeKey(hash))
    52  }
    53  
    54  func (db *NodeSet) WriteMerkleProof(key, value []byte) {
    55  	db.Put(key, value)
    56  }
    57  
    58  // Put stores a new node in the set
    59  func (db *NodeSet) Put(key []byte, value []byte) error {
    60  	db.lock.Lock()
    61  	defer db.lock.Unlock()
    62  
    63  	keystr := string(key)
    64  	if _, ok := db.nodes[keystr]; ok {
    65  		return nil
    66  	}
    67  
    68  	db.nodes[keystr] = common.CopyBytes(value)
    69  	db.order = append(db.order, keystr)
    70  	db.dataSize += len(value)
    71  
    72  	return nil
    73  }
    74  
    75  // Delete removes a node from the set
    76  func (db *NodeSet) Delete(key []byte) error {
    77  	db.lock.Lock()
    78  	defer db.lock.Unlock()
    79  
    80  	delete(db.nodes, string(key))
    81  	return nil
    82  }
    83  
    84  // Get returns a stored node
    85  func (db *NodeSet) Get(key []byte) ([]byte, error) {
    86  	db.lock.RLock()
    87  	defer db.lock.RUnlock()
    88  
    89  	if entry, ok := db.nodes[string(key)]; ok {
    90  		return entry, nil
    91  	}
    92  	return nil, errors.New("not found")
    93  }
    94  
    95  // Has returns true if the node set contains the given key
    96  func (db *NodeSet) Has(key []byte) (bool, error) {
    97  	_, err := db.Get(key)
    98  	return err == nil, nil
    99  }
   100  
   101  // KeyCount returns the number of nodes in the set
   102  func (db *NodeSet) KeyCount() int {
   103  	db.lock.RLock()
   104  	defer db.lock.RUnlock()
   105  
   106  	return len(db.nodes)
   107  }
   108  
   109  // DataSize returns the aggregated data size of nodes in the set
   110  func (db *NodeSet) DataSize() int {
   111  	db.lock.RLock()
   112  	defer db.lock.RUnlock()
   113  
   114  	return db.dataSize
   115  }
   116  
   117  // NodeList converts the node set to a NodeList
   118  func (db *NodeSet) NodeList() NodeList {
   119  	db.lock.RLock()
   120  	defer db.lock.RUnlock()
   121  
   122  	var values NodeList
   123  	for _, key := range db.order {
   124  		values = append(values, db.nodes[key])
   125  	}
   126  	return values
   127  }
   128  
   129  // Store writes the contents of the set to the given database
   130  func (db *NodeSet) Store(target database.KeyValueWriter) {
   131  	db.lock.RLock()
   132  	defer db.lock.RUnlock()
   133  
   134  	for key, value := range db.nodes {
   135  		target.Put([]byte(key), value)
   136  	}
   137  }
   138  
   139  // NodeList stores an ordered list of trie nodes. It implements ethdb.KeyValueWriter.
   140  type NodeList []rlp.RawValue
   141  
   142  // Store writes the contents of the list to the given database
   143  func (n NodeList) Store(db database.KeyValueWriter) {
   144  	for _, node := range n {
   145  		db.Put(crypto.Keccak256(node), node)
   146  	}
   147  }
   148  
   149  // NodeSet converts the node list to a NodeSet
   150  func (n NodeList) NodeSet() *NodeSet {
   151  	db := NewNodeSet()
   152  	n.Store(db)
   153  	return db
   154  }
   155  
   156  // Put stores a new node at the end of the list
   157  func (n *NodeList) Put(key []byte, value []byte) error {
   158  	*n = append(*n, value)
   159  	return nil
   160  }
   161  
   162  // Delete panics as there's no reason to remove a node from the list.
   163  func (n *NodeList) Delete(key []byte) error {
   164  	panic("not supported")
   165  }
   166  
   167  // DataSize returns the aggregated data size of nodes in the list
   168  func (n NodeList) DataSize() int {
   169  	var size int
   170  	for _, node := range n {
   171  		size += len(node)
   172  	}
   173  	return size
   174  }