Skip to content

Commit fcbb8f1

Browse files
committed
better isSubtreeValid
1 parent 4098e0c commit fcbb8f1

4 files changed

Lines changed: 19 additions & 20 deletions

File tree

proof/proof.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,12 @@ func Inclusion(index, size uint64) (Nodes, error) {
5959
// - start to be a multiple of the smallest power of two greater than or equal to
6060
// (end - start)
6161
func SubtreeInclusion(index, start, end uint64) (Nodes, error) {
62-
if start >= end {
63-
return Nodes{}, fmt.Errorf("start %d greater than or equal to end %d", start, end)
62+
if err := IsSubtreeValid(start, end); err != nil {
63+
return Nodes{}, fmt.Errorf("subtree invalid: %v", err)
6464
}
6565
if index < start || index >= end {
6666
return Nodes{}, fmt.Errorf("index %d out of bounds for subtree [%d, %d)", index, start, end)
6767
}
68-
if err := isSubtreeValid(start, end); err != nil {
69-
return Nodes{}, fmt.Errorf("subtree invalid: %v", err)
70-
}
7168

7269
// Shift the subtree to the left, such that it starts at 0.
7370
p := nodes(index-start, 0, end-start).skipFirst()
@@ -223,26 +220,33 @@ func reverse(ids []compact.NodeID) {
223220
}
224221
}
225222

226-
// isSubtreeValid returns whether a subtree covers a valid range.
223+
// IsSubtreeValid returns whether a subtree covers a valid range.
227224
// A subtree is valid if there exist a parent tree node to:
228225
// - all the subtree nodes
229226
// - no extra node to the left of the subtree
230227
// - potentially extra nodes to the right of the subtree
231-
func isSubtreeValid(start, end uint64) error {
232-
l := end - start
228+
func IsSubtreeValid(start, end uint64) error {
229+
if start >= end {
230+
return fmt.Errorf("start %d must be strictly less than end %d", start, end)
231+
}
233232
if start == 0 {
234233
return nil
235-
} else if l > uint64(1)<<63 {
236-
// special-case large subtree to avoid panic
234+
}
235+
236+
l := end - start
237+
238+
// special-case large subtree to avoid panic
239+
if l > uint64(1)<<63 {
237240
return fmt.Errorf("start %d must be 0 when subtree length %d > 1<<63. ", start, l)
238241
}
239-
if bc := bitCeil(l); start%bc != 0 {
242+
if bc := bitCeil(l); start&(bc-1) != 0 {
240243
return fmt.Errorf("start %d not a multiple of bit_ceil(end - start) = %d", start, bc)
241244
}
245+
242246
return nil
243247
}
244248

245-
// bitCeil returns the smallest power of 2 larger than n.
249+
// bitCeil returns the smallest power of 2 larger or equal than n.
246250
// MUST NOT be used with n larger than uint64(1)<<63.
247251
func bitCeil(n uint64) uint64 {
248252
if n <= 1 {

proof/proof_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ func TestInclusionSubtreeSucceedsUpToTreeSize(t *testing.T) {
425425
const maxSize = uint64(555)
426426
for sbe := uint64(1); sbe <= maxSize; sbe++ {
427427
for sbs := range sbe {
428-
if err := isSubtreeValid(sbs, sbe); err != nil {
428+
if err := IsSubtreeValid(sbs, sbe); err != nil {
429429
continue
430430
}
431431
for i := sbs; i < sbe; i++ {

proof/verify.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func VerifySubtreeInclusion(hasher merkle.LogHasher, index, start, end uint64, l
6565
if index < start || index >= end {
6666
return fmt.Errorf("index %d out of bounds for subtree [%d, %d)", index, start, end)
6767
}
68-
if err := isSubtreeValid(start, end); err != nil {
68+
if err := IsSubtreeValid(start, end); err != nil {
6969
return fmt.Errorf("subtree invalid: %v", err)
7070
}
7171
calcRoot, err := RootFromInclusionProof(hasher, index-start, end-start, leafHash, proof)

testonly/tree_fuzz_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package testonly
33
import (
44
"bytes"
55
"math"
6-
"math/bits"
76
"testing"
87

98
"github.com/google/go-cmp/cmp"
@@ -86,8 +85,7 @@ func FuzzSubtreeInclusionProofAndVerify(f *testing.F) {
8685
if end >= math.MaxUint16 {
8786
return
8887
}
89-
t.Logf("index=%d, start=%d, end=%d", index, start, end)
90-
if start >= end {
88+
if err := proof.IsSubtreeValid(start, end); err != nil {
9189
return
9290
}
9391
if index < start {
@@ -96,9 +94,6 @@ func FuzzSubtreeInclusionProofAndVerify(f *testing.F) {
9694
if index >= end {
9795
return
9896
}
99-
if bc := uint64(1) << bits.Len64(end-start-1); start%bc != 0 {
100-
return
101-
}
10297
tree := newTree(genEntries(end))
10398
p, err := tree.SubtreeInclusionProof(index, start, end)
10499
t.Logf("proof=%v", p)

0 commit comments

Comments
 (0)