github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/proof.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 //</624450123149086720> 11 12 13 package trie 14 15 import ( 16 "bytes" 17 "fmt" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/crypto" 21 "github.com/ethereum/go-ethereum/ethdb" 22 "github.com/ethereum/go-ethereum/log" 23 "github.com/ethereum/go-ethereum/rlp" 24 ) 25 26 //prove为key构造了一个merkle证明。结果包含所有编码节点 27 //在键处的值的路径上。值本身也包含在最后一个 28 //节点,可以通过验证证据来检索。 29 // 30 //如果trie不包含键的值,则返回的证明包含所有 31 //键的最长现有前缀的节点(至少是根节点),结束 32 //证明没有键的节点。 33 func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { 34 //收集键路径上的所有节点。 35 key = keybytesToHex(key) 36 nodes := []node{} 37 tn := t.root 38 for len(key) > 0 && tn != nil { 39 switch n := tn.(type) { 40 case *shortNode: 41 if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { 42 //trie不包含密钥。 43 tn = nil 44 } else { 45 tn = n.Val 46 key = key[len(n.Key):] 47 } 48 nodes = append(nodes, n) 49 case *fullNode: 50 tn = n.Children[key[0]] 51 key = key[1:] 52 nodes = append(nodes, n) 53 case hashNode: 54 var err error 55 tn, err = t.resolveHash(n, nil) 56 if err != nil { 57 log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) 58 return err 59 } 60 default: 61 panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) 62 } 63 } 64 hasher := newHasher(0, 0, nil) 65 defer returnHasherToPool(hasher) 66 67 for i, n := range nodes { 68 //别费心检查这里的错误,因为哈瑟惊慌失措 69 //如果编码不起作用,而且我们没有写入任何数据库。 70 n, _, _ = hasher.hashChildren(n, nil) 71 hn, _ := hasher.store(n, nil, false) 72 if hash, ok := hn.(hashNode); ok || i == 0 { 73 //如果节点的数据库编码是哈希(或 74 //根节点),它成为一个证明元素。 75 if fromLevel > 0 { 76 fromLevel-- 77 } else { 78 enc, _ := rlp.EncodeToBytes(n) 79 if !ok { 80 hash = crypto.Keccak256(enc) 81 } 82 proofDb.Put(hash, enc) 83 } 84 } 85 } 86 return nil 87 } 88 89 //prove为key构造了一个merkle证明。结果包含所有编码节点 90 //在键处的值的路径上。值本身也包含在最后一个 91 //节点,可以通过验证证据来检索。 92 // 93 //如果trie不包含键的值,则返回的证明包含所有 94 //键的最长现有前缀的节点(至少是根节点),结束 95 //证明没有键的节点。 96 func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { 97 return t.trie.Prove(key, fromLevel, proofDb) 98 } 99 100 //验证校对检查Merkle校对。给定的证明必须包含 101 //用给定的根散列值键入trie。VerifyProof返回一个错误,如果 102 //证明包含无效的trie节点或错误的值。 103 func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, nodes int, err error) { 104 key = keybytesToHex(key) 105 wantHash := rootHash 106 for i := 0; ; i++ { 107 buf, _ := proofDb.Get(wantHash[:]) 108 if buf == nil { 109 return nil, i, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash) 110 } 111 n, err := decodeNode(wantHash[:], buf, 0) 112 if err != nil { 113 return nil, i, fmt.Errorf("bad proof node %d: %v", i, err) 114 } 115 keyrest, cld := get(n, key) 116 switch cld := cld.(type) { 117 case nil: 118 //trie不包含密钥。 119 return nil, i, nil 120 case hashNode: 121 key = keyrest 122 copy(wantHash[:], cld) 123 case valueNode: 124 return cld, i + 1, nil 125 } 126 } 127 } 128 129 func get(tn node, key []byte) ([]byte, node) { 130 for { 131 switch n := tn.(type) { 132 case *shortNode: 133 if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { 134 return nil, nil 135 } 136 tn = n.Val 137 key = key[len(n.Key):] 138 case *fullNode: 139 tn = n.Children[key[0]] 140 key = key[1:] 141 case hashNode: 142 return key, n 143 case nil: 144 return key, nil 145 case valueNode: 146 return nil, n 147 default: 148 panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) 149 } 150 } 151 } 152