Skip to content

Commit

Permalink
Add PrimeField::TWO_INV associated constant
Browse files Browse the repository at this point in the history
This is a useful constant in a variety of scenarios, and providing it
saves an inversion. This also reinforces the intention that `PrimeField`
represents a non-binary field with odd prime order (which is now clearly
documented).
  • Loading branch information
str4d committed Nov 24, 2022
1 parent c070ffb commit 9c30ad3
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this library adheres to Rust's notion of
- `ff::Field::pow`
- `ff::Field::{sqrt_ratio, sqrt_alt}`
- `core::iter::{Sum, Product}` bounds on `ff::Field`
- `ff::PrimeField::TWO_INV`
- `ff::PrimeField::{MULTIPLICATIVE_GENERATOR, ROOT_OF_UNITY}`
- `ff::helpers`:
- `sqrt_tonelli_shanks`
Expand All @@ -23,6 +24,9 @@ and this library adheres to Rust's notion of
if it is more efficient in practice, or they can keep their own implementation
of `Field::sqrt` and implement `Field::sqrt_ratio` in terms of that
implementation using the `ff::helpers::sqrt_ratio_generic` helper function.
- `ff::PrimeField` is now documented as representing a non-binary field (i.e.
its prime is not 2). This was always the intention, but is now a concrete
requirement in order for `PrimeField::TWO_INV` to exist.

### Removed
- `ff::Field::{zero, one}` (use `ff::Field::{ZERO, ONE}` instead).
Expand Down
20 changes: 16 additions & 4 deletions ff_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,14 @@ fn prime_field_constants_and_sqrt(

// Compute R = 2**(64 * limbs) mod m
let r = (BigUint::one() << (limbs * 64)) % modulus;
let to_mont = |v| (v * &r) % modulus;

let two = BigUint::from_str("2").unwrap();
let p_minus_2 = modulus - &two;
let invert = |v| exp(v, &p_minus_2, &modulus);

// 2^-1 mod m
let two_inv = biguint_to_u64_vec(to_mont(invert(two)), limbs);

// modulus - 1 = 2^s * t
let mut s: u32 = 0;
Expand All @@ -489,9 +497,8 @@ fn prime_field_constants_and_sqrt(
}

// Compute 2^s root of unity given the generator
let root_of_unity =
biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % modulus, limbs);
let generator = biguint_to_u64_vec((generator.clone() * &r) % modulus, limbs);
let root_of_unity = biguint_to_u64_vec(to_mont(exp(generator.clone(), &t, &modulus)), limbs);
let generator = biguint_to_u64_vec(to_mont(generator), limbs);

let sqrt_impl =
if (modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
Expand Down Expand Up @@ -577,7 +584,7 @@ fn prime_field_constants_and_sqrt(
};

// Compute R^2 mod m
let r2 = biguint_to_u64_vec((&r * &r) % modulus, limbs);
let r2 = biguint_to_u64_vec(to_mont(r.clone()), limbs);

let r = biguint_to_u64_vec(r, limbs);
let modulus_le_bytes = ReprEndianness::Little.modulus_repr(modulus, limbs * 8);
Expand Down Expand Up @@ -618,6 +625,9 @@ fn prime_field_constants_and_sqrt(
/// -(m^{-1} mod m) mod m
const INV: u64 = #inv;

/// 2^{-1} mod m
const TWO_INV: #name = #name(#two_inv);

/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
/// nonresidue.
const GENERATOR: #name = #name(#generator);
Expand Down Expand Up @@ -1219,6 +1229,8 @@ fn prime_field_impl(

const CAPACITY: u32 = Self::NUM_BITS - 1;

const TWO_INV: Self = TWO_INV;

const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;

const S: u32 = S;
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub trait Field:
}
}

/// This represents an element of a prime field.
/// This represents an element of a non-binary prime field.
pub trait PrimeField: Field + From<u64> {
/// The prime field can be converted back and forth into this binary
/// representation.
Expand Down Expand Up @@ -288,6 +288,9 @@ pub trait PrimeField: Field + From<u64> {
/// This is usually `Self::NUM_BITS - 1`.
const CAPACITY: u32;

/// Inverse of $2$ in the field.
const TWO_INV: Self;

/// A fixed multiplicative generator of `modulus - 1` order. This element must also be
/// a quadratic nonresidue.
///
Expand Down
10 changes: 10 additions & 0 deletions tests/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ mod full_limbs {
}
}

#[test]
fn constants() {
use ff::{Field, PrimeField};

assert_eq!(
Bls381K12Scalar::from(2) * Bls381K12Scalar::TWO_INV,
Bls381K12Scalar::ONE,
);
}

#[test]
fn batch_inversion() {
use ff::{BatchInverter, Field};
Expand Down

0 comments on commit 9c30ad3

Please sign in to comment.