-
Notifications
You must be signed in to change notification settings - Fork 284
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
feat: ZeroMorph #2664
feat: ZeroMorph #2664
Conversation
3d2c140
to
d7d5c03
Compare
e203c89
to
c91a95a
Compare
c5c6ad9
to
94afb95
Compare
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.
Very nice work! Thank you for the clear explanations in the code and HackMD. There are some things unclear to me and some suggestions.
barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.hpp
Outdated
Show resolved
Hide resolved
barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.hpp
Outdated
Show resolved
Hide resolved
barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.hpp
Outdated
Show resolved
Hide resolved
// Compute the q_k in reverse order, i.e. q_{n-1}, ..., q_0 | ||
for (size_t k = 0; k < log_N; ++k) { | ||
// Define partial evaluation point u' = (u_{n-k-1}, ..., u_{n-1}) | ||
auto partial_size = static_cast<std::ptrdiff_t>(k + 1); |
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.
I'm slightly confused, mentioned it above as well cus if it's in accordance with the paper and hackmd u'=(u_k,...,u_n-1) and then the size of the size of this should be n - k I think?
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.
fixed, thanks
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.
ah ok, now i understand why the partial size is k+1 because you allocate the size of the vector as n-k-1. hm, maybe partial_size should be called something else because i interpreted it as u_partial
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.
maybe evaluation_point_size
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.
yeah it's slightly confusing, I wasn't totally happy with this code. To be clear though, partial_size
is the size of u_partial
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.
BTW, this algorithm for computing q_k
is the one that will soon be replaced by Tohru with the more efficient algorithm detailed in the paper. So this code might go away entirely soon
ASSERT(size_ >= static_cast<size_t>(1 << m)); | ||
size_t n = numeric::get_msb(size_); | ||
|
||
// Partial evaluation is done in m rounds l = 0,...,m-1. At the end of round l, the polynomial has been partially |
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.
Can you give an intuition on this approach, it took me a bit to understand and decipher code
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.
Yeah took me a while to figure out how to do this myself. For whatever reason the comments on methods in this class are in the header. I left a note about intuition there - maybe that's what you are looking for?
* @brief Compute partially evaluated zeromorph identity polynomial Z_x | ||
* @details Compute Z_x, where | ||
* | ||
* Z_x = x * \sum_{i=0}^{m-1} f_i + \sum_{i=0}^{l-1} g_i - v * x * \Phi_n(x) |
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.
did you miss the alphas here or am I misunderstanding something?
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.
oh, they're implicitly multiplied before f_batched and g_batched provided as inputs
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.
Yeah you're right that the alphas were missing from the original comment then it wasnt updated when I changed the input to be the batched forms. I still havent decided whether it makes sense to the batching inside the funciton or outside. I'll fix the comment for now and this will get resolved later
f_polynomial += g_batched.shifted(); | ||
|
||
// The batched evaluation should match the evaluation of the batched polynomial | ||
// ASSERT_EQ(v_evaluation, f_polynomial.evaluate_mle(u_challenge)); |
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.
why is this commented out?
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.
This was just a debugging sanity check, removed
// Compute scalar y^k * x^{N - deg_k - 1} | ||
auto scalar = y_challenge.pow(k); | ||
scalar *= x_challenge.pow(N - deg_k - 1); | ||
scalar *= Fr(-1); |
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.
is it more efficient to multiply by Fr(1) than have the subtraction on line 285?
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 subtraction operator is actually not defined in this case, not entirely sure why. Possibly because these are affine points and we generally want to do operations in projective form? In any case, this will be changed in the follow on to be computed as a batch mul (since that's what's natural for the recursive computation and that's the one we care about)
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.
Oh right, I forgot to think about affine and projective while reviewing the PR wops. Can you add a TODO + issue for adding batch mul and generally converting point operations to projective form?
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.
This will all be handled in the immediate follow on but it's really not all that important anyway since the native verifier is basically nothing more than a debugging tool
for (auto& commitment : f_commitments) { | ||
auto scalar = x_challenge * alpha_pow; | ||
result = result + (commitment * scalar); | ||
alpha_pow *= alpha; |
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.
here, in contrast with the prover, you multiply by alpha inside the function but I think you forgot the alphas in the equation that is part of documentation
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.
Yes, you're right, thanks. Comment fixed
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.
And again, I'll probably make the Prover/Verifier consistent in this sense, I just haven't figured out which way to go
94afb95
to
26d8a0d
Compare
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.
see my last comment, and other than that I am happy for this to get merged, again great work :)
// Compute the q_k in reverse order, i.e. q_{n-1}, ..., q_0 | ||
for (size_t k = 0; k < log_N; ++k) { | ||
// Define partial evaluation point u' = (u_{n-k-1}, ..., u_{n-1}) | ||
auto partial_size = static_cast<std::ptrdiff_t>(k + 1); |
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.
maybe evaluation_point_size
This looks great! but the doc linked in the comment and PR (ref) isn't public 😢 |
Working to make it public - will keep you posted! |
@huitseeker Should be public now |
Adds ZeroMorph functionality (without zk) required to prove and verify batched multilinear evaluation claims, including efficient handling of shifts. For now, the protocol is fully laid out in a test. Incorporation into honk will be done in a separate PR.
The best resource for understanding this PR is this companion doc. The full batched protocol description therein matches the implementation.
Note: The goal of this first pass was to make the implementations as clear as possible. There are many simple optimizations that could be introduced to make things more efficient.
Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.