Skip to content

Commit b21e9b5

Browse files
Dan Lainedboehm-avalabshexfusion
authored
merkledb -- verify range proof in fuzz test; fix bound error (#1789)
Co-authored-by: dboehm-avalabs <david.boehm@avalabs.org> Co-authored-by: Sam Batschelet <sam.batschelet@avalabs.org>
1 parent e70a17d commit b21e9b5

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

x/merkledb/proof.go

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,24 @@ func (proof *RangeProof) Verify(
302302
return err
303303
}
304304

305-
largestPath := maybe.Bind(end, newPath)
305+
// [proof] allegedly provides and proves all key-value
306+
// pairs in [smallestProvenPath, largestProvenPath].
307+
// If [smallestProvenPath] is Nothing, [proof] should
308+
// provide and prove all keys < [largestProvenPath].
309+
// If [largestProvenPath] is Nothing, [proof] should
310+
// provide and prove all keys > [smallestProvenPath].
311+
// If both are Nothing, [proof] should prove the entire trie.
312+
smallestProvenPath := maybe.Nothing[path]()
313+
if start != nil {
314+
smallestProvenPath = maybe.Some(newPath(start))
315+
}
316+
317+
largestProvenPath := maybe.Bind(end, newPath)
306318
if len(proof.KeyValues) > 0 {
307319
// If [proof] has key-value pairs, we should insert children
308-
// greater than [largestKey] to ancestors of the node containing
309-
// [largestKey] so that we get the expected root ID.
310-
largestPath = maybe.Some(newPath(proof.KeyValues[len(proof.KeyValues)-1].Key))
320+
// greater than [largestProvenPath] to ancestors of the node containing
321+
// [largestProvenPath] so that we get the expected root ID.
322+
largestProvenPath = maybe.Some(newPath(proof.KeyValues[len(proof.KeyValues)-1].Key))
311323
}
312324

313325
// The key-value pairs (allegedly) proven by [proof].
@@ -316,23 +328,31 @@ func (proof *RangeProof) Verify(
316328
keyValues[newPath(keyValue.Key)] = keyValue.Value
317329
}
318330

319-
smallestPath := newPath(start)
320-
321331
// Ensure that the start proof is valid and contains values that
322332
// match the key/values that were sent.
323-
if err := verifyProofPath(proof.StartProof, smallestPath); err != nil {
333+
if err := verifyProofPath(proof.StartProof, smallestProvenPath.Value()); err != nil {
324334
return err
325335
}
326-
if err := verifyAllRangeProofKeyValuesPresent(proof.StartProof, smallestPath, largestPath, keyValues); err != nil {
336+
if err := verifyAllRangeProofKeyValuesPresent(
337+
proof.StartProof,
338+
smallestProvenPath.Value(),
339+
largestProvenPath,
340+
keyValues,
341+
); err != nil {
327342
return err
328343
}
329344

330345
// Ensure that the end proof is valid and contains values that
331346
// match the key/values that were sent.
332-
if err := verifyProofPath(proof.EndProof, largestPath.Value()); err != nil {
347+
if err := verifyProofPath(proof.EndProof, largestProvenPath.Value()); err != nil {
333348
return err
334349
}
335-
if err := verifyAllRangeProofKeyValuesPresent(proof.EndProof, smallestPath, largestPath, keyValues); err != nil {
350+
if err := verifyAllRangeProofKeyValuesPresent(
351+
proof.EndProof,
352+
smallestProvenPath.Value(),
353+
largestProvenPath,
354+
keyValues,
355+
); err != nil {
336356
return err
337357
}
338358

@@ -350,24 +370,24 @@ func (proof *RangeProof) Verify(
350370
}
351371

352372
// For all the nodes along the edges of the proof, insert children
353-
// < [smallestPath] and > [largestPath]
373+
// < [smallestProvenPath] and > [largestProvenPath]
354374
// into the trie so that we get the expected root ID (if this proof is valid).
355-
// By inserting all children < [smallestPath], we prove that there are no keys
356-
// > [largestPath] but less than the first key given.
375+
// By inserting all children < [smallestProvenPath], we prove that there are no keys
376+
// > [smallestProvenPath] but less than the first key given.
357377
// That is, the peer who gave us this proof is not omitting nodes.
358378
if err := addPathInfo(
359379
view,
360380
proof.StartProof,
361-
maybe.Some(smallestPath),
362-
largestPath,
381+
smallestProvenPath,
382+
largestProvenPath,
363383
); err != nil {
364384
return err
365385
}
366386
if err := addPathInfo(
367387
view,
368388
proof.EndProof,
369-
maybe.Some(smallestPath),
370-
largestPath,
389+
smallestProvenPath,
390+
largestProvenPath,
371391
); err != nil {
372392
return err
373393
}

x/merkledb/proof_test.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,33 +1691,44 @@ func FuzzRangeProofInvariants(f *testing.F) {
16911691

16921692
f.Fuzz(func(
16931693
t *testing.T,
1694-
start []byte,
1694+
startBytes []byte,
16951695
endBytes []byte,
16961696
maxProofLen uint,
16971697
) {
16981698
require := require.New(t)
16991699

17001700
// Make sure proof bounds are valid
1701-
if len(endBytes) != 0 && bytes.Compare(start, endBytes) > 0 {
1701+
if len(endBytes) != 0 && bytes.Compare(startBytes, endBytes) > 0 {
17021702
return
17031703
}
1704-
end := maybe.Nothing[[]byte]()
1705-
if len(endBytes) > 0 {
1706-
end = maybe.Some(endBytes)
1707-
}
17081704
// Make sure proof length is valid
17091705
if maxProofLen == 0 {
17101706
return
17111707
}
17121708

1709+
end := maybe.Nothing[[]byte]()
1710+
if len(endBytes) != 0 {
1711+
end = maybe.Some(endBytes)
1712+
}
1713+
17131714
rangeProof, err := db.GetRangeProof(
17141715
context.Background(),
1715-
start,
1716+
startBytes,
17161717
end,
17171718
int(maxProofLen),
17181719
)
17191720
require.NoError(err)
17201721

1722+
rootID, err := db.GetMerkleRoot(context.Background())
1723+
require.NoError(err)
1724+
1725+
require.NoError(rangeProof.Verify(
1726+
context.Background(),
1727+
startBytes,
1728+
end,
1729+
rootID,
1730+
))
1731+
17211732
// Make sure the start proof doesn't contain any nodes
17221733
// that are in the end proof.
17231734
endProofKeys := set.Set[path]{}

0 commit comments

Comments
 (0)