Skip to content

Commit

Permalink
chore: rename gmerkle types to reduce stutter
Browse files Browse the repository at this point in the history
Now that we are starting to use them in the BLS work, gmerkle.MerkleTree
did not read as well as just gmerkle.Tree.
  • Loading branch information
mark-rushakoff committed Dec 19, 2024
1 parent 4eefb14 commit 0f9c02c
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 44 deletions.
6 changes: 5 additions & 1 deletion gcrypto/commonmessagesignatureproof.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ type CommonMessageSignatureProof interface {
// but not a proof scheme, and you need to make a complicated operation.
Derive() CommonMessageSignatureProof

// SignatureBitSet returns a bit set indicating which of the candidate keys
// SignatureBitSet returns the underlying bit set indicating which of the candidate keys
// have signatures included in this proof.
//
// The caller must not modify the bit set,
// and using the bit set after another call to a CommonMessageSignatureProof method
// risks causing another data race.
//
// In the case of a SignatureProof that involves aggregating signatures,
// the count of set bits may be greater than the number of signatures.
SignatureBitSet() *bitset.BitSet
Expand Down
4 changes: 2 additions & 2 deletions gmerkle/gmerkletest/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
)

// DumpStringIDTree is a shorthand for DumpTree when the tree has string IDs.
func DumpStringIDTree(t *gmerkle.MerkleTree[string]) string {
func DumpStringIDTree(t *gmerkle.Tree[string]) string {
return DumpTree(t, func(id string) string { return id })
}

// DumpTree returns a crude string showing the structure of the Merkle tree t.
// This output is only meant for debugging purposes, and it is not guaranteed to be stable.
func DumpTree[I comparable](t *gmerkle.MerkleTree[I], idFormatter func(I) string) string {
func DumpTree[I comparable](t *gmerkle.Tree[I], idFormatter func(I) string) string {
var buf bytes.Buffer
rootDepth := -1

Expand Down
36 changes: 18 additions & 18 deletions gmerkle/merkle.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
"github.com/bits-and-blooms/bitset"
)

// MerkleScheme specifies the details on producing a merkle tree from an ordered collection of leaves.
// Scheme specifies the details on producing a merkle tree from an ordered collection of leaves.
// Type parameter L is the leaf data, and I is the ID type of the nodes.
// The ID type will often be a byte slice representing a cryptographic hash,
// but in the case of public key aggregation it could be a public key.
type MerkleScheme[L any, I comparable] interface {
type Scheme[L any, I comparable] interface {
// How many children each branch must have
// (excepting the rightmost branch in a row, which will have at least 1 element
// but possibly less than BranchFactor).
Expand All @@ -36,7 +36,7 @@ type MerkleScheme[L any, I comparable] interface {
LeafID(idx int, leafData L) (I, error)
}

// MerkleTree is the primary Merkle tree used in Gordian.
// Tree is the primary Merkle tree used in Gordian.
// Compared to other possible implementations,
// features of this implementation include:
// - Rather than representing branches as "hashes", they are "IDs" of the type parameter I.
Expand All @@ -52,8 +52,8 @@ type MerkleScheme[L any, I comparable] interface {
// at indices 5-8.
// - After calculating the leaf IDs, the tree holds no reference to the leaf values.
// - While a branching factor of 2 is suggested,
// other sizes may be specified through the [MerkleScheme].
type MerkleTree[I comparable] struct {
// other sizes may be specified through the [Scheme].
type Tree[I comparable] struct {
// Branch factor.
m int

Expand All @@ -66,7 +66,7 @@ type MerkleTree[I comparable] struct {
}

// RootID returns the ID of the root branch of the tree.
func (t *MerkleTree[I]) RootID() I {
func (t *Tree[I]) RootID() I {
return t.branches[len(t.branches)-1][0].ID
}

Expand All @@ -76,7 +76,7 @@ func (t *MerkleTree[I]) RootID() I {
// If a match is found, leafIdxStart is the starting index into the original slice of leaf data,
// and n is how many elements are represented by the matching branch.
// If no match is found, Lookup returns -1, 0.
func (t *MerkleTree[I]) Lookup(id I) (leafIdxStart, n int) {
func (t *Tree[I]) Lookup(id I) (leafIdxStart, n int) {
branchSpan := 1
for ri, row := range t.branches {
if ri > 0 {
Expand All @@ -99,7 +99,7 @@ func (t *MerkleTree[I]) Lookup(id I) (leafIdxStart, n int) {
}

// BitSetToIDs returns branch IDs in t that map to leaves at the indices indicated in b.
// In many use cases of MerkleTree, the branch IDs are nothing more than arbitrary identifiers of collections of leaves.
// In many use cases of Tree, the branch IDs are nothing more than arbitrary identifiers of collections of leaves.
// For those, the simple bitset will be a sufficient and more condensed representation of the leaves' presence.
// For example, you may use bitset 0b1111 (the 4 least significant bits) to represent which leaves are used,
// and you may transmit [sig0, sig1, sig2, sig3] with the understanding that those map
Expand All @@ -116,10 +116,10 @@ func (t *MerkleTree[I]) Lookup(id I) (leafIdxStart, n int) {
// the signatures for the first 4 values.
// Depending on how expensive it is to re-calculate an aggregated public key,
// you may want to track the tree's IDs and their corresponding keys in some persistent storage.
func (t *MerkleTree[I]) BitSetToIDs(b *bitset.BitSet) []I {
func (t *Tree[I]) BitSetToIDs(b *bitset.BitSet) []I {
var out []I

// The bitset package expectsx uint values everywhere.
// The bitset package expects uint values everywhere.
// Convert these values to uint once up front, for readability when we need them later.
m := uint(t.m)
nLeaves := uint(t.nLeaves)
Expand Down Expand Up @@ -200,13 +200,13 @@ func (t *MerkleTree[I]) BitSetToIDs(b *bitset.BitSet) []I {
return out
}

// TreeVisitFunc is the callback passed to [MerkleTree.WalkFromRoot].
// TreeVisitFunc is the callback passed to [Tree.WalkFromRoot].
// If it returns stop=true, traversal will stop and the callback will not be called again.
type TreeVisitFunc[I comparable] func(id I, depth, rowIdx int, childBranchIDs []I, leafIndex, nLeaves int) (stop bool)

// WalkFromRootB starts at the root branch of the tree
// and traverses breadth-first, calling fn on each branch.
func (t *MerkleTree[I]) WalkFromRootB(fn TreeVisitFunc[I]) {
func (t *Tree[I]) WalkFromRootB(fn TreeVisitFunc[I]) {
rootRow := t.branches[len(t.branches)-1]
if len(rootRow) != 1 {
panic(fmt.Errorf("BUG: invalid tree; root row had %d branches", len(rootRow)))
Expand Down Expand Up @@ -265,7 +265,7 @@ func (t *MerkleTree[I]) WalkFromRootB(fn TreeVisitFunc[I]) {

// WalkFromRootD starts at the root branch of the tree
// and traverses depth-first, calling fn on each branch.
func (t *MerkleTree[I]) WalkFromRootD(fn TreeVisitFunc[I]) {
func (t *Tree[I]) WalkFromRootD(fn TreeVisitFunc[I]) {
rootRow := t.branches[len(t.branches)-1]
if len(rootRow) != 1 {
panic(fmt.Errorf("BUG: invalid tree; root row had %d branches", len(rootRow)))
Expand Down Expand Up @@ -293,7 +293,7 @@ func (t *MerkleTree[I]) WalkFromRootD(fn TreeVisitFunc[I]) {
}
}

func (t *MerkleTree[I]) walkD(depth, rowIdx int, fn TreeVisitFunc[I]) (stop bool) {
func (t *Tree[I]) walkD(depth, rowIdx int, fn TreeVisitFunc[I]) (stop bool) {
b := t.branches[depth][rowIdx]
if depth == 0 {
// Just emit the current branch.
Expand Down Expand Up @@ -340,7 +340,7 @@ func (t *MerkleTree[I]) walkD(depth, rowIdx int, fn TreeVisitFunc[I]) (stop bool

// childIndexRange returns the two integers to use for slicing the branches underneath
// the branch at parentDepth, parentRowIdx.
func (t *MerkleTree[I]) childIndexRange(parentDepth, parentRowIdx int) (start, end int) {
func (t *Tree[I]) childIndexRange(parentDepth, parentRowIdx int) (start, end int) {
if parentDepth == 0 {
panic(fmt.Errorf("BUG: childIndexRange should not be called with parentDepth=0"))
}
Expand All @@ -363,8 +363,8 @@ type branch[I comparable] struct {
Index int
}

// NewMerkleTree returns a new Merkle tree based on the given scheme and leaf data.
func NewMerkleTree[L any, I comparable](scheme MerkleScheme[L, I], leafData []L) (*MerkleTree[I], error) {
// NewTree returns a new Merkle tree based on the given scheme and leaf data.
func NewTree[L any, I comparable](scheme Scheme[L, I], leafData []L) (*Tree[I], error) {
m := int(scheme.BranchFactor()) // m as in "m-ary tree".
if m < 2 {
return nil, fmt.Errorf("branch factor must be at least 2 (got %d)", m)
Expand Down Expand Up @@ -447,7 +447,7 @@ func NewMerkleTree[L any, I comparable](scheme MerkleScheme[L, I], leafData []L)
}
}

return &MerkleTree[I]{
return &Tree[I]{
m: m,
nLeaves: len(leafData),
branches: rows,
Expand Down
46 changes: 23 additions & 23 deletions gmerkle/merkle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require"
)

// Very simple implementation of MerkleScheme.
// Very simple implementation of Scheme.
type sha256Scheme struct {
M uint8 // Branch factor.

Expand Down Expand Up @@ -56,7 +56,7 @@ func (s sha256Scheme) BranchID(depth, rowIdx int, childIDs [][sha256.Size]byte)
return out, nil
}

func TestMerkleTree_RootID(t *testing.T) {
func TestTree_RootID(t *testing.T) {
t.Run("complete first depth, binary tree", func(t *testing.T) {
leaves := []string{"This", "is", "a", "test."}

Expand Down Expand Up @@ -84,7 +84,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in) // sha256( sha256(sha256("This") + sha256("is")) + sha256(sha256("a") + sha256("test.")) )

scheme := sha256Scheme{M: 2}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand All @@ -109,7 +109,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in) // sha256( sha256(sha256("only") + sha256("three")) + sha256("leaves") )

scheme := sha256Scheme{M: 2}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand All @@ -130,7 +130,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in) // sha256(sha256("exactly") + sha256("three") + sha256("leaves"))

scheme := sha256Scheme{M: 3}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand All @@ -150,7 +150,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in) // sha256(sha256("just") + sha256("two"))

scheme := sha256Scheme{M: 3}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand Down Expand Up @@ -190,7 +190,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in) // sha256( sha256(1-3) + sha256(4-6) + sha256(7-9) )

scheme := sha256Scheme{M: 3}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand Down Expand Up @@ -220,7 +220,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in)

scheme := sha256Scheme{M: 3, PadRightmostBranches: true}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand Down Expand Up @@ -249,7 +249,7 @@ func TestMerkleTree_RootID(t *testing.T) {
root := sha256.Sum256(in)

scheme := sha256Scheme{M: 2, HashPosition: true}
tree, err := gmerkle.NewMerkleTree[string, [sha256.Size]byte](scheme, leaves)
tree, err := gmerkle.NewTree(scheme, leaves)
require.NoError(t, err)

require.Equal(t, root, tree.RootID())
Expand All @@ -271,11 +271,11 @@ func (stringConcatScheme) BranchID(_, _ int, childIDs []string) (string, error)
return childIDs[0] + childIDs[1], nil
}

func TestMerkleTree_Lookup(t *testing.T) {
func TestTree_Lookup(t *testing.T) {
t.Run("complete first row", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4", "5", "6", "7"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

for _, tc := range []struct {
Expand Down Expand Up @@ -319,7 +319,7 @@ func TestMerkleTree_Lookup(t *testing.T) {
t.Run("incomplete first row", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4", "5", "6"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

for _, tc := range []struct {
Expand Down Expand Up @@ -381,11 +381,11 @@ func (v *visitor) Visit(id string, depth, rowIdx int, childBranchIDs []string, l
return false
}

func TestMerkleTree_WalkFromRootB(t *testing.T) {
func TestTree_WalkFromRootB(t *testing.T) {
t.Run("full, balanced, binary tree", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4", "5", "6", "7"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand Down Expand Up @@ -471,7 +471,7 @@ func TestMerkleTree_WalkFromRootB(t *testing.T) {
t.Run("tree with orphan", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand Down Expand Up @@ -542,7 +542,7 @@ func TestMerkleTree_WalkFromRootB(t *testing.T) {
t.Run("single element tree", func(t *testing.T) {
leaves := []string{"alone"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand All @@ -561,11 +561,11 @@ func TestMerkleTree_WalkFromRootB(t *testing.T) {
})
}

func TestMerkleTree_WalkFromRootD(t *testing.T) {
func TestTree_WalkFromRootD(t *testing.T) {
t.Run("full, balanced, binary tree", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4", "5", "6", "7"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand Down Expand Up @@ -712,7 +712,7 @@ func TestMerkleTree_WalkFromRootD(t *testing.T) {
t.Run("tree with orphan", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand Down Expand Up @@ -805,7 +805,7 @@ func TestMerkleTree_WalkFromRootD(t *testing.T) {
t.Run("single element tree", func(t *testing.T) {
leaves := []string{"alone"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

var v visitor
Expand All @@ -824,11 +824,11 @@ func TestMerkleTree_WalkFromRootD(t *testing.T) {
})
}

func TestMerkleTree_BitSetToIDs(t *testing.T) {
func TestTree_BitSetToIDs(t *testing.T) {
t.Run("balanced tree", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4", "5", "6", "7"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

for _, tc := range []struct {
Expand Down Expand Up @@ -873,7 +873,7 @@ func TestMerkleTree_BitSetToIDs(t *testing.T) {
t.Run("unbalanced tree", func(t *testing.T) {
leaves := []string{"0", "1", "2", "3", "4"}

tree, err := gmerkle.NewMerkleTree[string, string](stringConcatScheme{}, leaves)
tree, err := gmerkle.NewTree(stringConcatScheme{}, leaves)
require.NoError(t, err)

for _, tc := range []struct {
Expand Down

0 comments on commit 0f9c02c

Please sign in to comment.