secure_trie.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright 2015 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. package trie
  17. import (
  18. "fmt"
  19. "github.com/ethereum/go-ethereum/common"
  20. "github.com/ethereum/go-ethereum/log"
  21. )
  22. // SecureTrie wraps a trie with key hashing. In a secure trie, all
  23. // access operations hash the key using keccak256. This prevents
  24. // calling code from creating long chains of nodes that
  25. // increase the access time.
  26. //
  27. // Contrary to a regular trie, a SecureTrie can only be created with
  28. // New and must have an attached database. The database also stores
  29. // the preimage of each key.
  30. //
  31. // SecureTrie is not safe for concurrent use.
  32. type SecureTrie struct {
  33. trie Trie
  34. hashKeyBuf [common.HashLength]byte
  35. secKeyCache map[string][]byte
  36. secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch
  37. }
  38. // NewSecure creates a trie with an existing root node from a backing database
  39. // and optional intermediate in-memory node pool.
  40. //
  41. // If root is the zero hash or the sha3 hash of an empty string, the
  42. // trie is initially empty. Otherwise, New will panic if db is nil
  43. // and returns MissingNodeError if the root node cannot be found.
  44. //
  45. // Accessing the trie loads nodes from the database or node pool on demand.
  46. // Loaded nodes are kept around until their 'cache generation' expires.
  47. // A new cache generation is created by each call to Commit.
  48. // cachelimit sets the number of past cache generations to keep.
  49. func NewSecure(root common.Hash, db *Database) (*SecureTrie, error) {
  50. if db == nil {
  51. panic("trie.NewSecure called without a database")
  52. }
  53. trie, err := New(root, db)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return &SecureTrie{trie: *trie}, nil
  58. }
  59. // Get returns the value for key stored in the trie.
  60. // The value bytes must not be modified by the caller.
  61. func (t *SecureTrie) Get(key []byte) []byte {
  62. res, err := t.TryGet(key)
  63. if err != nil {
  64. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  65. }
  66. return res
  67. }
  68. // TryGet returns the value for key stored in the trie.
  69. // The value bytes must not be modified by the caller.
  70. // If a node was not found in the database, a MissingNodeError is returned.
  71. func (t *SecureTrie) TryGet(key []byte) ([]byte, error) {
  72. return t.trie.TryGet(t.hashKey(key))
  73. }
  74. // TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not
  75. // possible to use keybyte-encoding as the path might contain odd nibbles.
  76. func (t *SecureTrie) TryGetNode(path []byte) ([]byte, int, error) {
  77. return t.trie.TryGetNode(path)
  78. }
  79. // Update associates key with value in the trie. Subsequent calls to
  80. // Get will return value. If value has length zero, any existing value
  81. // is deleted from the trie and calls to Get will return nil.
  82. //
  83. // The value bytes must not be modified by the caller while they are
  84. // stored in the trie.
  85. func (t *SecureTrie) Update(key, value []byte) {
  86. if err := t.TryUpdate(key, value); err != nil {
  87. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  88. }
  89. }
  90. // TryUpdate associates key with value in the trie. Subsequent calls to
  91. // Get will return value. If value has length zero, any existing value
  92. // is deleted from the trie and calls to Get will return nil.
  93. //
  94. // The value bytes must not be modified by the caller while they are
  95. // stored in the trie.
  96. //
  97. // If a node was not found in the database, a MissingNodeError is returned.
  98. func (t *SecureTrie) TryUpdate(key, value []byte) error {
  99. hk := t.hashKey(key)
  100. err := t.trie.TryUpdate(hk, value)
  101. if err != nil {
  102. return err
  103. }
  104. t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
  105. return nil
  106. }
  107. // Delete removes any existing value for key from the trie.
  108. func (t *SecureTrie) Delete(key []byte) {
  109. if err := t.TryDelete(key); err != nil {
  110. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  111. }
  112. }
  113. // TryDelete removes any existing value for key from the trie.
  114. // If a node was not found in the database, a MissingNodeError is returned.
  115. func (t *SecureTrie) TryDelete(key []byte) error {
  116. hk := t.hashKey(key)
  117. delete(t.getSecKeyCache(), string(hk))
  118. return t.trie.TryDelete(hk)
  119. }
  120. // GetKey returns the sha3 preimage of a hashed key that was
  121. // previously used to store a value.
  122. func (t *SecureTrie) GetKey(shaKey []byte) []byte {
  123. if key, ok := t.getSecKeyCache()[string(shaKey)]; ok {
  124. return key
  125. }
  126. return t.trie.db.preimage(common.BytesToHash(shaKey))
  127. }
  128. // Commit writes all nodes and the secure hash pre-images to the trie's database.
  129. // Nodes are stored with their sha3 hash as the key.
  130. //
  131. // Committing flushes nodes from memory. Subsequent Get calls will load nodes
  132. // from the database.
  133. func (t *SecureTrie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
  134. // Write all the pre-images to the actual disk database
  135. if len(t.getSecKeyCache()) > 0 {
  136. if t.trie.db.preimages != nil { // Ugly direct check but avoids the below write lock
  137. t.trie.db.lock.Lock()
  138. for hk, key := range t.secKeyCache {
  139. t.trie.db.insertPreimage(common.BytesToHash([]byte(hk)), key)
  140. }
  141. t.trie.db.lock.Unlock()
  142. }
  143. t.secKeyCache = make(map[string][]byte)
  144. }
  145. // Commit the trie to its intermediate node database
  146. return t.trie.Commit(onleaf)
  147. }
  148. // Hash returns the root hash of SecureTrie. It does not write to the
  149. // database and can be used even if the trie doesn't have one.
  150. func (t *SecureTrie) Hash() common.Hash {
  151. return t.trie.Hash()
  152. }
  153. // Copy returns a copy of SecureTrie.
  154. func (t *SecureTrie) Copy() *SecureTrie {
  155. cpy := *t
  156. return &cpy
  157. }
  158. // NodeIterator returns an iterator that returns nodes of the underlying trie. Iteration
  159. // starts at the key after the given start key.
  160. func (t *SecureTrie) NodeIterator(start []byte) NodeIterator {
  161. return t.trie.NodeIterator(start)
  162. }
  163. // hashKey returns the hash of key as an ephemeral buffer.
  164. // The caller must not hold onto the return value because it will become
  165. // invalid on the next call to hashKey or secKey.
  166. func (t *SecureTrie) hashKey(key []byte) []byte {
  167. h := newHasher(false)
  168. h.sha.Reset()
  169. h.sha.Write(key)
  170. h.sha.Read(t.hashKeyBuf[:])
  171. returnHasherToPool(h)
  172. return t.hashKeyBuf[:]
  173. }
  174. // getSecKeyCache returns the current secure key cache, creating a new one if
  175. // ownership changed (i.e. the current secure trie is a copy of another owning
  176. // the actual cache).
  177. func (t *SecureTrie) getSecKeyCache() map[string][]byte {
  178. if t != t.secKeyCacheOwner {
  179. t.secKeyCacheOwner = t
  180. t.secKeyCache = make(map[string][]byte)
  181. }
  182. return t.secKeyCache
  183. }