github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/secure_trie.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:45</date> 10 //</624450123312664576> 11 12 13 package trie 14 15 import ( 16 "fmt" 17 18 "github.com/ethereum/go-ethereum/common" 19 "github.com/ethereum/go-ethereum/log" 20 ) 21 22 //securetrie使用键哈希对trie进行包装。在安全的测试中,所有 23 //访问操作使用keccak256散列密钥。这防止 24 //通过创建长的节点链来调用代码 25 //增加访问时间。 26 // 27 //与常规trie相反,只能使用 28 //新建,必须具有附加的数据库。数据库还存储 29 //每个键的预映像。 30 // 31 //SecureTrie不能同时使用。 32 type SecureTrie struct { 33 trie Trie 34 hashKeyBuf [common.HashLength]byte 35 secKeyCache map[string][]byte 36 secKeyCacheOwner *SecureTrie //指向self的指针,不匹配时替换密钥缓存 37 } 38 39 //NewSecure从备份数据库创建具有现有根节点的trie 40 //以及可选的中间内存节点池。 41 // 42 //如果根是空字符串的零哈希或sha3哈希,则 43 //trie最初是空的。否则,如果db为零,new将恐慌。 44 //如果找不到根节点,则返回MissingNodeError。 45 // 46 //访问trie会根据需要从数据库或节点池加载节点。 47 //加载的节点将一直保留,直到其“缓存生成”过期。 48 //每次调用commit都会创建新的缓存生成。 49 //cachelimit设置要保留的上一代缓存的数量。 50 func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, error) { 51 if db == nil { 52 panic("trie.NewSecure called without a database") 53 } 54 trie, err := New(root, db) 55 if err != nil { 56 return nil, err 57 } 58 trie.SetCacheLimit(cachelimit) 59 return &SecureTrie{trie: *trie}, nil 60 } 61 62 //get返回存储在trie中的键的值。 63 //调用方不能修改值字节。 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 72 //Tryget返回存储在trie中的键的值。 73 //调用方不能修改值字节。 74 //如果在数据库中找不到节点,则返回MissingNodeError。 75 func (t *SecureTrie) TryGet(key []byte) ([]byte, error) { 76 return t.trie.TryGet(t.hashKey(key)) 77 } 78 79 //更新trie中的关联键和值。后续呼叫 80 //get将返回值。如果值的长度为零,则任何现有值 81 //从trie中删除,调用get将返回nil。 82 // 83 //当值字节是 84 //存储在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 91 //TryUpdate将键与trie中的值关联。后续呼叫 92 //get将返回值。如果值的长度为零,则任何现有值 93 //从trie中删除,调用get将返回nil。 94 // 95 //当值字节是 96 //存储在trie中。 97 // 98 //如果在数据库中找不到节点,则返回MissingNodeError。 99 func (t *SecureTrie) TryUpdate(key, value []byte) error { 100 hk := t.hashKey(key) 101 err := t.trie.TryUpdate(hk, value) 102 if err != nil { 103 return err 104 } 105 t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) 106 return nil 107 } 108 109 //删除从trie中删除键的任何现有值。 110 func (t *SecureTrie) Delete(key []byte) { 111 if err := t.TryDelete(key); err != nil { 112 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 113 } 114 } 115 116 //Trydelete从trie中删除键的任何现有值。 117 //如果在数据库中找不到节点,则返回MissingNodeError。 118 func (t *SecureTrie) TryDelete(key []byte) error { 119 hk := t.hashKey(key) 120 delete(t.getSecKeyCache(), string(hk)) 121 return t.trie.TryDelete(hk) 122 } 123 124 //getkey返回哈希键的sha3 preimage 125 //以前用于存储值。 126 func (t *SecureTrie) GetKey(shaKey []byte) []byte { 127 if key, ok := t.getSecKeyCache()[string(shaKey)]; ok { 128 return key 129 } 130 key, _ := t.trie.db.preimage(common.BytesToHash(shaKey)) 131 return key 132 } 133 134 //commit将所有节点和安全哈希预映像写入trie的数据库。 135 //节点以其sha3散列作为密钥存储。 136 // 137 //提交将刷新内存中的节点。后续的get调用将加载节点 138 //从数据库中。 139 func (t *SecureTrie) Commit(onleaf LeafCallback) (root common.Hash, err error) { 140 //将所有预映像写入实际磁盘数据库 141 if len(t.getSecKeyCache()) > 0 { 142 t.trie.db.lock.Lock() 143 for hk, key := range t.secKeyCache { 144 t.trie.db.insertPreimage(common.BytesToHash([]byte(hk)), key) 145 } 146 t.trie.db.lock.Unlock() 147 148 t.secKeyCache = make(map[string][]byte) 149 } 150 //将trie提交到其中间节点数据库 151 return t.trie.Commit(onleaf) 152 } 153 154 //hash返回securetrie的根哈希。它不会写信给 155 //即使trie没有数据库也可以使用。 156 func (t *SecureTrie) Hash() common.Hash { 157 return t.trie.Hash() 158 } 159 160 //root返回securetrie的根哈希。 161 //已弃用:请改用哈希。 162 func (t *SecureTrie) Root() []byte { 163 return t.trie.Root() 164 } 165 166 //copy返回securetrie的副本。 167 func (t *SecureTrie) Copy() *SecureTrie { 168 cpy := *t 169 return &cpy 170 } 171 172 //nodeiterator返回返回底层trie节点的迭代器。迭代 173 //从给定的开始键之后的键开始。 174 func (t *SecureTrie) NodeIterator(start []byte) NodeIterator { 175 return t.trie.NodeIterator(start) 176 } 177 178 //hash key返回作为临时缓冲区的键的哈希。 179 //调用方不能保留返回值,因为它将成为 180 //下次调用hashkey或seckey时无效。 181 func (t *SecureTrie) hashKey(key []byte) []byte { 182 h := newHasher(0, 0, nil) 183 h.sha.Reset() 184 h.sha.Write(key) 185 buf := h.sha.Sum(t.hashKeyBuf[:0]) 186 returnHasherToPool(h) 187 return buf 188 } 189 190 //GetSecKeyCache返回当前的安全密钥缓存,如果 191 //所有权已更改(即当前安全的trie是另一个拥有者的副本 192 //实际缓存)。 193 func (t *SecureTrie) getSecKeyCache() map[string][]byte { 194 if t != t.secKeyCacheOwner { 195 t.secKeyCacheOwner = t 196 t.secKeyCache = make(map[string][]byte) 197 } 198 return t.secKeyCache 199 } 200