secure_trie.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. var secureKeyPrefix = []byte("secure-key-")
  23. const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash
  24. // SecureTrie wraps a trie with key hashing. In a secure trie, all
  25. // access operations hash the key using keccak256. This prevents
  26. // calling code from creating long chains of nodes that
  27. // increase the access time.
  28. //
  29. // Contrary to a regular trie, a SecureTrie can only be created with
  30. // New and must have an attached database. The database also stores
  31. // the preimage of each key.
  32. //
  33. // SecureTrie is not safe for concurrent use.
  34. type SecureTrie struct {
  35. trie Trie
  36. hashKeyBuf [secureKeyLength]byte
  37. secKeyBuf [200]byte
  38. secKeyCache map[string][]byte
  39. secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch
  40. }
  41. // NewSecure creates a trie with an existing root node from db.
  42. //
  43. // If root is the zero hash or the sha3 hash of an empty string, the
  44. // trie is initially empty. Otherwise, New will panic if db is nil
  45. // and returns MissingNodeError if the root node cannot be found.
  46. //
  47. // Accessing the trie loads nodes from db on demand.
  48. // Loaded nodes are kept around until their 'cache generation' expires.
  49. // A new cache generation is created by each call to Commit.
  50. // cachelimit sets the number of past cache generations to keep.
  51. func NewSecure(root common.Hash, db Database, cachelimit uint16) (*SecureTrie, error) {
  52. if db == nil {
  53. panic("NewSecure called with nil database")
  54. }
  55. trie, err := New(root, db)
  56. if err != nil {
  57. return nil, err
  58. }
  59. trie.SetCacheLimit(cachelimit)
  60. return &SecureTrie{trie: *trie}, nil
  61. }
  62. // Get returns the value for key stored in the trie.
  63. // The value bytes must not be modified by the caller.
  64. func (t *SecureTrie) Get(key []byte) []byte {
  65. res, err := t.TryGet(key)
  66. if err != nil {
  67. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  68. }
  69. return res
  70. }
  71. // TryGet returns the value for key stored in the trie.
  72. // The value bytes must not be modified by the caller.
  73. // If a node was not found in the database, a MissingNodeError is returned.
  74. func (t *SecureTrie) TryGet(key []byte) ([]byte, error) {
  75. return t.trie.TryGet(t.hashKey(key))
  76. }
  77. // Update associates key with value in the trie. Subsequent calls to
  78. // Get will return value. If value has length zero, any existing value
  79. // is deleted from the trie and calls to Get will return nil.
  80. //
  81. // The value bytes must not be modified by the caller while they are
  82. // stored in the trie.
  83. func (t *SecureTrie) Update(key, value []byte) {
  84. if err := t.TryUpdate(key, value); err != nil {
  85. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  86. }
  87. }
  88. // TryUpdate associates key with value in the trie. Subsequent calls to
  89. // Get will return value. If value has length zero, any existing value
  90. // is deleted from the trie and calls to Get will return nil.
  91. //
  92. // The value bytes must not be modified by the caller while they are
  93. // stored in the trie.
  94. //
  95. // If a node was not found in the database, a MissingNodeError is returned.
  96. func (t *SecureTrie) TryUpdate(key, value []byte) error {
  97. hk := t.hashKey(key)
  98. err := t.trie.TryUpdate(hk, value)
  99. if err != nil {
  100. return err
  101. }
  102. t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
  103. return nil
  104. }
  105. // Delete removes any existing value for key from the trie.
  106. func (t *SecureTrie) Delete(key []byte) {
  107. if err := t.TryDelete(key); err != nil {
  108. log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
  109. }
  110. }
  111. // TryDelete removes any existing value for key from the trie.
  112. // If a node was not found in the database, a MissingNodeError is returned.
  113. func (t *SecureTrie) TryDelete(key []byte) error {
  114. hk := t.hashKey(key)
  115. delete(t.getSecKeyCache(), string(hk))
  116. return t.trie.TryDelete(hk)
  117. }
  118. // GetKey returns the sha3 preimage of a hashed key that was
  119. // previously used to store a value.
  120. func (t *SecureTrie) GetKey(shaKey []byte) []byte {
  121. if key, ok := t.getSecKeyCache()[string(shaKey)]; ok {
  122. return key
  123. }
  124. key, _ := t.trie.db.Get(t.secKey(shaKey))
  125. return key
  126. }
  127. // Commit writes all nodes and the secure hash pre-images to the trie's database.
  128. // Nodes are stored with their sha3 hash as the key.
  129. //
  130. // Committing flushes nodes from memory. Subsequent Get calls will load nodes
  131. // from the database.
  132. func (t *SecureTrie) Commit() (root common.Hash, err error) {
  133. return t.CommitTo(t.trie.db)
  134. }
  135. func (t *SecureTrie) Hash() common.Hash {
  136. return t.trie.Hash()
  137. }
  138. func (t *SecureTrie) Root() []byte {
  139. return t.trie.Root()
  140. }
  141. func (t *SecureTrie) NodeIterator() NodeIterator {
  142. return t.trie.NodeIterator()
  143. }
  144. // CommitTo writes all nodes and the secure hash pre-images to the given database.
  145. // Nodes are stored with their sha3 hash as the key.
  146. //
  147. // Committing flushes nodes from memory. Subsequent Get calls will load nodes from
  148. // the trie's database. Calling code must ensure that the changes made to db are
  149. // written back to the trie's attached database before using the trie.
  150. func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
  151. if len(t.getSecKeyCache()) > 0 {
  152. for hk, key := range t.secKeyCache {
  153. if err := db.Put(t.secKey([]byte(hk)), key); err != nil {
  154. return common.Hash{}, err
  155. }
  156. }
  157. t.secKeyCache = make(map[string][]byte)
  158. }
  159. return t.trie.CommitTo(db)
  160. }
  161. // secKey returns the database key for the preimage of key, as an ephemeral buffer.
  162. // The caller must not hold onto the return value because it will become
  163. // invalid on the next call to hashKey or secKey.
  164. func (t *SecureTrie) secKey(key []byte) []byte {
  165. buf := append(t.secKeyBuf[:0], secureKeyPrefix...)
  166. buf = append(buf, key...)
  167. return buf
  168. }
  169. // hashKey returns the hash of key as an ephemeral buffer.
  170. // The caller must not hold onto the return value because it will become
  171. // invalid on the next call to hashKey or secKey.
  172. func (t *SecureTrie) hashKey(key []byte) []byte {
  173. h := newHasher(0, 0)
  174. h.sha.Reset()
  175. h.sha.Write(key)
  176. buf := h.sha.Sum(t.hashKeyBuf[:0])
  177. returnHasherToPool(h)
  178. return buf
  179. }
  180. // getSecKeyCache returns the current secure key cache, creating a new one if
  181. // ownership changed (i.e. the current secure trie is a copy of another owning
  182. // the actual cache).
  183. func (t *SecureTrie) getSecKeyCache() map[string][]byte {
  184. if t != t.secKeyCacheOwner {
  185. t.secKeyCacheOwner = t
  186. t.secKeyCache = make(map[string][]byte)
  187. }
  188. return t.secKeyCache
  189. }