-
Notifications
You must be signed in to change notification settings - Fork 72
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
✖️ Modular exponentiation implementation #43
Conversation
…or usage under the curve
…-trait-impls` 🗼 Tower Extension Implementation
…igin' into feature/modexp
src/gadgets/modexp/mod.rs
Outdated
fn u512_geq_than_u256<F, CS>(cs: &mut CS, a: &UInt512<F>, b: &UInt256<F>) -> Boolean<F> | ||
where | ||
F: SmallField, | ||
CS: ConstraintSystem<F>, | ||
{ | ||
let mut limbs = [UInt32::zero(cs); 16]; | ||
// Put b.inner into first 8 elements | ||
limbs[..8].copy_from_slice(&b.inner); | ||
|
||
let b_u512 = UInt512::from_limbs(limbs); | ||
// If a >= b, then b-a should overflow or equal to 0 | ||
let (sub, overflow) = b_u512.overflowing_sub(cs, a); | ||
let a_equal_b = sub.is_zero(cs); | ||
|
||
overflow.or(cs, a_equal_b) | ||
} |
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.
could it potentially be cheaper to do this with a.to_low()
rather than making a UInt512
for b
and incurring the extra constraints during the sub
?
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.
what i mean here is something like this:
let high = a.to_high();
let under_256 = high.is_zero(cs);
let over_256 = under_256.negated(cs);
let low = a.to_low();
let (sub, overflow) = b.overflowing_sub(cs, low);
let a_equal_b = sub.is_zero(cs);
Boolean::multi_or(cs, &[overflow, a_equal_b, over_256])
i think it may be a little cheaper
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, sub for two UInt256<F>
should be indeed much cheaper than for two UInt512<F>
, fixed!
src/gadgets/modexp/mod.rs
Outdated
} | ||
|
||
/// Find quotient and remainder of division of `n` by `m` using the naive long division algorithm in base 2^{32} | ||
/// since both `UInt512<F>` and `UInt256<F>` are represented as arrays of `UInt8<F>`. The implementation is based on |
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.
small nit: they are represented as arrays of UInt32
, not UInt8
:)
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.
Oooops, indeed my bad, fixed :)
…veFieldOverU16Params and NonNativeFieldOverU16
…onNativeFieldOverU16
|
What ❔
This pull request adds the modular exponentiation ($b^e \; \text{mod} \; m$ .
modexp
) implementation, that is, performing an operationWhile implementing the$a \times b \; \text{mod} \; m$ .
modexp
, we have also implemented the modular multiplication (modmul
) that calculatesWhy ❔
To further have the
modexp
precompile, we need the corresponding implementation over a tuple of(UInt256<F>, UInt256<F>, UInt256<F>)
.Checklist
zk fmt
andzk lint
.