-
Notifications
You must be signed in to change notification settings - Fork 0
fuzz tests #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fuzz tests #4
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -82,10 +82,19 @@ func (t *Tree) Hash() []byte { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // HashAt returns the root hash at the given size. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Requires 0 <= size <= Size(), otherwise panics. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *Tree) HashAt(size uint64) []byte { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if size == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.SubtreeHashAt(0, size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SubtreeHashAt returns the root hash of the [start, end) subtree. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Requires 0 <= start <= end <= Size() otherwise panics. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *Tree) SubtreeHashAt(start, end uint64) []byte { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if start > end || end > t.size { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| panic("invalid subtree range") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if start == end { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.hasher.EmptyRoot() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hashes := t.getNodes(compact.RangeNodes(0, size, nil)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hashes := t.getNodes(compact.RangeNodes(start, end, nil)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hash := hashes[len(hashes)-1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i := len(hashes) - 2; i >= 0; i-- { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -105,6 +114,18 @@ func (t *Tree) InclusionProof(index, size uint64) ([][]byte, error) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nodes.Rehash(t.getNodes(nodes.IDs), t.hasher.HashChildren) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SubtreeInclusionProof returns the inclusion proof for the given leaf index in the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // [start, end) subtree. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // It requires end <= Size(), and may panic otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // May return and error if the subtree boundaries or the index are not valid. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *Tree) SubtreeInclusionProof(index, start, end uint64) ([][]byte, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nodes, err := proof.SubtreeInclusion(index, start, end) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nodes.Rehash(t.getNodes(nodes.IDs), t.hasher.HashChildren) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+117
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The documentation comment states that the function panics if
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ConsistencyProof returns the consistency proof between the two given tree | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // sizes. Requires 0 <= size1 <= size2 <= Size(), otherwise may panic. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *Tree) ConsistencyProof(size1, size2 uint64) ([][]byte, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,7 @@ package testonly | |||||||||||||||
| import ( | ||||||||||||||||
| "bytes" | ||||||||||||||||
| "math" | ||||||||||||||||
| "math/bits" | ||||||||||||||||
| "testing" | ||||||||||||||||
|
|
||||||||||||||||
| "github.com/google/go-cmp/cmp" | ||||||||||||||||
|
|
@@ -74,6 +75,45 @@ func FuzzInclusionProofAndVerify(f *testing.F) { | |||||||||||||||
| }) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Compute and verify inclusion proofs | ||||||||||||||||
| func FuzzSubtreeInclusionProofAndVerify(f *testing.F) { | ||||||||||||||||
| for end := 0; end <= 8; end++ { | ||||||||||||||||
| for start := 0; start <= end; start++ { | ||||||||||||||||
| for index := start; index <= end; index++ { | ||||||||||||||||
| f.Add(uint64(index), uint64(start), uint64(end)) | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| f.Fuzz(func(t *testing.T, index, start, end uint64) { | ||||||||||||||||
| if end >= math.MaxUint16 { | ||||||||||||||||
| return | ||||||||||||||||
| } | ||||||||||||||||
| t.Logf("index=%d, start=%d, end=%d", index, start, end) | ||||||||||||||||
| if start >= end { | ||||||||||||||||
| return | ||||||||||||||||
| } | ||||||||||||||||
| if index < start { | ||||||||||||||||
| return | ||||||||||||||||
| } | ||||||||||||||||
| if index >= end { | ||||||||||||||||
| return | ||||||||||||||||
| } | ||||||||||||||||
| if bc := uint64(1) << bits.Len64(end-start-1); start%bc != 0 { | ||||||||||||||||
| return | ||||||||||||||||
| } | ||||||||||||||||
| tree := newTree(genEntries(end)) | ||||||||||||||||
| p, err := tree.SubtreeInclusionProof(index, start, end) | ||||||||||||||||
| t.Logf("proof=%v", p) | ||||||||||||||||
| if err != nil { | ||||||||||||||||
| t.Error(err) | ||||||||||||||||
| } | ||||||||||||||||
|
Comment on lines
+107
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Suggested change
|
||||||||||||||||
| err = proof.VerifySubtreeInclusion(tree.hasher, index, start, end, tree.LeafHash(index), p, tree.SubtreeHashAt(start, end)) | ||||||||||||||||
| if err != nil { | ||||||||||||||||
| t.Error(err) | ||||||||||||||||
| } | ||||||||||||||||
| }) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| func FuzzHashAtAgainstReferenceImplementation(f *testing.F) { | ||||||||||||||||
| for size := 0; size <= 8; size++ { | ||||||||||||||||
| for index := 0; index <= size; index++ { | ||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
SubtreeHashAtmethod does not validate whether the[start, end)range represents a valid subtree (i.e., whetherstartis aligned to a multiple of the smallest power of two greater than or equal to the subtree length). If an invalid range is provided, the method will silently compute and return an incorrect/garbage hash by combining the compact range roots, which can lead to hard-to-debug test failures. Adding a validation check to panic on invalid subtree ranges ensures correctness.