-
Notifications
You must be signed in to change notification settings - Fork 158
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
Fix bitwise rotate #109
Fix bitwise rotate #109
Conversation
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.
Good fix, I should have caught this the first time.
The main diff:
let l_witness = Witness(F::from_u128(val_l));
let r_witness = Witness(F::from_u128(val_r));
let val_witness = self.mul_add(ctx, l_witness, Constant(self.pow_of_two()[bit]), r_witness);
ctx.constrain_equal(&a, &val_witness);
let val_l = val >> bit;
let val_r = val - (val_l << bit);
let l_witness = ctx.load_witness(F::from_u128(val_l));
let r_witness = ctx.load_witness(F::from_u128(val_r));
let val_witness = self.gate.mul_add(ctx, l_witness, Constant(self.gate.pow_of_two()[bit]), r_witness);
self.range_check(ctx, l_witness, num_bits - bit);
self.range_check(ctx, r_witness, bit);
ctx.constrain_equal(&a, &val_witness);
Whenever a decomposition is done, there must be range checks to ensure overflow protection.
Please add a negative test (can use MockProver), where you prank l_witness = 0, r_witness = a
. Unfortunately I think you either have to just prank by the exact offset in ctx
or copy paste the function code over... Be aware of copy constraints when pranking, so it's actually checking the right thing. A good test is that the negative test will pass without the range checks.
halo2-base/src/gates/range.rs
Outdated
let val = a.value().get_lower_128(); | ||
let val_l = val >> bit; | ||
let val_r = val - (val_l << bit); | ||
let l_witness = ctx.load_witness(F::from_u128(val_l)); |
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.
A bit low level, but an optimization is to still use Witness(F::from_u128(val_l))
and then fetch l_witness = ctx.get(-3), r_witness = ctx.get(-4)
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.
Going to merge this for expediency. A negative test would still be nice in the future.
The existing implementation of
const_right_rotate_unsafe_internal
is under-constraints.r_witness
should havebit
bits but it's also valid if it equals toa
.