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 }