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

✖️ Modular exponentiation implementation #43

Closed
wants to merge 69 commits into from

Conversation

ZamDimon
Copy link

@ZamDimon ZamDimon commented May 6, 2024

What ❔

This pull request adds the modular exponentiation (modexp) implementation, that is, performing an operation $b^e \; \text{mod} \; m$.

While implementing the modexp, we have also implemented the modular multiplication (modmul) that calculates $a \times b \; \text{mod} \; m$.

Why ❔

To further have the modexp precompile, we need the corresponding implementation over a tuple of (UInt256<F>, UInt256<F>, UInt256<F>).

Checklist

  • PR title corresponds to the body of PR (we generate changelog entries from PRs).
  • Tests for the changes have been added / updated.
  • Documentation comments have been added / updated.
  • Code has been formatted via zk fmt and zk lint.

ZamDimon and others added 30 commits March 12, 2024 16:12
…-trait-impls`

🗼 Tower Extension Implementation
Comment on lines 42 to 57
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)
}
Copy link
Member

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?

Copy link
Member

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

Copy link
Author

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!

}

/// 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
Copy link
Member

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 :)

Copy link
Author

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 :)

@ZamDimon
Copy link
Author

modexp will be transferred to era-zkevm_circuits and will not be included in era-boojum. Therefore, we close this pull request. For helper gadgets, see PR #38.

@ZamDimon ZamDimon closed this May 22, 2024
@NikitaMasych NikitaMasych deleted the feature/modexp branch May 23, 2024 13:42
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.

None yet

3 participants