github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/internal/proofs/convert.go (about) 1 package proofs 2 3 import ( 4 "fmt" 5 "math/bits" 6 7 "github.com/fibonacci-chain/fbc/libs/tendermint/proto/crypto/merkle" 8 9 ics23 "github.com/confio/ics23/go" 10 ) 11 12 // ConvertExistenceProof will convert the given proof into a valid 13 // existence proof, if that's what it is. 14 // 15 // This is the simplest case of the range proof and we will focus on 16 // demoing compatibility here 17 func ConvertExistenceProof(p *merkle.SimpleProof, key, value []byte) (*ics23.ExistenceProof, error) { 18 path, err := convertInnerOps(p) 19 if err != nil { 20 return nil, err 21 } 22 23 proof := &ics23.ExistenceProof{ 24 Key: key, 25 Value: value, 26 Leaf: convertLeafOp(), 27 Path: path, 28 } 29 return proof, nil 30 } 31 32 // this is adapted from merkle/hash.go:leafHash() 33 // and merkle/simple_map.go:KVPair.Bytes() 34 func convertLeafOp() *ics23.LeafOp { 35 prefix := []byte{0} 36 37 return &ics23.LeafOp{ 38 Hash: ics23.HashOp_SHA256, 39 PrehashKey: ics23.HashOp_NO_HASH, 40 PrehashValue: ics23.HashOp_SHA256, 41 Length: ics23.LengthOp_VAR_PROTO, 42 Prefix: prefix, 43 } 44 } 45 46 func convertInnerOps(p *merkle.SimpleProof) ([]*ics23.InnerOp, error) { 47 inners := make([]*ics23.InnerOp, 0, len(p.Aunts)) 48 path := buildPath(p.Index, p.Total) 49 50 if len(p.Aunts) != len(path) { 51 return nil, fmt.Errorf("calculated a path different length (%d) than provided by SimpleProof (%d)", len(path), len(p.Aunts)) 52 } 53 54 for i, aunt := range p.Aunts { 55 auntRight := path[i] 56 57 // combine with: 0x01 || lefthash || righthash 58 inner := &ics23.InnerOp{Hash: ics23.HashOp_SHA256} 59 if auntRight { 60 inner.Prefix = []byte{1} 61 inner.Suffix = aunt 62 } else { 63 inner.Prefix = append([]byte{1}, aunt...) 64 } 65 inners = append(inners, inner) 66 } 67 return inners, nil 68 } 69 70 // buildPath returns a list of steps from leaf to root 71 // in each step, true means index is left side, false index is right side 72 // code adapted from merkle/simple_proof.go:computeHashFromAunts 73 func buildPath(idx, total int64) []bool { 74 if total < 2 { 75 return nil 76 } 77 numLeft := getSplitPoint(total) 78 goLeft := idx < numLeft 79 80 // we put goLeft at the end of the array, as we recurse from top to bottom, 81 // and want the leaf to be first in array, root last 82 if goLeft { 83 return append(buildPath(idx, numLeft), goLeft) 84 } 85 return append(buildPath(idx-numLeft, total-numLeft), goLeft) 86 } 87 88 func getSplitPoint(length int64) int64 { 89 if length < 1 { 90 panic("Trying to split a tree with size < 1") 91 } 92 uLength := uint(length) 93 bitlen := bits.Len(uLength) 94 k := int64(1 << uint(bitlen-1)) 95 if k == length { 96 k >>= 1 97 } 98 return k 99 }