General indices helpers (#3575)

* Implemented Power of 2 helpers

* Test for power of 2 helpers

* Gazelle

* Fmt

* Implemented MerkleTree

* Test for MerkleTree

* Fixed tests

* Implemented ConcatGeneralizedIndices and GeneralizedIndexLength

* Tests for the above

* Benchmarked copy, it's faster

* Implemented rest of the indices helpers

* Tests for indices helpers

* Delete
This commit is contained in:
terence tsao
2019-09-25 02:05:35 -07:00
committed by Nishant Das
parent 7c9ddfeb58
commit 6c892dc376
2 changed files with 209 additions and 23 deletions

View File

@@ -1,6 +1,8 @@
package trieutil
import (
"math"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -77,3 +79,77 @@ func MerkleTree(leaves [][]byte) [][]byte {
return merkleTree
}
// ConcatGeneralizedIndices concats the generalized indices together.
//
// Spec pseudocode definition:
// def concat_generalized_indices(*indices: GeneralizedIndex) -> GeneralizedIndex:
// """
// Given generalized indices i1 for A -> B, i2 for B -> C .... i_n for Y -> Z, returns
// the generalized index for A -> Z.
// """
// o = GeneralizedIndex(1)
// for i in indices:
// o = GeneralizedIndex(o * get_previous_power_of_two(i) + (i - get_previous_power_of_two(i)))
// return o
func ConcatGeneralizedIndices(indices []int) int {
index := 1
for _, i := range indices {
index = index*PrevPowerOf2(i) + (i - PrevPowerOf2(i))
}
return index
}
// GeneralizedIndexLength returns the generalized index length from a given index.
//
// Spec pseudocode definition:
// def get_generalized_index_length(index: GeneralizedIndex) -> int:
// """
// Return the length of a path represented by a generalized index.
// """
// return int(log2(index))
func GeneralizedIndexLength(index int) int {
return int(math.Log2(float64(index)))
}
// GeneralizedIndexBit returns the given bit of a generalized index.
//
// Spec pseudocode definition:
// def get_generalized_index_bit(index: GeneralizedIndex, position: int) -> bool:
// """
// Return the given bit of a generalized index.
// """
// return (index & (1 << position)) > 0
func GeneralizedIndexBit(index uint64, pos uint64) bool {
return (index & (1 << pos)) > 0
}
// GeneralizedIndexSibling returns the sibling of a generalized index.
//
// Spec pseudocode definition:
// def generalized_index_sibling(index: GeneralizedIndex) -> GeneralizedIndex:
// return GeneralizedIndex(index ^ 1)
func GeneralizedIndexSibling(index int) int {
return index ^ 1
}
// GeneralizedIndexChild returns the child of a generalized index.
//
// Spec pseudocode definition:
// def generalized_index_child(index: GeneralizedIndex, right_side: bool) -> GeneralizedIndex:
// return GeneralizedIndex(index * 2 + right_side)
func GeneralizedIndexChild(index int, rightSide bool) int {
if rightSide {
return index*2 + 1
}
return index * 2
}
// GeneralizedIndexParent returns the parent of a generalized index.
//
// Spec pseudocode definition:
// def generalized_index_parent(index: GeneralizedIndex) -> GeneralizedIndex:
// return GeneralizedIndex(index // 2)
func GeneralizedIndexParent(index int) int {
return index / 2
}

View File

@@ -7,40 +7,40 @@ import (
func TestNextPowerOf2(t *testing.T) {
tests := []struct {
input int
want int
input int
result int
}{
{input: 0, want: 0},
{input: 1, want: 1},
{input: 2, want: 2},
{input: 3, want: 4},
{input: 5, want: 8},
{input: 9, want: 16},
{input: 20, want: 32},
{input: 0, result: 0},
{input: 1, result: 1},
{input: 2, result: 2},
{input: 3, result: 4},
{input: 5, result: 8},
{input: 9, result: 16},
{input: 20, result: 32},
}
for _, tt := range tests {
if got := NextPowerOf2(tt.input); got != tt.want {
t.Errorf("NextPowerOf2() = %v, want %v", got, tt.want)
if got := NextPowerOf2(tt.input); got != tt.result {
t.Errorf("NextPowerOf2() = %d, result %d", got, tt.result)
}
}
}
func TestPrevPowerOf2(t *testing.T) {
tests := []struct {
input int
want int
input int
result int
}{
{input: 0, want: 0},
{input: 1, want: 1},
{input: 2, want: 2},
{input: 3, want: 2},
{input: 5, want: 4},
{input: 9, want: 8},
{input: 20, want: 16},
{input: 0, result: 0},
{input: 1, result: 1},
{input: 2, result: 2},
{input: 3, result: 2},
{input: 5, result: 4},
{input: 9, result: 8},
{input: 20, result: 16},
}
for _, tt := range tests {
if got := PrevPowerOf2(tt.input); got != tt.want {
t.Errorf("PrevPowerOf2() = %v, want %v", got, tt.want)
if got := PrevPowerOf2(tt.input); got != tt.result {
t.Errorf("PrevPowerOf2() = %d, result %d", got, tt.result)
}
}
}
@@ -56,7 +56,117 @@ func TestMerkleTreeLength(t *testing.T) {
}
for _, tt := range tests {
if got := MerkleTree(tt.leaves); len(got) != tt.length {
t.Errorf("len(MerkleTree()) = %v, want %v", got, tt.length)
t.Errorf("len(MerkleTree()) = %d, result %d", got, tt.length)
}
}
}
func TestConcatGeneralizedIndices(t *testing.T) {
tests := []struct {
indices []int
result int
}{
{[]int{1, 2}, 2},
{[]int{1, 3, 6}, 14},
{[]int{1, 2, 4, 8}, 64},
{[]int{1, 2, 5, 10}, 74},
}
for _, tt := range tests {
if got := ConcatGeneralizedIndices(tt.indices); got != tt.result {
t.Errorf("ConcatGeneralizedIndices() = %d, result %d", got, tt.result)
}
}
}
func TestGeneralizedIndexLength(t *testing.T) {
tests := []struct {
index int
result int
}{
{index: 20, result: 4},
{index: 200, result: 7},
{index: 1987, result: 10},
{index: 34989843, result: 25},
{index: 97282, result: 16},
}
for _, tt := range tests {
result := GeneralizedIndexLength(tt.index)
if tt.result != result {
t.Errorf("GeneralizedIndexLength() = %d, result %d", tt.result, result)
}
}
}
func TestGeneralizedIndexBit(t *testing.T) {
tests := []struct {
index uint64
pos uint64
result bool
}{
{index: 7, pos: 2, result: true},
{index: 7, pos: 3, result: false},
{index: 10, pos: 2, result: false},
{index: 10, pos: 3, result: true},
}
for _, tt := range tests {
result := GeneralizedIndexBit(tt.index, tt.pos)
if result != tt.result {
t.Errorf("GeneralizedIndexBit() = %v, result %v", tt.result, result)
}
}
}
func TestGeneralizedIndexChild(t *testing.T) {
tests := []struct {
index int
right bool
result int
}{
{index: 5, right: true, result: 11},
{index: 10, right: false, result: 20},
{index: 1000, right: true, result: 2001},
{index: 9999, right: false, result: 19998},
}
for _, tt := range tests {
result := GeneralizedIndexChild(tt.index, tt.right)
if result != tt.result {
t.Errorf("GeneralizedIndexChild() = %v, result %v", tt.result, result)
}
}
}
func TestGeneralizedIndexSibling(t *testing.T) {
tests := []struct {
index int
result int
}{
{index: 5, result: 4},
{index: 10, result: 11},
{index: 1000, result: 1001},
{index: 9999, result: 9998},
}
for _, tt := range tests {
result := GeneralizedIndexSibling(tt.index)
if result != tt.result {
t.Errorf("GeneralizedIndexSibling() = %v, result %v", tt.result, result)
}
}
}
func TestGeneralizedIndexParent(t *testing.T) {
tests := []struct {
index int
result int
}{
{index: 5, result: 2},
{index: 10, result: 5},
{index: 1000, result: 500},
{index: 9999, result: 4999},
}
for _, tt := range tests {
result := GeneralizedIndexParent(tt.index)
if result != tt.result {
t.Errorf("GeneralizedIndexParent() = %v, result %v", tt.result, result)
}
}
}