Skip to content

Commit

Permalink
Fix MontFp issue in fields with 64 * k bits (#550)
Browse files Browse the repository at this point in the history
* fix

* use the spare bit

* mont macro

* remove unused

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
  • Loading branch information
3 people authored Dec 21, 2022
1 parent 6d20923 commit 3351d0f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 8 deletions.
2 changes: 1 addition & 1 deletion ff/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ digest = { version = "0.10", default-features = false, features = ["alloc"] }
itertools = { version = "0.10", default-features = false }

[dev-dependencies]
ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = [ "bls12_381_curve", "mnt6_753"] }
ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = [ "bls12_381_curve", "mnt6_753", "secp256k1"] }
blake2 = { version = "0.10", default-features = false }
sha3 = { version = "0.10", default-features = false }
sha2 = { version = "0.10", default-features = false }
Expand Down
76 changes: 69 additions & 7 deletions ff/src/fields/models/fp/montgomery_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,19 @@ pub trait MontConfig<const N: usize>: 'static + Sync + Send + Sized {
}
(a.0).0 = r;
}
a.subtract_modulus();
} else {
// Alternative implementation
// Implements CIOS.
*a = a.mul_without_cond_subtract(b);
let (carry, res) = a.mul_without_cond_subtract(b);
*a = res;

if Self::MODULUS_HAS_SPARE_BIT {
a.subtract_modulus_with_carry(carry);
} else {
a.subtract_modulus();
}
}
a.subtract_modulus();
}

#[inline(always)]
Expand Down Expand Up @@ -734,7 +741,7 @@ impl<T: MontConfig<N>, const N: usize> Fp<MontBackend<T, N>, N> {
}
}

const fn mul_without_cond_subtract(mut self, other: &Self) -> Self {
const fn mul_without_cond_subtract(mut self, other: &Self) -> (bool, Self) {
let (mut lo, mut hi) = ([0u64; N], [0u64; N]);
crate::const_for!((i in 0..N) {
let mut carry = 0;
Expand Down Expand Up @@ -768,12 +775,16 @@ impl<T: MontConfig<N>, const N: usize> Fp<MontBackend<T, N>, N> {
crate::const_for!((i in 0..N) {
(self.0).0[i] = hi[i];
});
self
(carry2 != 0, self)
}

const fn mul(mut self, other: &Self) -> Self {
self = self.mul_without_cond_subtract(other);
self.const_subtract_modulus()
const fn mul(self, other: &Self) -> Self {
let (carry, res) = self.mul_without_cond_subtract(other);
if T::MODULUS_HAS_SPARE_BIT {
res.const_subtract_modulus()
} else {
res.const_subtract_modulus_with_carry(carry)
}
}

const fn const_is_valid(&self) -> bool {
Expand All @@ -795,7 +806,58 @@ impl<T: MontConfig<N>, const N: usize> Fp<MontBackend<T, N>, N> {
self
}

#[inline]
const fn const_subtract_modulus_with_carry(mut self, carry: bool) -> Self {
if carry || !self.const_is_valid() {
self.0 = Self::sub_with_borrow(&self.0, &T::MODULUS);
}
self
}

const fn sub_with_borrow(a: &BigInt<N>, b: &BigInt<N>) -> BigInt<N> {
a.const_sub_with_borrow(b).0
}
}

#[cfg(test)]
mod test {
use ark_std::str::FromStr;
use ark_std::vec::Vec;
use ark_test_curves::secp256k1::Fr;
use num_bigint::{BigInt, BigUint, Sign};

#[test]
fn test_mont_macro_correctness() {
let (is_positive, limbs) = str_to_limbs_u64(
"111192936301596926984056301862066282284536849596023571352007112326586892541694",
);
let t = Fr::from_sign_and_limbs(is_positive, &limbs);

let result: BigUint = t.into();
let expected = BigUint::from_str(
"111192936301596926984056301862066282284536849596023571352007112326586892541694",
)
.unwrap();

assert_eq!(result, expected);
}

fn str_to_limbs_u64(num: &str) -> (bool, Vec<u64>) {
let (sign, digits) = BigInt::from_str(num)
.expect("could not parse to bigint")
.to_radix_le(16);
let limbs = digits
.chunks(16)
.map(|chunk| {
let mut this = 0u64;
for (i, hexit) in chunk.iter().enumerate() {
this += (*hexit as u64) << (4 * i);
}
this
})
.collect::<Vec<_>>();

let sign_is_positive = sign != Sign::Minus;
(sign_is_positive, limbs)
}
}

0 comments on commit 3351d0f

Please sign in to comment.