github.com/turingchain2020/turingchain@v1.1.21/system/store/mavl/db/proof.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package mavl 6 7 import ( 8 "bytes" 9 10 "github.com/turingchain2020/turingchain/types" 11 "github.com/golang/protobuf/proto" 12 ) 13 14 //const proofLimit = 1 << 16 // 64 KB 15 16 // Proof merkle avl tree proof证明结构体 17 type Proof struct { 18 LeafHash []byte 19 InnerNodes []*types.InnerNode 20 RootHash []byte 21 } 22 23 var sha256Len = 32 24 25 // Verify key:value 的proof确认 26 func (proof *Proof) Verify(key []byte, value []byte, root []byte) bool { 27 if !bytes.Equal(proof.RootHash, root) { 28 return false 29 } 30 leafNode := types.LeafNode{Key: key, Value: value, Height: 0, Size: 1} 31 leafHash := leafNode.Hash() 32 33 hashLen := sha256Len 34 if len(proof.LeafHash) > hashLen { 35 proof.LeafHash = proof.LeafHash[len(proof.LeafHash)-hashLen:] 36 } 37 38 if !bytes.Equal(leafHash, proof.LeafHash) { 39 return false 40 } 41 hash := leafHash 42 for _, branch := range proof.InnerNodes { 43 //hash = branch.ProofHash(hash) 44 hash = InnerNodeProofHash(hash, branch) 45 } 46 return bytes.Equal(proof.RootHash, hash) 47 } 48 49 // Root 证明节点的root hash 50 func (proof *Proof) Root() []byte { 51 return proof.RootHash 52 } 53 54 // ReadProof will deserialize a MAVLProof from bytes 55 func ReadProof(roothash []byte, leafhash []byte, data []byte) (*Proof, error) { 56 var mavlproof types.MAVLProof 57 err := proto.Unmarshal(data, &mavlproof) 58 if err != nil { 59 treelog.Error("Unmarshal err!", "err", err) 60 return nil, err 61 } 62 var merkleAvlProof Proof 63 merkleAvlProof.InnerNodes = mavlproof.InnerNodes 64 merkleAvlProof.LeafHash = leafhash 65 merkleAvlProof.RootHash = roothash 66 return &merkleAvlProof, nil 67 } 68 69 // InnerNodeProofHash 计算inner节点的hash 70 func InnerNodeProofHash(childHash []byte, branch *types.InnerNode) []byte { 71 var innernode types.InnerNode 72 73 innernode.Height = branch.Height 74 innernode.Size = branch.Size 75 76 // left is nil 77 if len(branch.LeftHash) == 0 { 78 innernode.LeftHash = childHash 79 innernode.RightHash = branch.RightHash 80 } else { 81 innernode.LeftHash = branch.LeftHash 82 innernode.RightHash = childHash 83 } 84 return innernode.Hash() 85 } 86 87 func (node *Node) constructProof(t *Tree, key []byte, valuePtr *[]byte, proof *Proof) (exists bool) { 88 if node.height == 0 { 89 if bytes.Equal(node.key, key) { 90 *valuePtr = node.value 91 proof.LeafHash = node.hash 92 return true 93 } 94 return false 95 } 96 if bytes.Compare(key, node.key) < 0 { 97 exists := node.getLeftNode(t).constructProof(t, key, valuePtr, proof) 98 if !exists { 99 return false 100 } 101 branch := types.InnerNode{ 102 Height: node.height, 103 Size: node.size, 104 LeftHash: nil, 105 RightHash: node.getRightNode(t).hash, 106 } 107 proof.InnerNodes = append(proof.InnerNodes, &branch) 108 return true 109 } 110 exists = node.getRightNode(t).constructProof(t, key, valuePtr, proof) 111 if !exists { 112 return false 113 } 114 branch := types.InnerNode{ 115 Height: node.height, 116 Size: node.size, 117 LeftHash: node.getLeftNode(t).hash, 118 RightHash: nil, 119 } 120 proof.InnerNodes = append(proof.InnerNodes, &branch) 121 return true 122 } 123 124 // ConstructProof Returns nil, nil if key is not in tree. 125 func (t *Tree) ConstructProof(key []byte) (value []byte, proof *Proof) { 126 if t.root == nil { 127 return nil, nil 128 } 129 t.root.Hash(t) // Ensure that all hashes are calculated. 130 proof = &Proof{ 131 RootHash: t.root.hash, 132 } 133 exists := t.root.constructProof(t, key, &value, proof) 134 if exists { 135 return value, proof 136 } 137 return nil, nil 138 }