-
Notifications
You must be signed in to change notification settings - Fork 60
Runtime moduli #134
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
Merged
Merged
Runtime moduli #134
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
213e796
Implement Modular with add and mul
jellevos f13f399
Implement modular exponentiation
jellevos d1177b1
Merge remote-tracking branch 'upstream/master' into powmod
jellevos d3887f0
Fix obvious issues and add documentation
jellevos 4177420
Use Word instead of u64
jellevos df3c898
Use e.g. U64 instead of UInt::<1>
jellevos bf77788
Rewrite uint operations to const fn
jellevos 154d82e
Checkpoint: working modulus macro
jellevos 1814a0d
Add tests and make remaining fn const
jellevos daf3299
Make pow a const fn
jellevos 515d78d
Add missing documentation
jellevos a0ed6ff
Bump rustc version to 1.61
jellevos 0cd95b7
Bump rustc version to 1.61 in Github actions
jellevos dc85a35
Address comments
jellevos e57e1d9
Add const keyword to modular add
jellevos 57cb0b7
Initial implementation of runtime moduli
jellevos 9051b11
Write docstring where required
jellevos beccc95
Implement inverse for residues
jellevos 2fff3e1
Cargo fmt
jellevos 9d51b10
Merge branch 'runtime-moduli' into powmod
jellevos 423e60f
Remove runtime moduli (not in PR scope)
jellevos b455a09
Fix docstring and remove stale code
jellevos dcdb1f6
Revert ConstResidue to Residue
jellevos a2ee635
Impl two invs: panicking and ctoption
jellevos 797ad32
Change Residue to DynResidue
jellevos 04ce885
Merge remote-tracking branch 'upstream/master' into runtime-moduli
jellevos 17963d8
Make residue traits public
jellevos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
use crate::{Limb, UInt, Word}; | ||
|
||
use super::{reduction::montgomery_reduction, GenericResidue}; | ||
|
||
/// Additions between residues with a modulus set at runtime | ||
mod runtime_add; | ||
/// Multiplicative inverses of residues with a modulus set at runtime | ||
mod runtime_inv; | ||
/// Multiplications between residues with a modulus set at runtime | ||
mod runtime_mul; | ||
/// Exponentiation of residues with a modulus set at runtime | ||
mod runtime_pow; | ||
|
||
/// The parameters to efficiently go to and from the Montgomery form for a modulus provided at runtime. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct DynResidueParams<const LIMBS: usize> { | ||
// The constant modulus | ||
modulus: UInt<LIMBS>, | ||
// Parameter used in Montgomery reduction | ||
r: UInt<LIMBS>, | ||
// R^2, used to move into Montgomery form | ||
r2: UInt<LIMBS>, | ||
// R^3, used to compute the multiplicative inverse | ||
r3: UInt<LIMBS>, | ||
// The lowest limbs of -(MODULUS^-1) mod R | ||
// We only need the LSB because during reduction this value is multiplied modulo 2**64. | ||
mod_neg_inv: Limb, | ||
} | ||
|
||
impl<const LIMBS: usize> DynResidueParams<LIMBS> { | ||
/// Instantiates a new set of `ResidueParams` representing the given `modulus`. | ||
pub fn new(modulus: UInt<LIMBS>) -> Self { | ||
let r = UInt::MAX.ct_reduce(&modulus).0.wrapping_add(&UInt::ONE); | ||
let r2 = UInt::ct_reduce_wide(r.square_wide(), &modulus).0; | ||
let mod_neg_inv = | ||
Limb(Word::MIN.wrapping_sub(modulus.inv_mod2k(Word::BITS as usize).limbs[0].0)); | ||
let r3 = montgomery_reduction(r2.square_wide(), modulus, mod_neg_inv); | ||
|
||
Self { | ||
modulus, | ||
r, | ||
r2, | ||
r3, | ||
mod_neg_inv, | ||
} | ||
} | ||
} | ||
|
||
/// A residue represented using `LIMBS` limbs. The odd modulus of this residue is set at runtime. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct DynResidue<const LIMBS: usize> { | ||
montgomery_form: UInt<LIMBS>, | ||
residue_params: DynResidueParams<LIMBS>, | ||
} | ||
|
||
impl<const LIMBS: usize> DynResidue<LIMBS> { | ||
/// Instantiates a new `Residue` that represents this `integer` mod `MOD`. | ||
pub const fn new(integer: UInt<LIMBS>, residue_params: DynResidueParams<LIMBS>) -> Self { | ||
let mut modular_integer = Self { | ||
montgomery_form: integer, | ||
residue_params, | ||
}; | ||
|
||
let product = integer.mul_wide(&residue_params.r2); | ||
modular_integer.montgomery_form = | ||
montgomery_reduction(product, residue_params.modulus, residue_params.mod_neg_inv); | ||
|
||
modular_integer | ||
} | ||
|
||
/// Retrieves the integer currently encoded in this `Residue`, guaranteed to be reduced. | ||
pub const fn retrieve(&self) -> UInt<LIMBS> { | ||
montgomery_reduction( | ||
(self.montgomery_form, UInt::ZERO), | ||
self.residue_params.modulus, | ||
self.residue_params.mod_neg_inv, | ||
) | ||
} | ||
} | ||
|
||
impl<const LIMBS: usize> GenericResidue<LIMBS> for DynResidue<LIMBS> { | ||
fn retrieve(&self) -> UInt<LIMBS> { | ||
self.retrieve() | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use core::ops::{Add, AddAssign}; | ||
|
||
use crate::{ | ||
modular::{add::add_montgomery_form, AddResidue}, | ||
UInt, | ||
}; | ||
|
||
use super::DynResidue; | ||
|
||
impl<const LIMBS: usize> AddResidue for DynResidue<LIMBS> { | ||
fn add(&self, rhs: &Self) -> Self { | ||
debug_assert_eq!(self.residue_params, rhs.residue_params); | ||
Self { | ||
montgomery_form: add_montgomery_form( | ||
&self.montgomery_form, | ||
&rhs.montgomery_form, | ||
&self.residue_params.modulus, | ||
), | ||
residue_params: self.residue_params, | ||
} | ||
} | ||
} | ||
|
||
impl<const LIMBS: usize> AddAssign for DynResidue<LIMBS> { | ||
fn add_assign(&mut self, rhs: Self) { | ||
self.montgomery_form = add_montgomery_form( | ||
&self.montgomery_form, | ||
&rhs.montgomery_form, | ||
&self.residue_params.modulus, | ||
); | ||
} | ||
} | ||
|
||
impl<const LIMBS: usize> AddAssign<UInt<LIMBS>> for DynResidue<LIMBS> { | ||
fn add_assign(&mut self, rhs: UInt<LIMBS>) { | ||
self.montgomery_form = add_montgomery_form( | ||
&self.montgomery_form, | ||
&DynResidue::new(rhs, self.residue_params).montgomery_form, | ||
&self.residue_params.modulus, | ||
); | ||
} | ||
} | ||
|
||
impl<const LIMBS: usize> Add for DynResidue<LIMBS> { | ||
type Output = DynResidue<LIMBS>; | ||
|
||
fn add(mut self, rhs: Self) -> Self::Output { | ||
self += rhs; | ||
self | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::{ | ||
modular::runtime_mod::{DynResidue, DynResidueParams}, | ||
U256, | ||
}; | ||
|
||
#[test] | ||
fn add_overflow() { | ||
let params = DynResidueParams::new(U256::from_be_hex( | ||
"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", | ||
)); | ||
|
||
let x = | ||
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); | ||
let mut x_mod = DynResidue::new(x, params); | ||
|
||
let y = | ||
U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); | ||
|
||
x_mod += y; | ||
|
||
let expected = | ||
U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"); | ||
|
||
assert_eq!(expected, x_mod.retrieve()); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
use subtle::{Choice, CtOption}; | ||
|
||
use crate::{ | ||
modular::{inv::inv_montgomery_form, InvResidue}, | ||
Word, | ||
}; | ||
|
||
use super::DynResidue; | ||
|
||
impl<const LIMBS: usize> InvResidue for DynResidue<LIMBS> { | ||
fn inv(self) -> CtOption<Self> { | ||
let (montgomery_form, error) = inv_montgomery_form( | ||
self.montgomery_form, | ||
self.residue_params.modulus, | ||
&self.residue_params.r3, | ||
self.residue_params.mod_neg_inv, | ||
); | ||
|
||
let value = Self { | ||
montgomery_form, | ||
residue_params: self.residue_params, | ||
}; | ||
|
||
CtOption::new(value, Choice::from((error == Word::MAX) as u8)) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This PR looks good aside from the use of the 2015 edition module style (i.e.
mod.rs
)We've adopted the 2018 edition module style, where this file would be modular.rs.
Unfortunately I don't think they ever added a lint for mixed module styles.
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.
Is this what you mean?:
https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files
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.
Oh ho, went looking for that the other day and didn't find it... weird