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  }