feat: proof parser + query-wise verifier#12
Conversation
bobbinth
left a comment
There was a problem hiding this comment.
Thank you! And sorry for such a delay with the review.
This is not a full review yet - just a few suggestions about high-level changes to improve code clarity/organization. Feel free to disagree with any of these.
Unbatch PR
I'd rename BatchMerkleProof::unbatch() method into something like BatchMerkleProof::into_paths() and move this work into a separate PR. We should probably make this PR against the main Winterfell repo - I think it would be pretty useful to have this functionality there.
Verify query
I'd create a stand-alone function for verifying a single query (it seems like the current verify_generic_query still iterates over a set of positions). I'd also try to make it as as self-contained as possible - so that it is super clear what the function requires as inputs / produces as outputs. For example, I'd probably not have it take self and channel as arguments but instead would pass w/e is needed from these structs. I think the arguments we need are (but I may be missing something):
- layer commitments
- layer alphas
- position
- evaluation
- a Merkle path per layer
- options
I think it is OK to have these many parameters as we need this primarily for reference purposes rather than production code.
Also, it would be cool to add some kind of hash counter so that we can estimate how many invocations of a hash function required for verifying a given FRI proof.
FRI changes in Winterfell
I wonder if we should make a PR to update FRI implementation in Winterfell to allow the following:
- Folding factor of 2 (currently, 4 is the smallest).
- Go down to the smallest possible remainder (to simplify remainder testing).
Though, I guess these should be driven by our understanding of how much not having the above would complicate things inside Miden VM.
|
One more thought regarding verify query: instead of passing a Merkle path per layer, let's pass a struct which closely mimics the mtree_get instruction. That is, it exposes a function with roughly this interface: fn get_node(root: Digest, depth: usize, index: usize) -> DigestThe above function would return the value of the node from the tree with the specified root. The node would be located in the tree at the specified index and depth. If the tree with the specified root is not present in the struct, or the specified node is not present in the tree - the function should panic. To implement this struct, you can probably adapt the code form AdviceProvider and MerklePathSet structs. |
|
Thank you Bobbin! |
Here I am bit not sure about what you mean. More specifically:
|
|
@Al-Kindi-0 Thank you! I'll leave some comments in the other PRs. To answer the above questions:
|
2496f01 to
eea409c
Compare
This PR proposes a draft implementation of a FRI verifier which runs the query phase of the FRI protocol in a query-by-query fashion. To do this, this PR also includes a potential modification to the verifier part of the channel so that the proof generated by the prover, which looks at all the queries in certain layer in one go, can be parsed for the new verifier implementation in this PR.
The interface of both the
unbatchfunction as well as theverify_generic_queryfunction is, in my opinion, suboptimal. The reason being that, in order to parse the proof, theunbatchfunction requires the array of queried positions and this makes the design of the interfaces, based on the current one, a challenge.