Skip to content

Commit

Permalink
Fast modular inverse - 9.4x acceleration (privacy-scaling-exploration…
Browse files Browse the repository at this point in the history
…s#83)

* Bernstein yang modular multiplicative inverter (#2)

* rename similar to privacy-scaling-explorations#95

---------

Co-authored-by: Aleksei Vambol <[email protected]>
  • Loading branch information
mratsim and AlekseiVambol authored Oct 19, 2023
1 parent 91d8dc1 commit a835096
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 60 deletions.
3 changes: 3 additions & 0 deletions benches/bn256_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pub fn bench_bn256_field(c: &mut Criterion) {
group.bench_function("bn256_fq_square", |bencher| {
bencher.iter(|| black_box(&a).square())
});
group.bench_function("bn256_fq_invert", |bencher| {
bencher.iter(|| black_box(&a).invert())
});
}

criterion_group!(benches, bench_bn256_field);
Expand Down
13 changes: 3 additions & 10 deletions src/bn256/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,10 @@ impl ff::Field for Fq {
ff::helpers::sqrt_ratio_generic(num, div)
}

/// Computes the multiplicative inverse of this element,
/// failing if the element is zero.
/// Returns the multiplicative inverse of the
/// element. If it is zero, the method fails.
fn invert(&self) -> CtOption<Self> {
let tmp = self.pow([
0x3c208c16d87cfd45,
0x97816a916871ca8d,
0xb85045b68181585d,
0x30644e72e131a029,
]);

CtOption::new(tmp, !self.ct_eq(&Self::zero()))
self.invert()
}
}

Expand Down
13 changes: 3 additions & 10 deletions src/bn256/fr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,10 @@ impl ff::Field for Fr {
self.square()
}

/// Computes the multiplicative inverse of this element,
/// failing if the element is zero.
/// Returns the multiplicative inverse of the
/// element. If it is zero, the method fails.
fn invert(&self) -> CtOption<Self> {
let tmp = self.pow([
0x43e1f593efffffff,
0x2833e84879b97091,
0xb85045b68181585d,
0x30644e72e131a029,
]);

CtOption::new(tmp, !self.ct_eq(&Self::zero()))
self.invert()
}

fn sqrt(&self) -> CtOption<Self> {
Expand Down
16 changes: 16 additions & 0 deletions src/derive/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ macro_rules! field_common {
$r2:ident,
$r3:ident
) => {
/// Bernstein-Yang modular multiplicative inverter created for the modulus equal to
/// the characteristic of the field to invert positive integers in the Montgomery form.
const BYINVERTOR: $crate::ff_inverse::BYInverter<6> =
$crate::ff_inverse::BYInverter::<6>::new(&$modulus.0, &$r2.0);

impl $field {
/// Returns zero, the additive identity.
#[inline]
Expand All @@ -37,6 +42,16 @@ macro_rules! field_common {
$r
}

/// Returns the multiplicative inverse of the
/// element. If it is zero, the method fails.
pub fn invert(&self) -> CtOption<Self> {
if let Some(inverse) = BYINVERTOR.invert(&self.0) {
CtOption::new(Self(inverse), Choice::from(1))
} else {
CtOption::new(Self::zero(), Choice::from(0))
}
}

fn from_u512(limbs: [u64; 8]) -> $field {
// We reduce an arbitrary 512-bit number by decomposing it into two 256-bit digits
// with the higher bits multiplied by 2^256. Thus, we perform two reductions
Expand Down Expand Up @@ -345,6 +360,7 @@ macro_rules! field_common {
macro_rules! field_arithmetic {
($field:ident, $modulus:ident, $inv:ident, $field_type:ident) => {
field_specific!($field, $modulus, $inv, $field_type);

impl $field {
/// Doubles this field element.
#[inline]
Expand Down
Loading

0 comments on commit a835096

Please sign in to comment.