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

Remove SquareRootField, and move functionality to Field #422

Merged
merged 31 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a36784b
Removed SquareRootField
solomonjoseph Feb 7, 2022
a08137e
Merged from master
solomonjoseph Feb 7, 2022
bf84185
Merge cleanup
solomonjoseph Feb 7, 2022
08dc4d6
Reverted changes to track master
solomonjoseph Feb 8, 2022
a518c67
Added Tonelli-Shanks and Shanks sqrt algorithms for cubic extension f…
solomonjoseph Feb 8, 2022
df8d67c
Apply suggestions from code review
Pratyush Feb 8, 2022
d9136e5
WIP: Drafted square root algorithms for cubic extensions
solomonjoseph Mar 29, 2022
0db2b0d
Merge branch 'sjoseph/unify_field_traits' of github.com:arkworks-rs/a…
solomonjoseph Mar 29, 2022
5475426
Small fix
solomonjoseph Mar 29, 2022
db214f6
Merge branch 'master' into unify-sqrt-and-field
mmagician May 25, 2022
4374ec7
Remove old imports
mmagician May 25, 2022
ba4f0cd
As a first step, use Tonelli-Shanks for cubic sqrt
mmagician May 25, 2022
cff8e61
Expose attributes on CubicExtField
mmagician May 25, 2022
69a4c3b
re-introduce SQRT_PRECOMP
mmagician Jul 13, 2022
b6713e9
Call `sqrt_impl` macro from FpConfig square_root
mmagician Jul 13, 2022
08cf0bd
Test sqrt on Fq6_3over2
mmagician Jul 13, 2022
36446a6
sqrt on Fp3 should still work
mmagician Jul 13, 2022
a764fc4
Merge branch 'master' into unify-sqrt-and-field
mmagician Jul 13, 2022
28d5df6
Mark SqrtPrecomputation enum as non-exhaustive
mmagician Jul 14, 2022
90c9b29
Delegate sqrt precom definition to config
mmagician Jul 14, 2022
cb32939
Rename PRECOMP -> SQRT_PRECOMP
mmagician Jul 14, 2022
e4c093a
Merge branch 'master' into unify-sqrt-and-field
mmagician Jul 14, 2022
1341215
Call `from_base_prime_field` instead
mmagician Jul 14, 2022
5976eed
Remove old code
mmagician Jul 14, 2022
40be9d0
Add default impl of sqrt
Pratyush Jul 14, 2022
287cf8d
Delegate SQRT_PRECOMP to FpConfig
mmagician Jul 14, 2022
bbb8883
Add comments and sort definitions
mmagician Jul 14, 2022
5cd329c
Move `SQRT_PRECOMP` to `MontConfig`
Pratyush Jul 14, 2022
d2434f3
Remove `sqrt_impl` macro
Pratyush Jul 14, 2022
63982ec
fmt
mmagician Jul 14, 2022
ef0262d
Update CHANGELOG
Pratyush Jul 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ec/src/hashing/curve_maps/swu/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::models::short_weierstrass::SWCurveConfig;
use ark_ff::{BigInteger, Field, One, PrimeField, SquareRootField, Zero};
use ark_ff::{BigInteger, Field, One, PrimeField, Zero};
use ark_std::string::ToString;
use core::marker::PhantomData;

Expand Down
7 changes: 3 additions & 4 deletions ec/src/hashing/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ use crate::{
CurveConfig,
};
use ark_ff::{
biginteger::BigInteger64, field_hashers::DefaultFieldHasher, fields::Fp64, BigInt, MontBackend,
MontFp,
biginteger::BigInteger64, field_hashers::DefaultFieldHasher, fields::Fp64, BigInt, Field,
MontBackend, MontFp,
};

use ark_ff::SquareRootField;
use ark_std::vec::Vec;
use ark_test_curves::bls12_381::{Fq, Fq2, Fq6};
use hashbrown::HashMap;
Expand Down Expand Up @@ -119,7 +118,7 @@ fn test_field_division() {
/// Check that the hashing parameters are sane: zeta should be a non-square
#[test]
fn checking_the_hashing_parameters() {
assert!(!SquareRootField::legendre(&TestSWUMapToCurveParams::ZETA).is_qr());
assert!(!Field::legendre(&TestSWUMapToCurveParams::ZETA).is_qr());
}

/// The point of the test is to get a simple SWU compatible curve and make
Expand Down
12 changes: 6 additions & 6 deletions ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern crate derivative;
extern crate ark_std;

use ark_ff::{
fields::{Field, PrimeField, SquareRootField},
fields::{Field, PrimeField},
UniformRand,
};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand Down Expand Up @@ -50,7 +50,7 @@ pub mod wnaf;
/// how to compute a pairing over a pairing-friendly curve.
pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + PartialEq {
/// This is the scalar field of the G1/G2 groups.
type Fr: PrimeField + SquareRootField;
type Fr: PrimeField;

/// The projective representation of an element in G1.
type G1Projective: ProjectiveCurve<BaseField = Self::Fq, ScalarField = Self::Fr, Affine = Self::G1Affine>
Expand Down Expand Up @@ -87,10 +87,10 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par
type G2Prepared: Default + Clone + Send + Sync + Debug + From<Self::G2Affine>;

/// The base field that hosts G1.
type Fq: PrimeField + SquareRootField;
type Fq: PrimeField;

/// The extension field that hosts G2.
type Fqe: SquareRootField;
type Fqe: Field;

/// The extension field that hosts the target group of the pairing.
type Fqk: Field;
Expand Down Expand Up @@ -161,7 +161,7 @@ pub trait ProjectiveCurve:
+ From<<Self as ProjectiveCurve>::Affine>
{
type Config: CurveConfig<ScalarField = Self::ScalarField, BaseField = Self::BaseField>;
type ScalarField: PrimeField + SquareRootField;
type ScalarField: PrimeField;
type BaseField: Field;
type Affine: AffineCurve<
Config = Self::Config,
Expand Down Expand Up @@ -251,7 +251,7 @@ pub trait AffineCurve:

/// The group defined by this curve has order `h * r` where `r` is a large
/// prime. `Self::ScalarField` is the prime field defined by `r`
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInt>;
type ScalarField: PrimeField + Into<<Self::ScalarField as PrimeField>::BigInt>;

/// The finite field over which this curve is defined.
type BaseField: Field;
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bls12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ark_ff::fields::{
fp12_2over3over2::{Fp12, Fp12Config},
fp2::Fp2Config,
fp6_3over2::Fp6Config,
BitIteratorBE, Field, Fp2, PrimeField, SquareRootField,
BitIteratorBE, Field, Fp2, PrimeField,
};
use core::marker::PhantomData;
use num_traits::{One, Zero};
Expand All @@ -33,7 +33,7 @@ pub trait Bls12Parameters: 'static {
/// What kind of twist is this?
const TWIST_TYPE: TwistType;

type Fp: PrimeField + SquareRootField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp: PrimeField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp2Config: Fp2Config<Fp = Self::Fp>;
type Fp6Config: Fp6Config<Fp2Config = Self::Fp2Config>;
type Fp12Config: Fp12Config<Fp6Config = Self::Fp6Config>;
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ark_ff::fields::{
fp12_2over3over2::{Fp12, Fp12Config},
fp2::Fp2Config,
fp6_3over2::Fp6Config,
Field, Fp2, PrimeField, SquareRootField,
Field, Fp2, PrimeField,
};
use num_traits::One;

Expand All @@ -31,7 +31,7 @@ pub trait BnParameters: 'static {
const TWIST_TYPE: TwistType;
const TWIST_MUL_BY_Q_X: Fp2<Self::Fp2Config>;
const TWIST_MUL_BY_Q_Y: Fp2<Self::Fp2Config>;
type Fp: PrimeField + SquareRootField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp: PrimeField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp2Config: Fp2Config<Fp = Self::Fp>;
type Fp6Config: Fp6Config<Fp2Config = Self::Fp2Config>;
type Fp12Config: Fp12Config<Fp6Config = Self::Fp6Config>;
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bw6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use ark_ff::fields::{
fp3::Fp3Config,
fp6_2over3::{Fp6, Fp6Config},
BitIteratorBE, Field, PrimeField, SquareRootField,
BitIteratorBE, Field, PrimeField,
};
use num_traits::One;

Expand All @@ -24,7 +24,7 @@ pub trait BW6Parameters: 'static + Eq + PartialEq {
const ATE_LOOP_COUNT_2: &'static [i8];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool;
const TWIST_TYPE: TwistType;
type Fp: PrimeField + SquareRootField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp: PrimeField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fp3Config: Fp3Config<Fp = Self::Fp>;
type Fp6Config: Fp6Config<Fp3Config = Self::Fp3Config>;
type G1Parameters: SWCurveConfig<BaseField = Self::Fp>;
Expand Down
6 changes: 3 additions & 3 deletions ec/src/models/mnt4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use ark_ff::{
fp2::{Fp2, Fp2Config},
fp4::{Fp4, Fp4Config},
BitIteratorBE, Field, PrimeField, SquareRootField,
BitIteratorBE, Field, PrimeField,
};
use num_traits::{One, Zero};

Expand All @@ -30,8 +30,8 @@ pub trait MNT4Parameters: 'static {
const FINAL_EXPONENT_LAST_CHUNK_1: <Self::Fp as PrimeField>::BigInt;
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool;
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: <Self::Fp as PrimeField>::BigInt;
type Fp: PrimeField + SquareRootField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fr: PrimeField + SquareRootField + Into<<Self::Fr as PrimeField>::BigInt>;
type Fp: PrimeField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fr: PrimeField + Into<<Self::Fr as PrimeField>::BigInt>;
type Fp2Config: Fp2Config<Fp = Self::Fp>;
type Fp4Config: Fp4Config<Fp2Config = Self::Fp2Config>;
type G1Parameters: SWCurveConfig<BaseField = Self::Fp, ScalarField = Self::Fr>;
Expand Down
6 changes: 3 additions & 3 deletions ec/src/models/mnt6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use ark_ff::{
fp3::{Fp3, Fp3Config},
fp6_2over3::{Fp6, Fp6Config},
BitIteratorBE, Field, PrimeField, SquareRootField,
BitIteratorBE, Field, PrimeField,
};
use num_traits::{One, Zero};

Expand All @@ -30,8 +30,8 @@ pub trait MNT6Parameters: 'static {
const FINAL_EXPONENT_LAST_CHUNK_1: <Self::Fp as PrimeField>::BigInt;
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool;
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: <Self::Fp as PrimeField>::BigInt;
type Fp: PrimeField + SquareRootField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fr: PrimeField + SquareRootField + Into<<Self::Fr as PrimeField>::BigInt>;
type Fp: PrimeField + Into<<Self::Fp as PrimeField>::BigInt>;
type Fr: PrimeField + Into<<Self::Fr as PrimeField>::BigInt>;
type Fp3Config: Fp3Config<Fp = Self::Fp>;
type Fp6Config: Fp6Config<Fp3Config = Self::Fp3Config>;
type G1Parameters: SWCurveConfig<BaseField = Self::Fp, ScalarField = Self::Fr>;
Expand Down
6 changes: 3 additions & 3 deletions ec/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ark_ff::{Field, PrimeField, SquareRootField};
use ark_ff::{Field, PrimeField};

pub mod bls12;
pub mod bn;
Expand All @@ -16,10 +16,10 @@ pub mod twisted_edwards;
/// prime-order subgroup of the curve.
pub trait CurveConfig: Send + Sync + Sized + 'static {
/// Base field that the curve is defined over.
type BaseField: Field + SquareRootField;
type BaseField: Field;
/// Finite prime field corresponding to an appropriate prime-order subgroup
/// of the curve group.
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInt>;
type ScalarField: PrimeField + Into<<Self::ScalarField as PrimeField>::BigInt>;

const COFACTOR: &'static [u64];
const COFACTOR_INV: Self::ScalarField;
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/short_weierstrass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use ark_std::{
};

use ark_ff::{
fields::{Field, PrimeField, SquareRootField},
fields::{Field, PrimeField},
ToConstraintField, UniformRand,
};

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/twisted_edwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use num_traits::{One, Zero};
use zeroize::Zeroize;

use ark_ff::{
fields::{Field, PrimeField, SquareRootField},
fields::{Field, PrimeField},
ToConstraintField, UniformRand,
};

Expand Down
11 changes: 6 additions & 5 deletions ff/src/fields/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
macro_rules! sqrt_impl {
($Self:ident, $P:tt, $self:expr) => {{
($Self:ident, $self:expr, $two_adicity:expr, $trace_minus_one_div_two:expr, $quadratic_nonresidue:expr) => {{
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
// Actually this is just normal Tonelli-Shanks; since `P::Generator`
// is a quadratic non-residue, `P::ROOT_OF_UNITY = P::GENERATOR ^ t`
Expand All @@ -10,12 +10,13 @@ macro_rules! sqrt_impl {
// Try computing the square root (x at the end of the algorithm)
// Check at the end of the algorithm if x was a square root
// Begin Tonelli-Shanks
let mut z = $Self::qnr_to_t();
let mut w = $self.pow($P::TRACE_MINUS_ONE_DIV_TWO);
let mut z = *$quadratic_nonresidue;
let mut w = $self.pow($trace_minus_one_div_two);
let mut x = w * $self;
let mut b = x * &w;

let mut v = $P::TWO_ADICITY as usize;
// let mut v = $P::TWO_ADICITY as usize;
let mut v = *$two_adicity as usize;

while !b.is_one() {
let mut k = 0usize;
Expand All @@ -27,7 +28,7 @@ macro_rules! sqrt_impl {
k += 1;
}

if k == ($P::TWO_ADICITY as usize) {
if k == (*$two_adicity as usize) {
// We are in the case where self^(T * 2^k) = x^(P::MODULUS - 1) = 1,
// which means that no square root exists.
return None;
Expand Down
66 changes: 45 additions & 21 deletions ff/src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ pub trait Field:
+ From<bool>
{
type BasePrimeField: PrimeField;

const SQRT_PRECOMP: Option<SqrtPrecomputation<Self>>;

type BasePrimeFieldIter: Iterator<Item = Self::BasePrimeField>;

/// The additive identity of the field.
Expand Down Expand Up @@ -177,6 +180,19 @@ pub trait Field:
/// from a hash-function or RNG output.
fn from_random_bytes_with_flags<F: Flags>(bytes: &[u8]) -> Option<(Self, F)>;

/// Returns a `LegendreSymbol`, which indicates whether this field element
/// is 1 : a quadratic residue
/// 0 : equal to 0
/// -1 : a quadratic non-residue
fn legendre(&self) -> LegendreSymbol;

/// Returns the square root of self, if it exists.
#[must_use]
fn sqrt(&self) -> Option<Self>;

/// Sets `self` to be the square root of `self`, if it exists.
fn sqrt_in_place(&mut self) -> Option<&mut Self>;

/// Returns `self * self`.
#[must_use]
fn square(&self) -> Self;
Expand Down Expand Up @@ -407,30 +423,13 @@ pub trait PrimeField:
}
}

/// The interface for a field that supports an efficient square-root operation.
pub trait SquareRootField: Field {
/// Returns a `LegendreSymbol`, which indicates whether this field element
/// is
/// - 1: a quadratic residue
/// - 0: equal to 0
/// - -1: a quadratic non-residue
fn legendre(&self) -> LegendreSymbol;

/// Returns the square root of self, if it exists.
#[must_use]
fn sqrt(&self) -> Option<Self>;

/// Sets `self` to be the square root of `self`, if it exists.
fn sqrt_in_place(&mut self) -> Option<&mut Self>;
}

/// Indication of the field element's quadratic residuosity
///
/// # Examples
/// ```
/// # use ark_std::test_rng;
/// # use ark_std::UniformRand;
/// # use ark_test_curves::{LegendreSymbol, Field, SquareRootField, bls12_381::Fq as Fp};
/// # use ark_test_curves::{LegendreSymbol, Field, bls12_381::Fq as Fp};
/// let a: Fp = Fp::rand(&mut test_rng());
/// let b = a.square();
/// assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
Expand All @@ -449,7 +448,7 @@ impl LegendreSymbol {
/// ```
/// # use ark_std::test_rng;
/// # use ark_std::UniformRand;
/// # use ark_test_curves::{LegendreSymbol, Field, SquareRootField, bls12_381::Fq as Fp};
/// # use ark_test_curves::{LegendreSymbol, Field, bls12_381::Fq as Fp};
/// let a: Fp = Fp::rand(&mut test_rng());
/// let b: Fp = a.square();
/// assert!(!b.legendre().is_zero());
Expand All @@ -462,7 +461,7 @@ impl LegendreSymbol {
///
/// # Examples
/// ```
/// # use ark_test_curves::{Fp2Config, LegendreSymbol, SquareRootField, bls12_381::{Fq, Fq2Config}};
/// # use ark_test_curves::{Fp2Config, Field, LegendreSymbol, bls12_381::{Fq, Fq2Config}};
/// let a: Fq = Fq2Config::NONRESIDUE;
/// assert!(a.legendre().is_qnr());
/// ```
Expand All @@ -476,7 +475,7 @@ impl LegendreSymbol {
/// # use ark_std::test_rng;
/// # use ark_test_curves::bls12_381::Fq as Fp;
/// # use ark_std::UniformRand;
/// # use ark_ff::{LegendreSymbol, Field, SquareRootField};
/// # use ark_ff::{LegendreSymbol, Field};
/// let a: Fp = Fp::rand(&mut test_rng());
/// let b: Fp = a.square();
/// assert!(b.legendre().is_qr());
Expand All @@ -486,6 +485,31 @@ impl LegendreSymbol {
}
}

pub enum SqrtPrecomputation<F: Field> {
Pratyush marked this conversation as resolved.
Show resolved Hide resolved
// Tonelli-Shanks algorithm works for all elements, no matter what the modulus is.
TonelliShanks(u32, &'static [u64], F),
}

impl<F: Field> SqrtPrecomputation<F> {
fn sqrt(&self, elem: &F) -> Option<F> {
match self {
SqrtPrecomputation::TonelliShanks(
two_adicity,
trace_minus_one_div_two,
quad_non_residue_to_t,
) => {
sqrt_impl!(
F,
elem,
two_adicity,
trace_minus_one_div_two,
quad_non_residue_to_t
)
},
}
}
}

/// Iterates over a slice of `u64` in *big-endian* order.
#[derive(Debug)]
pub struct BitIteratorBE<Slice: AsRef<[u64]>> {
Expand Down
Loading