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

rearranging arkworks / non-arkworks ECC code #82

Merged
merged 14 commits into from
Jan 31, 2024
Merged
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ std = ["alloc", "tracing/std", "anyhow/std", "tracing-subscriber/std", "zeroize/
parallel = ["ark-ff/parallel", "ark-ec/parallel", "ark-groth16/parallel", "ark-std/parallel", "ark-r1cs-std/parallel"]
# TODO: eventually, feature-gate all arkworks deps behind this feature.
arkworks = ["std", "ark-std", "ark-ec", "ark-ff", "ark-serialize", "ark-bls12-377", "ark-ed-on-bls12-377"]
r1cs = ["ark-groth16", "ark-r1cs-std", "ark-relations", "ark-snark"]
r1cs = ["arkworks", "ark-groth16", "ark-r1cs-std", "ark-relations", "ark-snark"]
u32_backend = []

[dev-dependencies]
Expand Down
4 changes: 1 addition & 3 deletions benches/sqrt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ fn sqrt_original(u: &Fq, v: &Fq) -> (bool, Fq) {
if let Some(sqrt_uv) = uv.sqrt() {
(true, sqrt_uv)
} else {
let sqrt_zeta_uv = (*ZETA * uv)
.sqrt()
.expect("must be square if u/v nonsquare");
let sqrt_zeta_uv = (ZETA * uv).sqrt().expect("must be square if u/v nonsquare");
(false, sqrt_zeta_uv)
}
}
Expand Down
File renamed without changes.
13 changes: 7 additions & 6 deletions src/constants.rs → src/ark_curve/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ fn from_ark_fr(x: ArkFr) -> Fr {
}

// Zeta is called QNR in the sage specification.
pub static ZETA: Lazy<Fq> = Lazy::new(|| {
from_ark_fq(ark_ff::MontFp!(
"2841681278031794617739547238867782961338435681360110683443920362658525667816"
))
});
pub const ZETA: Fq = Fq::from_montgomery_limbs_64([
5947794125541564500,
11292571455564096885,
11814268415718120036,
155746270000486182,
]);

// Constants used for square root computation //

Expand Down Expand Up @@ -51,7 +52,7 @@ pub static ZETA_TO_ONE_MINUS_M_DIV_TWO: Lazy<Fq> = Lazy::new(|| {

// G = ZETA^M
// = 4732611889701835744065511820927274956354524915951001256593514693060564426294
pub static G: Lazy<Fq> = Lazy::new(|| (*ZETA).pow(*M));
pub static G: Lazy<Fq> = Lazy::new(|| ZETA.pow(*M));

// Choice of W in the square root algorithm.
pub static SQRT_W: u32 = 8;
Expand Down
77 changes: 77 additions & 0 deletions src/ark_curve/edwards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use ark_ec::{
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
CurveConfig,
};

use crate::ark_curve::constants::{GENERATOR_X, GENERATOR_Y};
use crate::{Fq, Fr};

#[derive(Clone, Default, PartialEq, Eq)]
pub struct Decaf377EdwardsConfig;

// These types should not be exported. They are similar to `EdwardsAffine` and
// `EdwardsProjective` from the `ark_ed_on_bls12_377` crate, except using our own
// `Decaf377Config` that has the cofactor set to 1. Consumers of this
// library should use the `AffinePoint` and `Element` (projective)
// types.
pub type EdwardsAffine = Affine<Decaf377EdwardsConfig>;
pub type EdwardsProjective = Projective<Decaf377EdwardsConfig>;

impl CurveConfig for Decaf377EdwardsConfig {
type BaseField = Fq;
type ScalarField = Fr;

const COFACTOR: &'static [u64] = &[1];

const COFACTOR_INV: Fr = Fr::one();
}

impl TECurveConfig for Decaf377EdwardsConfig {
/// COEFF_A = -1
const COEFF_A: Fq = Fq::from_montgomery_limbs_64([
10157024534604021774,
16668528035959406606,
5322190058819395602,
387181115924875961,
]);

/// COEFF_D = 3021
const COEFF_D: Fq = Fq::from_montgomery_limbs_64([
15008245758212136496,
17341409599856531410,
648869460136961410,
719771289660577536,
]);

const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y);

type MontCurveConfig = Decaf377EdwardsConfig;

/// Multiplication by `a` is just negation.
#[inline(always)]
fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
-elem
}

fn is_in_correct_subgroup_assuming_on_curve(_: &Affine<Self>) -> bool {
true
}
}

impl MontCurveConfig for Decaf377EdwardsConfig {
const COEFF_A: Fq = Fq::from_montgomery_limbs_64([
13800168384327121454,
6841573379969807446,
12529593083398462246,
853978956621483129,
]);

const COEFF_B: Fq = Fq::from_montgomery_limbs_64([
7239382437352637935,
14509846070439283655,
5083066350480839936,
1265663645916442191,
]);

type TECurveConfig = Decaf377EdwardsConfig;
}
111 changes: 19 additions & 92 deletions src/element.rs → src/ark_curve/element.rs
Original file line number Diff line number Diff line change
@@ -1,99 +1,26 @@
use ark_ec::{
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
AffineRepr, CurveConfig, CurveGroup, Group, ScalarMul, VariableBaseMSM,
};
use ark_ec::{AffineRepr, CurveGroup, Group, ScalarMul, VariableBaseMSM};
use ark_serialize::Valid;
use ark_std::vec::Vec;

use crate::{
constants::{GENERATOR_X, GENERATOR_Y},
ark_curve::{edwards::EdwardsAffine, Decaf377EdwardsConfig, EdwardsProjective},
Fq, Fr,
};

pub mod affine;
pub mod projective;

pub use affine::AffineElement;
pub use affine::AffinePoint;
pub use projective::Element;

#[derive(Clone, Default, PartialEq, Eq)]
pub struct Decaf377EdwardsConfig;

// These types should not be exported. They are similar to `EdwardsAffine` and
// `EdwardsProjective` from the `ark_ed_on_bls12_377` crate, except using our own
// `Decaf377Config` that has the cofactor set to 1. Consumers of this
// library should use the `AffineElement` and `Element` (projective)
// types.
pub(crate) type EdwardsAffine = Affine<Decaf377EdwardsConfig>;
pub(crate) type EdwardsProjective = Projective<Decaf377EdwardsConfig>;

impl CurveConfig for Decaf377EdwardsConfig {
type BaseField = Fq;
type ScalarField = Fr;

const COFACTOR: &'static [u64] = &[1];

const COFACTOR_INV: Fr = Fr::one();
}

impl TECurveConfig for Decaf377EdwardsConfig {
/// COEFF_A = -1
const COEFF_A: Fq = Fq::from_montgomery_limbs_64([
10157024534604021774,
16668528035959406606,
5322190058819395602,
387181115924875961,
]);

/// COEFF_D = 3021
const COEFF_D: Fq = Fq::from_montgomery_limbs_64([
15008245758212136496,
17341409599856531410,
648869460136961410,
719771289660577536,
]);

const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y);

type MontCurveConfig = Decaf377EdwardsConfig;

/// Multiplication by `a` is just negation.
#[inline(always)]
fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
-elem
}

fn is_in_correct_subgroup_assuming_on_curve(_: &Affine<Self>) -> bool {
true
}
}

impl MontCurveConfig for Decaf377EdwardsConfig {
const COEFF_A: Fq = Fq::from_montgomery_limbs_64([
13800168384327121454,
6841573379969807446,
12529593083398462246,
853978956621483129,
]);

const COEFF_B: Fq = Fq::from_montgomery_limbs_64([
7239382437352637935,
14509846070439283655,
5083066350480839936,
1265663645916442191,
]);

type TECurveConfig = Decaf377EdwardsConfig;
}

impl Valid for Element {
fn check(&self) -> Result<(), ark_serialize::SerializationError> {
Ok(())
}
}

impl ScalarMul for Element {
type MulBase = AffineElement;
type MulBase = AffinePoint;

const NEGATION_IS_CHEAP: bool = true;

Expand All @@ -102,7 +29,7 @@ impl ScalarMul for Element {
let result = EdwardsProjective::batch_convert_to_mul_base(&bases_inner[..]);
result
.into_iter()
.map(|g| AffineElement { inner: g })
.map(|g| AffinePoint { inner: g })
.collect::<Vec<_>>()
}
}
Expand Down Expand Up @@ -137,19 +64,19 @@ impl CurveGroup for Element {

type BaseField = Fq;

type Affine = AffineElement;
type Affine = AffinePoint;

// This type is supposed to represent an element of the entire elliptic
// curve group, not just the prime-order subgroup. Since this is decaf,
// this is just an `Element` again.
type FullGroup = AffineElement;
type FullGroup = AffinePoint;

fn normalize_batch(v: &[Self]) -> Vec<AffineElement> {
fn normalize_batch(v: &[Self]) -> Vec<AffinePoint> {
let v_inner = v.iter().map(|g| g.inner).collect::<Vec<_>>();
let result = EdwardsProjective::normalize_batch(&v_inner[..]);
result
.into_iter()
.map(|g| AffineElement { inner: g })
.map(|g| AffinePoint { inner: g })
.collect::<Vec<_>>()
}

Expand All @@ -158,13 +85,13 @@ impl CurveGroup for Element {
}
}

impl Valid for AffineElement {
impl Valid for AffinePoint {
fn check(&self) -> Result<(), ark_serialize::SerializationError> {
Ok(())
}
}

impl AffineRepr for AffineElement {
impl AffineRepr for AffinePoint {
type Config = Decaf377EdwardsConfig;

type ScalarField = Fr;
Expand All @@ -178,7 +105,7 @@ impl AffineRepr for AffineElement {
}

fn zero() -> Self {
AffineElement {
AffinePoint {
inner: EdwardsAffine::zero(),
}
}
Expand All @@ -188,7 +115,7 @@ impl AffineRepr for AffineElement {
}

fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
EdwardsAffine::from_random_bytes(bytes).map(|inner| AffineElement { inner })
EdwardsAffine::from_random_bytes(bytes).map(|inner| AffinePoint { inner })
}

fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self::Group {
Expand All @@ -207,32 +134,32 @@ impl AffineRepr for AffineElement {
}
}

impl From<Element> for AffineElement {
impl From<Element> for AffinePoint {
fn from(point: Element) -> Self {
Self {
inner: point.inner.into(),
}
}
}

impl From<AffineElement> for Element {
fn from(point: AffineElement) -> Self {
impl From<AffinePoint> for Element {
fn from(point: AffinePoint) -> Self {
Self {
inner: point.inner.into(),
}
}
}

impl From<&Element> for AffineElement {
impl From<&Element> for AffinePoint {
fn from(point: &Element) -> Self {
Self {
inner: point.inner.into(),
}
}
}

impl From<&AffineElement> for Element {
fn from(point: &AffineElement) -> Self {
impl From<&AffinePoint> for Element {
fn from(point: &AffinePoint) -> Self {
Self {
inner: point.inner.into(),
}
Expand Down
Loading
Loading