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  }