-
Notifications
You must be signed in to change notification settings - Fork 13
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
bellpepper-emulated: Add missing final carry check and fix limb count calculation #49
Conversation
e520231
to
ce404b3
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.
Thank you for the investigation and fix!
To sanity check my understanding, in the pseudocode and in the pdf (caveat: I have not fully read it yet), should the least_significant_64_bits(e[i])
actually be something like least_significant_num_bits_per_limb_bits(e[i])
since the limbs are not necessarily 64 bits long? (I believe this is the case, since the pdf considers the limb_width = 64
case for simplicity, but I wanted to double check)
Also, I'm not sure where in the emulated
code we currently handle the if least_significant_64_bits(e[i]) != 0: exit with error
check, shouldn't there be some check on the least-significant-bits of diff_num
to follow the pseudocode correctly? Reading the pdf (though I did not read it all yet), it seems like this is always true if qn = d
, but that is precisely what this is aiming to check, so we need to perform this check. Am I misunderstanding something, e.g. is this check being made implicitly inside right_shift
, or it's not necessary to be specified as a constraint, or would this be part of the follow-up changes to emulated
and is unrelated to the fix in this PR?
Regarding the CI clippy failure, feel free to cherry-pick ff3e970 onto your branch (or run clippy --fix locally if you prefer). The clippy::useless_vec
got turned on by default in the latest rust stable release.
Yes, you are right. It should be
The check that the
In
Thanks for the clippy fix. I have added it to the PR. |
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.
In
right_shift
, we do the following [...]
Thanks for the explanation! I noticed that we were skipping the first start_digit
bits when doing the weighted sum, but I see now that the final comparison would indeed fail if any of those lower bits are set!
Thanks for the clippy fix. I have added it to the PR.
Sorry, I forgot to run cargo fmt
after the clippy fix, you'll also need to apply 997030c. Once CI is passing I can re-approve the PR if necessary
While replacing the 64 bits with |
@wwared Please re-approve this PR. I only added the |
- Removed remark about missing carry check that was fixed in argumentcomputer#49 - Typos in remarks fixed - Added clarifying phrases - Formatting in equation superscripts
- Removed remark about missing carry check that was fixed in argumentcomputer#49 - Typos in remarks fixed - Added clarifying phrases - Formatting in equation superscripts
I missed the final carry check in the limb-wise equality check code in
crates/emulated/src/field_ops.rs:assert_limbs_equality_slow
. Adding this check revealed another bug which was under-counting the number of new limbs incrates/emulated/src/field_element.rs:compact_limbs
.This PR fixed these bugs and updates the constraint counts (which have all increased).
I am marking this PR as draft as I could not calculate the updated counts in thecrates/bls12381/src/curves/pairing.rs
. My machine ran out of RAM. If someone can tell me the updated values, I can add them.EDIT: I got the updated number of constraints and variables from Github test failures.
Explanation
When two non-native field elements are equal, it is not necessary that their respective limbs will all be equal to each other. But they will be equal as big integers.
For example, suppose the limb width is 4 bits. The integer 100 can be written as$a = 6 \times 2^4 + 4$ and $b = 5 \times 2^4 +20$ . The limbs of $a$ are $a_0=4, a_1=6$ and the limbs of $b$ are $b_0 = 20, b_1 =5$ . There is no overflow in the limbs of $a$ while the limbs of $b$ have an overflow of 1 bit. The overflow allows the two different sets of limbs to represent the same integer. The difference of the limbs $a_0 - b_0 = -16$ . This means that $-1$ has to be carried and added to the difference $a_1 - b_1 = 1$ .
To prevent underflow, the carry is first calculated by adding an offset
max_value
. In the next limb, the shifted version ofmax_value
given bymax_value_shifted
is deducted.The pseudo-code for the limb-wise equality check is as follows:
I missed the
assert_is_equal
check in the last line. A more detailed explanation can be found in Section 5.5 of the document at https://github.com/avras/bellpepper-gadgets/blob/emulated-overflow-fix/crates/emulated/docs/overflow.pdf.I discovered the missing check while working out the overflow bounds. That requires some changes to
emulated
as well. But I wanted to restrict the fix in this PR to final carry check and correct limb count calculation.