github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/iavl/proof_path.go (about) 1 package iavl 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // pathWithLeaf is a path to a leaf node and the leaf node itself. 9 type pathWithLeaf struct { 10 Path PathToLeaf `json:"path"` 11 Leaf proofLeafNode `json:"leaf"` 12 } 13 14 func (pwl pathWithLeaf) String() string { 15 return pwl.StringIndented("") 16 } 17 18 func (pwl pathWithLeaf) StringIndented(indent string) string { 19 return fmt.Sprintf(`pathWithLeaf{ 20 %s Path: %v 21 %s Leaf: %v 22 %s}`, 23 indent, pwl.Path.stringIndented(indent+" "), 24 indent, pwl.Leaf.stringIndented(indent+" "), 25 indent) 26 } 27 28 // `computeRootHash` computes the root hash with leaf node. 29 // Does not verify the root hash. 30 func (pwl pathWithLeaf) computeRootHash() []byte { 31 leafHash := pwl.Leaf.Hash() 32 return pwl.Path.computeRootHash(leafHash) 33 } 34 35 // ---------------------------------------- 36 37 // PathToLeaf represents an inner path to a leaf node. 38 // Note that the nodes are ordered such that the last one is closest 39 // to the root of the tree. 40 type PathToLeaf []proofInnerNode 41 42 func (pl PathToLeaf) String() string { 43 return pl.stringIndented("") 44 } 45 46 func (pl PathToLeaf) stringIndented(indent string) string { 47 if len(pl) == 0 { 48 return "empty-PathToLeaf" 49 } 50 strs := make([]string, len(pl)) 51 for i, pin := range pl { 52 if i == 20 { 53 strs[i] = fmt.Sprintf("... (%v total)", len(pl)) 54 break 55 } 56 strs[i] = fmt.Sprintf("%v:%v", i, pin.stringIndented(indent+" ")) 57 } 58 return fmt.Sprintf(`PathToLeaf{ 59 %s %v 60 %s}`, 61 indent, strings.Join(strs, "\n"+indent+" "), 62 indent) 63 } 64 65 // `computeRootHash` computes the root hash assuming some leaf hash. 66 // Does not verify the root hash. 67 func (pl PathToLeaf) computeRootHash(leafHash []byte) []byte { 68 hash := leafHash 69 for i := len(pl) - 1; i >= 0; i-- { 70 pin := pl[i] 71 hash = pin.Hash(hash) 72 } 73 return hash 74 } 75 76 func (pl PathToLeaf) isLeftmost() bool { 77 for _, node := range pl { 78 if len(node.Left) > 0 { 79 return false 80 } 81 } 82 return true 83 } 84 85 func (pl PathToLeaf) isRightmost() bool { 86 for _, node := range pl { 87 if len(node.Right) > 0 { 88 return false 89 } 90 } 91 return true 92 } 93 94 // returns -1 if invalid. 95 func (pl PathToLeaf) Index() (idx int64) { 96 for i, node := range pl { 97 if node.Left == nil { 98 continue 99 } else if node.Right == nil { 100 if i < len(pl)-1 { 101 idx += node.Size - pl[i+1].Size 102 } else { 103 idx += node.Size - 1 104 } 105 } else { 106 return -1 107 } 108 } 109 return idx 110 }