github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/hasher.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 //</624450122876456960> 11 12 13 package trie 14 15 import ( 16 "hash" 17 "sync" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/rlp" 21 "golang.org/x/crypto/sha3" 22 ) 23 24 type hasher struct { 25 tmp sliceBuffer 26 sha keccakState 27 cachegen uint16 28 cachelimit uint16 29 onleaf LeafCallback 30 } 31 32 //keccakstate包裹sha3.state。除了通常的哈希方法外,它还支持 33 //读取以从哈希状态获取可变数量的数据。读取比求和快 34 //因为它不复制内部状态,而是修改内部状态。 35 type keccakState interface { 36 hash.Hash 37 Read([]byte) (int, error) 38 } 39 40 type sliceBuffer []byte 41 42 func (b *sliceBuffer) Write(data []byte) (n int, err error) { 43 *b = append(*b, data...) 44 return len(data), nil 45 } 46 47 func (b *sliceBuffer) Reset() { 48 *b = (*b)[:0] 49 } 50 51 //哈希存在于全局数据库中。 52 var hasherPool = sync.Pool{ 53 New: func() interface{} { 54 return &hasher{ 55 tmp: make(sliceBuffer, 0, 550), //cap和完整的fullnode一样大。 56 sha: sha3.NewLegacyKeccak256().(keccakState), 57 } 58 }, 59 } 60 61 func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher { 62 h := hasherPool.Get().(*hasher) 63 h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf 64 return h 65 } 66 67 func returnHasherToPool(h *hasher) { 68 hasherPool.Put(h) 69 } 70 71 //哈希将节点向下折叠为哈希节点,同时返回 72 //原始节点初始化为计算哈希以替换原始节点。 73 func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) { 74 //如果我们不存储节点,只需要散列,使用可用的缓存数据 75 if hash, dirty := n.cache(); hash != nil { 76 if db == nil { 77 return hash, n, nil 78 } 79 if n.canUnload(h.cachegen, h.cachelimit) { 80 //从缓存中卸载节点。其所有子节点都将具有一个较低或相等的 81 //缓存生成编号。 82 cacheUnloadCounter.Inc(1) 83 return hash, hash, nil 84 } 85 if !dirty { 86 return hash, n, nil 87 } 88 } 89 //尚未处理或需要存储,请带孩子走 90 collapsed, cached, err := h.hashChildren(n, db) 91 if err != nil { 92 return hashNode{}, n, err 93 } 94 hashed, err := h.store(collapsed, db, force) 95 if err != nil { 96 return hashNode{}, n, err 97 } 98 //缓存节点的哈希以便稍后重用和删除 99 //提交模式下的脏标志。可以直接指定这些值 100 //不首先复制节点,因为hashchildren会复制它。 101 cachedHash, _ := hashed.(hashNode) 102 switch cn := cached.(type) { 103 case *shortNode: 104 cn.flags.hash = cachedHash 105 if db != nil { 106 cn.flags.dirty = false 107 } 108 case *fullNode: 109 cn.flags.hash = cachedHash 110 if db != nil { 111 cn.flags.dirty = false 112 } 113 } 114 return hashed, cached, nil 115 } 116 117 //hashchildren将节点的子节点替换为其哈希,如果 118 //子节点的大小大于哈希,同时返回折叠的节点 119 //用缓存的子哈希替换原始节点。 120 func (h *hasher) hashChildren(original node, db *Database) (node, node, error) { 121 var err error 122 123 switch n := original.(type) { 124 case *shortNode: 125 //散列短节点的子节点,缓存新散列的子树 126 collapsed, cached := n.copy(), n.copy() 127 collapsed.Key = hexToCompact(n.Key) 128 cached.Key = common.CopyBytes(n.Key) 129 130 if _, ok := n.Val.(valueNode); !ok { 131 collapsed.Val, cached.Val, err = h.hash(n.Val, db, false) 132 if err != nil { 133 return original, original, err 134 } 135 } 136 return collapsed, cached, nil 137 138 case *fullNode: 139 //散列完整节点的子节点,缓存新散列的子树 140 collapsed, cached := n.copy(), n.copy() 141 142 for i := 0; i < 16; i++ { 143 if n.Children[i] != nil { 144 collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false) 145 if err != nil { 146 return original, original, err 147 } 148 } 149 } 150 cached.Children[16] = n.Children[16] 151 return collapsed, cached, nil 152 153 default: 154 //值和哈希节点没有子节点,因此它们保持原样 155 return n, original, nil 156 } 157 } 158 159 //store散列节点n,如果指定了存储层,它将写入 160 //它的键/值对并跟踪任何节点->子引用以及任何 161 //节点->外部trie引用。 162 func (h *hasher) store(n node, db *Database, force bool) (node, error) { 163 //不要存储哈希或空节点。 164 if _, isHash := n.(hashNode); n == nil || isHash { 165 return n, nil 166 } 167 //生成节点的rlp编码 168 h.tmp.Reset() 169 if err := rlp.Encode(&h.tmp, n); err != nil { 170 panic("encode error: " + err.Error()) 171 } 172 if len(h.tmp) < 32 && !force { 173 return n, nil //小于32字节的节点存储在其父节点中 174 } 175 //较大的节点被其散列替换并存储在数据库中。 176 hash, _ := n.cache() 177 if hash == nil { 178 hash = h.makeHashNode(h.tmp) 179 } 180 181 if db != nil { 182 //我们正在将trie节点合并到中间内存缓存中 183 hash := common.BytesToHash(hash) 184 185 db.lock.Lock() 186 db.insert(hash, h.tmp, n) 187 db.lock.Unlock() 188 189 //从“帐户”->“存储检索”跟踪外部引用 190 if h.onleaf != nil { 191 switch n := n.(type) { 192 case *shortNode: 193 if child, ok := n.Val.(valueNode); ok { 194 h.onleaf(child, hash) 195 } 196 case *fullNode: 197 for i := 0; i < 16; i++ { 198 if child, ok := n.Children[i].(valueNode); ok { 199 h.onleaf(child, hash) 200 } 201 } 202 } 203 } 204 } 205 return hash, nil 206 } 207 208 func (h *hasher) makeHashNode(data []byte) hashNode { 209 n := make(hashNode, h.sha.Size()) 210 h.sha.Reset() 211 h.sha.Write(data) 212 h.sha.Read(n) 213 return n 214 } 215