github.com/prysmaticlabs/prysm@v1.4.4/shared/trieutil/helpers.go (about)

     1  package trieutil
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/prysmaticlabs/prysm/shared/hashutil"
     7  	"github.com/prysmaticlabs/prysm/shared/params"
     8  )
     9  
    10  // NextPowerOf2 returns the next power of 2 >= the input
    11  //
    12  // Spec pseudocode definition:
    13  //   def get_power_of_two_ceil(x: int) -> int:
    14  //    """
    15  //    Get the power of 2 for given input, or the closest higher power of 2 if the input is not a power of 2.
    16  //    Commonly used for "how many nodes do I need for a bottom tree layer fitting x elements?"
    17  //    Example: 0->1, 1->1, 2->2, 3->4, 4->4, 5->8, 6->8, 7->8, 8->8, 9->16.
    18  //    """
    19  //    if x <= 1:
    20  //        return 1
    21  //    elif x == 2:
    22  //        return 2
    23  //    else:
    24  //        return 2 * get_power_of_two_ceil((x + 1) // 2)
    25  func NextPowerOf2(n int) int {
    26  	if n <= 1 {
    27  		return 1
    28  	}
    29  	if n == 2 {
    30  		return n
    31  	}
    32  	return 2 * NextPowerOf2((n+1)/2)
    33  }
    34  
    35  // PrevPowerOf2 returns the previous power of 2 >= the input
    36  //
    37  // Spec pseudocode definition:
    38  //   def get_power_of_two_floor(x: int) -> int:
    39  //    """
    40  //    Get the power of 2 for given input, or the closest lower power of 2 if the input is not a power of 2.
    41  //    The zero case is a placeholder and not used for math with generalized indices.
    42  //    Commonly used for "what power of two makes up the root bit of the generalized index?"
    43  //    Example: 0->1, 1->1, 2->2, 3->2, 4->4, 5->4, 6->4, 7->4, 8->8, 9->8
    44  //    """
    45  //    if x <= 1:
    46  //        return 1
    47  //    if x == 2:
    48  //        return x
    49  //    else:
    50  //        return 2 * get_power_of_two_floor(x // 2)
    51  func PrevPowerOf2(n int) int {
    52  	if n <= 1 {
    53  		return 1
    54  	}
    55  	if n == 2 {
    56  		return n
    57  	}
    58  	return 2 * PrevPowerOf2(n/2)
    59  }
    60  
    61  // MerkleTree returns all the nodes in a merkle tree from inputting merkle leaves.
    62  //
    63  // Spec pseudocode definition:
    64  //   def merkle_tree(leaves: Sequence[Bytes32]) -> Sequence[Bytes32]:
    65  //    """
    66  //    Return an array representing the tree nodes by generalized index:
    67  //    [0, 1, 2, 3, 4, 5, 6, 7], where each layer is a power of 2. The 0 index is ignored. The 1 index is the root.
    68  //    The result will be twice the size as the padded bottom layer for the input leaves.
    69  //    """
    70  //    bottom_length = get_power_of_two_ceil(len(leaves))
    71  //    o = [Bytes32()] * bottom_length + list(leaves) + [Bytes32()] * (bottom_length - len(leaves))
    72  //    for i in range(bottom_length - 1, 0, -1):
    73  //        o[i] = hash(o[i * 2] + o[i * 2 + 1])
    74  //    return o
    75  func MerkleTree(leaves [][]byte) [][]byte {
    76  	paddedLength := NextPowerOf2(len(leaves))
    77  	parents := make([][]byte, paddedLength)
    78  	paddedLeaves := make([][]byte, paddedLength-len(leaves))
    79  
    80  	for i := 0; i < len(parents); i++ {
    81  		parents[i] = params.BeaconConfig().ZeroHash[:]
    82  	}
    83  	for i := 0; i < len(paddedLeaves); i++ {
    84  		paddedLeaves[i] = params.BeaconConfig().ZeroHash[:]
    85  	}
    86  
    87  	merkleTree := make([][]byte, len(parents)+len(leaves)+len(paddedLeaves))
    88  	copy(merkleTree, parents)
    89  	l := len(parents)
    90  	copy(merkleTree[l:], leaves)
    91  	l += len(paddedLeaves)
    92  	copy(merkleTree[l:], paddedLeaves)
    93  
    94  	for i := len(paddedLeaves) - 1; i > 0; i-- {
    95  		a := append(merkleTree[2*i], merkleTree[2*i+1]...)
    96  		b := hashutil.Hash(a)
    97  		merkleTree[i] = b[:]
    98  	}
    99  
   100  	return merkleTree
   101  }
   102  
   103  // ConcatGeneralizedIndices concats the generalized indices together.
   104  //
   105  // Spec pseudocode definition:
   106  //   def concat_generalized_indices(*indices: GeneralizedIndex) -> GeneralizedIndex:
   107  //    """
   108  //    Given generalized indices i1 for A -> B, i2 for B -> C .... i_n for Y -> Z, returns
   109  //    the generalized index for A -> Z.
   110  //    """
   111  //    o = GeneralizedIndex(1)
   112  //    for i in indices:
   113  //        o = GeneralizedIndex(o * get_power_of_two_floor(i) + (i - get_power_of_two_floor(i)))
   114  //    return o
   115  func ConcatGeneralizedIndices(indices []int) int {
   116  	index := 1
   117  	for _, i := range indices {
   118  		index = index*PrevPowerOf2(i) + (i - PrevPowerOf2(i))
   119  	}
   120  	return index
   121  }
   122  
   123  // GeneralizedIndexLength returns the generalized index length from a given index.
   124  //
   125  // Spec pseudocode definition:
   126  //   def get_generalized_index_length(index: GeneralizedIndex) -> int:
   127  //    """
   128  //    Return the length of a path represented by a generalized index.
   129  //    """
   130  //    return int(log2(index))
   131  func GeneralizedIndexLength(index int) int {
   132  	return int(math.Log2(float64(index)))
   133  }
   134  
   135  // GeneralizedIndexBit returns the given bit of a generalized index.
   136  //
   137  // Spec pseudocode definition:
   138  //   def get_generalized_index_bit(index: GeneralizedIndex, position: int) -> bool:
   139  //    """
   140  //    Return the given bit of a generalized index.
   141  //    """
   142  //    return (index & (1 << position)) > 0
   143  func GeneralizedIndexBit(index, pos uint64) bool {
   144  	return (index & (1 << pos)) > 0
   145  }
   146  
   147  // GeneralizedIndexSibling returns the sibling of a generalized index.
   148  //
   149  // Spec pseudocode definition:
   150  //   def generalized_index_sibling(index: GeneralizedIndex) -> GeneralizedIndex:
   151  //    return GeneralizedIndex(index ^ 1)
   152  func GeneralizedIndexSibling(index int) int {
   153  	return index ^ 1
   154  }
   155  
   156  // GeneralizedIndexChild returns the child of a generalized index.
   157  //
   158  // Spec pseudocode definition:
   159  //   def generalized_index_child(index: GeneralizedIndex, right_side: bool) -> GeneralizedIndex:
   160  //    return GeneralizedIndex(index * 2 + right_side)
   161  func GeneralizedIndexChild(index int, rightSide bool) int {
   162  	if rightSide {
   163  		return index*2 + 1
   164  	}
   165  	return index * 2
   166  }
   167  
   168  // GeneralizedIndexParent returns the parent of a generalized index.
   169  //
   170  // Spec pseudocode definition:
   171  //   def generalized_index_parent(index: GeneralizedIndex) -> GeneralizedIndex:
   172  //    return GeneralizedIndex(index // 2)
   173  func GeneralizedIndexParent(index int) int {
   174  	return index / 2
   175  }