44package firewood
55
66import (
7+ "bytes"
78 "context"
89 "errors"
910 "sync"
@@ -39,39 +40,30 @@ func (db *syncDB) GetMerkleRoot(context.Context) (ids.ID, error) {
3940 return ids .ID (root ), nil
4041}
4142
42- // TODO: implement
43- func (db * syncDB ) CommitChangeProof (_ context.Context , end maybe.Maybe [[]byte ], proof * ChangeProof ) (nextKey maybe.Maybe [[]byte ], err error ) {
44- // Set up cleanup.
45- var nextKeyRange * ffi.NextKeyRange
46- defer func () {
47- // If we got a nextKeyRange, free it too.
48- if nextKeyRange != nil {
49- err = errors .Join (err , nextKeyRange .Free ())
50- }
51- }()
52-
53- // Verify and commit the proof in a single step (TODO: separate these steps).
54- // CommitRangeProof will verify the proof as part of committing it.
55- db .lock .Lock ()
56- defer db .lock .Unlock ()
57- newRoot , err := db .fw .VerifyAndCommitChangeProof (proof .proof , ffi .Hash (proof .startRoot ), ffi .Hash (proof .endRoot ), proof .startKey , end , uint32 (proof .maxLength ))
43+ // GetRangeProof returns a range proof for x/sync between [start, end].
44+ func (db * syncDB ) GetRangeProofAtRoot (_ context.Context , rootID ids.ID , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], maxLength int ) (* RangeProof , error ) {
45+ proof , err := db .fw .RangeProof (ffi .Hash (rootID ), start , end , uint32 (maxLength ))
5846 if err != nil {
59- return maybe . Nothing [[] byte ]() , err
47+ return nil , err
6048 }
6149
62- // TODO: This case should be handled by `FindNextKey`.
63- if ids .ID (newRoot ) == proof .endRoot {
64- return maybe .Nothing [[]byte ](), nil
50+ return newRangeProof (proof ), nil
51+ }
52+
53+ // VerifyRangeProof ensures the range proof matches the expected parameters.
54+ func (db * syncDB ) VerifyRangeProof (_ context.Context , proof * RangeProof , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], expectedEndRootID ids.ID , maxLength int ) error {
55+ if proof .ffi == nil {
56+ return errNilProof
6557 }
6658
67- return proof .FindNextKey ()
59+ proof .root = expectedEndRootID
60+ proof .maxLength = maxLength
61+
62+ return proof .ffi .Verify (ffi .Hash (expectedEndRootID ), start , end , uint32 (maxLength ))
6863}
6964
7065// Commit the range proof to the database.
71- // TODO: This should only commit the range proof, not verify it.
72- // This will be resolved once the Firewood supports that.
73- // This is the last call to the proof, so it and any resources should be freed.
74- func (db * syncDB ) CommitRangeProof (_ context.Context , start , end maybe.Maybe [[]byte ], proof * RangeProof ) (nextKey maybe.Maybe [[]byte ], err error ) {
66+ func (db * syncDB ) CommitRangeProof (_ context.Context , start , end maybe.Maybe [[]byte ], proof * RangeProof ) (maybe.Maybe [[]byte ], error ) {
7567 // Verify and commit the proof in a single step (TODO: separate these steps).
7668 // CommitRangeProof will verify the proof as part of committing it.
7769 db .lock .Lock ()
@@ -86,69 +78,44 @@ func (db *syncDB) CommitRangeProof(_ context.Context, start, end maybe.Maybe[[]b
8678 return maybe .Nothing [[]byte ](), nil
8779 }
8880
89- return proof .FindNextKey ()
90- }
91-
92- // TODO: implement
93- func (db * syncDB ) GetChangeProof (_ context.Context , startRootID ids.ID , endRootID ids.ID , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], maxLength int ) (* ChangeProof , error ) {
94- proof , err := db .fw .ChangeProof (ffi .Hash (startRootID ), ffi .Hash (endRootID ), start , end , uint32 (maxLength ))
95- if err != nil {
96- return nil , err
81+ // We can now get the FindNextKey iterator.
82+ nextKeyRange , err := proof .ffi .FindNextKey ()
83+ if err != nil || nextKeyRange == nil {
84+ // Indicates the range is complete.
85+ return maybe .Nothing [[]byte ](), err
9786 }
9887
99- return newChangeProof (proof ), nil
100- }
88+ byteSlice := nextKeyRange .StartKey ()
89+ newSlice := make ([]byte , len (byteSlice ))
90+ copy (newSlice , byteSlice )
10191
102- // Get the range proof between [start, end].
103- // The returned proof must be freed when no longer needed.
104- // Since this method is only called prior to marshalling the proof for sending over the
105- // network, the proof will be freed when marshalled.
106- func (db * syncDB ) GetRangeProofAtRoot (_ context.Context , rootID ids.ID , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], maxLength int ) (* RangeProof , error ) {
107- proof , err := db .fw .RangeProof (ffi .Hash (rootID ), start , end , uint32 (maxLength ))
108- if err != nil {
109- return nil , err
92+ // Done using nextKeyRange
93+ if err := nextKeyRange .Free (); err != nil {
94+ return maybe .Nothing [[]byte ](), err
11095 }
11196
112- return newRangeProof (proof ), nil
113- }
114-
115- // TODO: implement
116- // Right now, we verify the proof as part of committing it, making this function a no-op.
117- // We must only pass the necessary data to CommitChangeProof so it can verify the proof.
118- //
119- //nolint:revive
120- func (db * syncDB ) VerifyChangeProof (_ context.Context , proof * ChangeProof , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], expectedEndRootID ids.ID , maxLength int ) error {
121- if proof .proof == nil {
122- return errNilProof
97+ if start .HasValue () && bytes .Equal (newSlice , start .Value ()) {
98+ // There is no next key.
99+ return maybe .Nothing [[]byte ](), nil
123100 }
124101
125- // TODO: once firewood can verify separately from committing, do that here.
126- // For now, pass any necessary data to be done in CommitChangeProof.
127- // Namely, the start root, end root, and max length.
128- proof .startRoot = expectedEndRootID
129- proof .endRoot = expectedEndRootID
130- proof .maxLength = maxLength
131- return nil
102+ return maybe .Some (newSlice ), nil
132103}
133104
134- // TODO: implement
135- // Right now, we verify the proof as part of committing it, making this function a no-op.
136- // We must only pass the necessary data to CommitRangeProof so it can verify the proof.
137- func (db * syncDB ) VerifyRangeProof (_ context.Context , proof * RangeProof , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], expectedEndRootID ids.ID , maxLength int ) error {
138- if proof .ffi == nil {
139- return errNilProof
140- }
105+ func (db * syncDB ) GetChangeProof (_ context.Context , startRootID ids.ID , endRootID ids.ID , start maybe.Maybe [[]byte ], end maybe.Maybe [[]byte ], maxLength int ) (* ChangeProof , error ) {
106+ return nil , errors .New ("change proofs are not implemented" )
107+ }
141108
142- proof .root = expectedEndRootID
143- proof .maxLength = maxLength
109+ func (db * syncDB ) VerifyChangeProof (context.Context , * ChangeProof , maybe.Maybe [[]byte ], maybe.Maybe [[]byte ], ids.ID , int ) error {
110+ return errors .New ("change proofs are not implemented" )
111+ }
144112
145- return proof .ffi .Verify (ffi .Hash (expectedEndRootID ), start , end , uint32 (maxLength ))
113+ func (db * syncDB ) CommitChangeProof (context.Context , maybe.Maybe [[]byte ], * ChangeProof ) (maybe.Maybe [[]byte ], error ) {
114+ return maybe .Nothing [[]byte ](), errors .New ("change proofs are not implemented" )
146115}
147116
148- // TODO: implement
149- // No error is returned to ensure some tests pass.
150- //
151- //nolint:revive
117+ // Clear the database.
118+ // TODO: implement this method. It is left nil to allow empty DBs to be used in tests.
152119func (db * syncDB ) Clear () error {
153120 return nil
154121}
0 commit comments