|
|
- package merkle
-
- import (
- "bytes"
- "crypto/sha256"
-
- "github.com/tendermint/tendermint/binary"
- . "github.com/tendermint/tendermint/common"
- )
-
- type IAVLProof struct {
- Root []byte
- Branches []IAVLProofBranch
- Leaf IAVLProofLeaf
- }
-
- func (proof *IAVLProof) Verify() bool {
- hash := proof.Leaf.Hash()
- // fmt.Printf("leaf hash: %X\n", hash)
- for i := len(proof.Branches) - 1; 0 <= i; i-- {
- hash = proof.Branches[i].Hash(hash)
- // fmt.Printf("branch hash: %X\n", hash)
- }
- // fmt.Printf("root: %X, computed: %X\n", proof.Root, hash)
- return bytes.Equal(proof.Root, hash)
- }
-
- type IAVLProofBranch struct {
- Height uint8
- Size uint
- Left []byte
- Right []byte
- }
-
- func (branch IAVLProofBranch) Hash(childHash []byte) []byte {
- hasher := sha256.New()
- buf := new(bytes.Buffer)
- n, err := int64(0), error(nil)
- binary.WriteUint8(branch.Height, buf, &n, &err)
- binary.WriteUvarint(branch.Size, buf, &n, &err)
- if branch.Left == nil {
- binary.WriteByteSlice(childHash, buf, &n, &err)
- binary.WriteByteSlice(branch.Right, buf, &n, &err)
- } else {
- binary.WriteByteSlice(branch.Left, buf, &n, &err)
- binary.WriteByteSlice(childHash, buf, &n, &err)
- }
- if err != nil {
- panic(Fmt("Failed to hash IAVLProofBranch: %v", err))
- }
- // fmt.Printf("Branch hash bytes: %X\n", buf.Bytes())
- hasher.Write(buf.Bytes())
- return hasher.Sum(nil)
- }
-
- type IAVLProofLeaf struct {
- KeyBytes []byte
- ValueBytes []byte
- }
-
- func (leaf IAVLProofLeaf) Hash() []byte {
- hasher := sha256.New()
- buf := new(bytes.Buffer)
- n, err := int64(0), error(nil)
- binary.WriteUint8(0, buf, &n, &err)
- binary.WriteUvarint(1, buf, &n, &err)
- binary.WriteByteSlice(leaf.KeyBytes, buf, &n, &err)
- binary.WriteByteSlice(leaf.ValueBytes, buf, &n, &err)
- if err != nil {
- panic(Fmt("Failed to hash IAVLProofLeaf: %v", err))
- }
- // fmt.Printf("Leaf hash bytes: %X\n", buf.Bytes())
- hasher.Write(buf.Bytes())
- return hasher.Sum(nil)
- }
-
- func (node *IAVLNode) constructProof(t *IAVLTree, key interface{}, proof *IAVLProof) (exists bool) {
- if node.height == 0 {
- if t.keyCodec.Compare(node.key, key) == 0 {
- keyBuf, valueBuf := new(bytes.Buffer), new(bytes.Buffer)
- n, err := int64(0), error(nil)
- t.keyCodec.Encode(node.key, keyBuf, &n, &err)
- if err != nil {
- panic(Fmt("Failed to encode node.key: %v", err))
- }
- t.valueCodec.Encode(node.value, valueBuf, &n, &err)
- if err != nil {
- panic(Fmt("Failed to encode node.value: %v", err))
- }
- leaf := IAVLProofLeaf{
- KeyBytes: keyBuf.Bytes(),
- ValueBytes: valueBuf.Bytes(),
- }
- proof.Leaf = leaf
- return true
- } else {
- return false
- }
- } else {
- if t.keyCodec.Compare(key, node.key) < 0 {
- branch := IAVLProofBranch{
- Height: node.height,
- Size: node.size,
- Left: nil,
- Right: node.getRightNode(t).hash,
- }
- if node.getRightNode(t).hash == nil {
- // fmt.Println(node.getRightNode(t))
- panic("WTF")
- }
- proof.Branches = append(proof.Branches, branch)
- return node.getLeftNode(t).constructProof(t, key, proof)
- } else {
- branch := IAVLProofBranch{
- Height: node.height,
- Size: node.size,
- Left: node.getLeftNode(t).hash,
- Right: nil,
- }
- proof.Branches = append(proof.Branches, branch)
- return node.getRightNode(t).constructProof(t, key, proof)
- }
- }
- }
-
- // Returns nil if key is not in tree.
- func (t *IAVLTree) ConstructProof(key interface{}) *IAVLProof {
- if t.root == nil {
- return nil
- }
- t.root.hashWithCount(t) // Ensure that all hashes are calculated.
- proof := &IAVLProof{
- Root: t.root.hash,
- }
- t.root.constructProof(t, key, proof)
- return proof
- }
|