secure_trie.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. "hash"
  19. "github.com/ethereum/go-ethereum/common"
  20. "github.com/ethereum/go-ethereum/crypto/sha3"
  21. "github.com/ethereum/go-ethereum/logger"
  22. "github.com/ethereum/go-ethereum/logger/glog"
  23. )
  24. var secureKeyPrefix = []byte("secure-key-")
  25. // SecureTrie wraps a trie with key hashing. In a secure trie, all
  26. // access operations hash the key using keccak256. This prevents
  27. // calling code from creating long chains of nodes that
  28. // increase the access time.
  29. //
  30. // Contrary to a regular trie, a SecureTrie can only be created with
  31. // New and must have an attached database. The database also stores
  32. // the preimage of each key.
  33. //
  34. // SecureTrie is not safe for concurrent use.
  35. type SecureTrie struct {
  36. *Trie
  37. hash hash.Hash
  38. hashKeyBuf []byte
  39. secKeyBuf []byte
  40. secKeyCache map[string][]byte
  41. }
  42. // NewSecure creates a trie with an existing root node from db.
  43. //
  44. // If root is the zero hash or the sha3 hash of an empty string, the
  45. // trie is initially empty. Otherwise, New will panic if db is nil
  46. // and returns MissingNodeError if the root node cannot be found.
  47. // Accessing the trie loads nodes from db on demand.
  48. func NewSecure(root common.Hash, db Database) (*SecureTrie, error) {
  49. if db == nil {
  50. panic("NewSecure called with nil database")
  51. }
  52. trie, err := New(root, db)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return &SecureTrie{
  57. Trie: trie,
  58. secKeyCache: make(map[string][]byte),
  59. }, nil
  60. }
  61. // Get returns the value for key stored in the trie.
  62. // The value bytes must not be modified by the caller.
  63. func (t *SecureTrie) Get(key []byte) []byte {
  64. res, err := t.TryGet(key)
  65. if err != nil && glog.V(logger.Error) {
  66. glog.Errorf("Unhandled trie error: %v", err)
  67. }
  68. return res
  69. }
  70. // TryGet returns the value for key stored in the trie.
  71. // The value bytes must not be modified by the caller.
  72. // If a node was not found in the database, a MissingNodeError is returned.
  73. func (t *SecureTrie) TryGet(key []byte) ([]byte, error) {
  74. return t.Trie.TryGet(t.hashKey(key))
  75. }
  76. // Update associates key with value in the trie. Subsequent calls to
  77. // Get will return value. If value has length zero, any existing value
  78. // is deleted from the trie and calls to Get will return nil.
  79. //
  80. // The value bytes must not be modified by the caller while they are
  81. // stored in the trie.
  82. func (t *SecureTrie) Update(key, value []byte) {
  83. if err := t.TryUpdate(key, value); err != nil && glog.V(logger.Error) {
  84. glog.Errorf("Unhandled trie error: %v", err)
  85. }
  86. }
  87. // TryUpdate associates key with value in the trie. Subsequent calls to
  88. // Get will return value. If value has length zero, any existing value
  89. // is deleted from the trie and calls to Get will return nil.
  90. //
  91. // The value bytes must not be modified by the caller while they are
  92. // stored in the trie.
  93. //
  94. // If a node was not found in the database, a MissingNodeError is returned.
  95. func (t *SecureTrie) TryUpdate(key, value []byte) error {
  96. hk := t.hashKey(key)
  97. err := t.Trie.TryUpdate(hk, value)
  98. if err != nil {
  99. return err
  100. }
  101. t.secKeyCache[string(hk)] = common.CopyBytes(key)
  102. return nil
  103. }
  104. // Delete removes any existing value for key from the trie.
  105. func (t *SecureTrie) Delete(key []byte) {
  106. if err := t.TryDelete(key); err != nil && glog.V(logger.Error) {
  107. glog.Errorf("Unhandled trie error: %v", err)
  108. }
  109. }
  110. // TryDelete removes any existing value for key from the trie.
  111. // If a node was not found in the database, a MissingNodeError is returned.
  112. func (t *SecureTrie) TryDelete(key []byte) error {
  113. hk := t.hashKey(key)
  114. delete(t.secKeyCache, string(hk))
  115. return t.Trie.TryDelete(hk)
  116. }
  117. // GetKey returns the sha3 preimage of a hashed key that was
  118. // previously used to store a value.
  119. func (t *SecureTrie) GetKey(shaKey []byte) []byte {
  120. if key, ok := t.secKeyCache[string(shaKey)]; ok {
  121. return key
  122. }
  123. key, _ := t.Trie.db.Get(t.secKey(shaKey))
  124. return key
  125. }
  126. // Commit writes all nodes and the secure hash pre-images to the trie's database.
  127. // Nodes are stored with their sha3 hash as the key.
  128. //
  129. // Committing flushes nodes from memory. Subsequent Get calls will load nodes
  130. // from the database.
  131. func (t *SecureTrie) Commit() (root common.Hash, err error) {
  132. return t.CommitTo(t.db)
  133. }
  134. // CommitTo writes all nodes and the secure hash pre-images to the given database.
  135. // Nodes are stored with their sha3 hash as the key.
  136. //
  137. // Committing flushes nodes from memory. Subsequent Get calls will load nodes from
  138. // the trie's database. Calling code must ensure that the changes made to db are
  139. // written back to the trie's attached database before using the trie.
  140. func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
  141. if len(t.secKeyCache) > 0 {
  142. for hk, key := range t.secKeyCache {
  143. if err := db.Put(t.secKey([]byte(hk)), key); err != nil {
  144. return common.Hash{}, err
  145. }
  146. }
  147. t.secKeyCache = make(map[string][]byte)
  148. }
  149. n, clean, err := t.hashRoot(db)
  150. if err != nil {
  151. return (common.Hash{}), err
  152. }
  153. t.root = clean
  154. return common.BytesToHash(n.(hashNode)), nil
  155. }
  156. func (t *SecureTrie) secKey(key []byte) []byte {
  157. t.secKeyBuf = append(t.secKeyBuf[:0], secureKeyPrefix...)
  158. t.secKeyBuf = append(t.secKeyBuf, key...)
  159. return t.secKeyBuf
  160. }
  161. func (t *SecureTrie) hashKey(key []byte) []byte {
  162. if t.hash == nil {
  163. t.hash = sha3.NewKeccak256()
  164. t.hashKeyBuf = make([]byte, 32)
  165. }
  166. t.hash.Reset()
  167. t.hash.Write(key)
  168. t.hashKeyBuf = t.hash.Sum(t.hashKeyBuf[:0])
  169. return t.hashKeyBuf
  170. }