Skip to content

Commit b203d45

Browse files
committed
fuzz tests
1 parent 0de243d commit b203d45

3 files changed

Lines changed: 73 additions & 1 deletion

File tree

proof/proof.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func reverse(ids []compact.NodeID) {
223223
}
224224
}
225225

226-
// isSubTreeValid returns whether a subtree covers a valid range.
226+
// isSubtreeValid returns whether a subtree covers a valid range.
227227
// A subtree is valid if there exist a parent tree node to:
228228
// - all the subtree nodes
229229
// - no extra node to the left of the subtree

testonly/tree.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ func (t *Tree) HashAt(size uint64) []byte {
9494
return hash
9595
}
9696

97+
// SubtreeHashAt returns the root hash of the [start, end) subtree.
98+
// Requires 0 <= start <= end <= Size() otherwise panics.
99+
func (t *Tree) SubtreeHashAt(start, end uint64) []byte {
100+
if start > end || end > t.size {
101+
panic("invalid subtree range")
102+
}
103+
if start == end {
104+
return t.hasher.EmptyRoot()
105+
}
106+
hashes := t.getNodes(compact.RangeNodes(start, end, nil))
107+
108+
hash := hashes[len(hashes)-1]
109+
for i := len(hashes) - 2; i >= 0; i-- {
110+
hash = t.hasher.HashChildren(hashes[i], hash)
111+
}
112+
return hash
113+
}
114+
97115
// InclusionProof returns the inclusion proof for the given leaf index in the
98116
// tree of the given size. Requires 0 <= index < size <= Size(), otherwise may
99117
// panic.
@@ -105,6 +123,20 @@ func (t *Tree) InclusionProof(index, size uint64) ([][]byte, error) {
105123
return nodes.Rehash(t.getNodes(nodes.IDs), t.hasher.HashChildren)
106124
}
107125

126+
// SubtreeInclusionProof returns the inclusion proof for the given leaf index in the
127+
// [start, end) subtree.
128+
// It requires end <= Size(), and may panic otherwise.
129+
// It returns an error if:
130+
// - index is outside of [start, end)
131+
// - start is not a multiple of the smallest power of two greater than or equal to (end-start)
132+
func (t *Tree) SubtreeInclusionProof(index, start, end uint64) ([][]byte, error) {
133+
nodes, err := proof.SubtreeInclusion(index, start, end)
134+
if err != nil {
135+
return nil, err
136+
}
137+
return nodes.Rehash(t.getNodes(nodes.IDs), t.hasher.HashChildren)
138+
}
139+
108140
// ConsistencyProof returns the consistency proof between the two given tree
109141
// sizes. Requires 0 <= size1 <= size2 <= Size(), otherwise may panic.
110142
func (t *Tree) ConsistencyProof(size1, size2 uint64) ([][]byte, error) {

testonly/tree_fuzz_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package testonly
55
import (
66
"bytes"
77
"math"
8+
"math/bits"
89
"testing"
910

1011
"github.com/google/go-cmp/cmp"
@@ -74,6 +75,45 @@ func FuzzInclusionProofAndVerify(f *testing.F) {
7475
})
7576
}
7677

78+
// Compute and verify inclusion proofs
79+
func FuzzSubtreeInclusionProofAndVerify(f *testing.F) {
80+
for end := 0; end <= 8; end++ {
81+
for start := 0; start <= end; start++ {
82+
for index := start; index <= end; index++ {
83+
f.Add(uint64(index), uint64(start), uint64(end))
84+
}
85+
}
86+
}
87+
f.Fuzz(func(t *testing.T, index, start, end uint64) {
88+
if end >= math.MaxUint16 {
89+
return
90+
}
91+
t.Logf("index=%d, start=%d, end=%d", index, start, end)
92+
if start >= end {
93+
return
94+
}
95+
if index < start {
96+
return
97+
}
98+
if index >= end {
99+
return
100+
}
101+
if bc := uint64(1) << bits.Len64(end-start-1); start%bc != 0 {
102+
return
103+
}
104+
tree := newTree(genEntries(end))
105+
p, err := tree.SubtreeInclusionProof(index, start, end)
106+
t.Logf("proof=%v", p)
107+
if err != nil {
108+
t.Error(err)
109+
}
110+
err = proof.VerifySubtreeInclusion(tree.hasher, index, start, end, tree.LeafHash(index), p, tree.SubtreeHashAt(start, end))
111+
if err != nil {
112+
t.Error(err)
113+
}
114+
})
115+
}
116+
77117
func FuzzHashAtAgainstReferenceImplementation(f *testing.F) {
78118
for size := 0; size <= 8; size++ {
79119
for index := 0; index <= size; index++ {

0 commit comments

Comments
 (0)