Skip to content
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

Merged
merged 2 commits into from
Nov 3, 2023
Merged

Fix bitwise rotate #109

merged 2 commits into from
Nov 3, 2023

Conversation

nyunyunyunyu
Copy link
Contributor

The existing implementation of const_right_rotate_unsafe_internal is under-constraints. r_witness should have bit bits but it's also valid if it equals to a.

@jonathanpwang jonathanpwang enabled auto-merge (squash) August 19, 2023 18:14
Copy link
Contributor

@jonathanpwang jonathanpwang left a 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 Show resolved Hide resolved
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));
Copy link
Contributor

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)

Copy link
Contributor

@jonathanpwang jonathanpwang left a 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.

@jonathanpwang jonathanpwang merged commit 262f5c5 into community-edition Nov 3, 2023
2 checks passed
@jonathanpwang jonathanpwang deleted the fix/bitwise-rotate branch November 3, 2023 05:13
pnyda pushed a commit to MynaWallet/halo2-lib that referenced this pull request Nov 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants