16 Commits

Author SHA1 Message Date
Michele Orrù
e2d16a27e2 Update README.md (#189) 2023-12-18 09:24:04 -08:00
Pratyush Mishra
7854883b47 Add archival notice to README (#188) 2023-12-18 08:56:41 -08:00
Davide Galassi
ccf83923f8 Expose Bandersnatch generators (#184) 2023-10-14 17:44:58 +02:00
Andrew Z
0a64024ebc Fix #178: Make MNT{4,6}-753, cp6_782 tests run conditionally (#179) 2023-09-25 11:28:26 -07:00
Pratyush Mishra
8c0256ac9c Fix comments for Grumpkin curve generator (#175)
Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
2023-09-19 04:47:35 -07:00
mmagician
72a18b6ecf GLV implementation for BLS12_377, BLS12_381 and BN254 (#158) 2023-09-11 17:29:38 -04:00
mmagician
8765798eb0 The scalar to be multiplied by should be at most num_limbs long (#171)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-11 12:44:41 -07:00
mmagician
7e4b4bf027 Non-canonical infinity point & bad flags in BLS12-381 serialization should fail (#176)
Co-authored-by: Kevaundray Wedderburn <kevtheappdev@gmail.com>
2023-09-11 12:21:37 -07:00
Carlos Pérez
4d1e504025 Add Grumpkin support for arkworks (#174)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-07 05:15:36 -07:00
Weikeng Chen
fc8379d9ed Add the small subgroup power for BN254 (#163)
Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-05 05:39:34 -07:00
mmagician
a0bd36f781 Revert "temp switch to bw6-optimization branch on algebra" (#172) 2023-09-04 11:38:00 -04:00
mmagician
1ce1fcf70f Bw6-761 optimized Miller loop (#155) 2023-09-03 09:38:44 -04:00
mmagician
379f23070c Use BigInt macro for defining curve config parameters (#170) 2023-09-01 09:43:12 -07:00
swasilyev
7e58260618 Add BW6-767 curve and update BW6-761 to use the new bw6 model (#156)
* Rework bw6-761 to bw6-767

use bls12-381 instead of 377 for test imports

fix the inline comments with correct name and params


Set the right base field


Equation for base curve is y2 = x3 + 1


fill in pairing params


adapt sage scripts with correct moduli


calculate the correct cubic non residue


correct the parameter B in the curve equation


remove the specialized method for mult by nonresidue

nonresidue is two, so default will be doubling

calculate more correct parameters for fq3

`TRACE_MINUS_ONE_DIV_TWO` and `QUADRATIC_NONRESIDUE_TO_T`

compute the right fq3 & fp6 frobenious coefficients


calculate the cofactor for g1


use the g1 generator from gnark's fork


use the right g2 equation


g2 cofactor is slightly smaller than g1 cofactor


get the g2 generators from gnark's fork


update g1 and g2 curve info in the comments


fill in `COFACTOR_INV` value for g1


fill in `COFACTOR_INV` value for g2

* update module description

author information
2-adicity of the scalar field

* update changelog

* remove trailing comma

* remove todo

* 2nd loop count is x^3 - x^2 - x

* Revert "2nd loop count is x^3 - x^2 - x"

This reverts commit 2b323db3baff06a6077fd7505ff489fa31be7282.

* fix comment regarding non-residue

* first loop count should be X

* 1. Generic BW6 params added to BW6-761
2. Curve specific hard part of the final exp moved from algebra

* 1. Generic BW6 params added to BW6-767
2. Miller loop params changed to the "unoptimized" version

* cargo fmt

* changelog updated

* X_MINUS_1_DIV_3 added to BW6Config

* imports fixed

---------

Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
2023-09-01 10:06:45 +02:00
Chris Sosnin
3fded1fbcc patch dependencies and fix imports (#167)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-08-19 13:13:13 -07:00
Hossein Moghaddas
32b487e7fd Adding AdditiveGroup and PrimeGroup (#159)
Co-authored-by: Michele Orrù <michele.orru@berkeley.edu>
Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-08-19 12:09:04 -07:00
85 changed files with 1589 additions and 194 deletions

View File

@@ -50,7 +50,7 @@ jobs:
toolchain: ${{ matrix.rust }} toolchain: ${{ matrix.rust }}
override: true override: true
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -104,6 +104,7 @@ jobs:
- dir: curve-constraint-tests/ - dir: curve-constraint-tests/
- dir: mnt4_753/ - dir: mnt4_753/
- dir: mnt6_753/ - dir: mnt6_753/
- dir: cp6_782/
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -115,11 +116,34 @@ jobs:
test-mnt4-753: test-mnt4-753:
name: Test (mnt4_753/) name: Test (mnt4_753/)
runs-on: macos-latest runs-on: macos-latest
needs: [directories] # Waits for the directory listing job
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Run tests
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
filters: |
mnt4_753_is_updated:
- 'mnt4_753/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.mnt4_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: | run: |
cd mnt4_753/ cd mnt4_753/
cargo test --all-features cargo test --all-features
@@ -127,15 +151,74 @@ jobs:
test-mnt6-753: test-mnt6-753:
name: Test (mnt6_753/) name: Test (mnt6_753/)
runs-on: macos-latest runs-on: macos-latest
needs: [directories] # Waits for the directory listing job
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Run tests
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
filters: |
mnt6_753_is_updated:
- 'mnt6_753/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.mnt6_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: | run: |
cd mnt6_753/ cd mnt6_753/
cargo test --all-features cargo test --all-features
test-cp6_782:
name: Test (cp6_782/)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
filters: |
cp6_782_is_updated:
- 'cp6_782/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.cp6_782_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: |
cd cp6_782/
cargo test --all-features
docs: docs:
name: Check Documentation name: Check Documentation
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -164,14 +247,14 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install Rust (${{ matrix.rust }}) - name: Install Rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: stable toolchain: stable
target: aarch64-unknown-none target: thumbv6m-none-eabi
override: true override: true
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -183,10 +266,10 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: check command: check
args: --examples --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none args: --examples --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi
- name: build - name: build
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: build command: build
args: --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none args: --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi

View File

@@ -6,10 +6,19 @@
### Features ### Features
- [\#156](https://github.com/arkworks-rs/curves/pull/156) Add the bw6-767 curve.
- [\#174](https://github.com/arkworks-rs/curves/pull/174) Add the "grumpkin" curve.
### Improvements ### Improvements
- [\#156](https://github.com/arkworks-rs/curves/pull/156) The hard part of the final exponentiation for bw6-761 relocated from arkworks/algebra.
- [\#158](https://github.com/arkworks-rs/curves/pull/158) Enabled GLV as the default scalar multiplication for BLS12-377, BLS12-381 and BN254.
### Bugfixes ### Bugfixes
- [\#176](https://github.com/arkworks-rs/curves/pull/176) Non-canonical infinity point and bad flags in BLS12-381 serialization should fail.
## v0.4.0 ## v0.4.0
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377 - [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
- Fixed curve benches - Fixed curve benches

View File

@@ -9,6 +9,8 @@ members = [
"bw6_761", "bw6_761",
"ed_on_bw6_761", "ed_on_bw6_761",
"bw6_767",
"cp6_782", "cp6_782",
"ed_on_cp6_782", "ed_on_cp6_782",
@@ -18,6 +20,7 @@ members = [
"bn254", "bn254",
"ed_on_bn254", "ed_on_bn254",
"grumpkin",
"mnt4_298", "mnt4_298",
"mnt6_298", "mnt6_298",
@@ -71,4 +74,5 @@ ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" } ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" } ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra/" } ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra/" }
ark-algebra-bench-templates = { git = "https://github.com/arkworks-rs/algebra/" }
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" } ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }

View File

@@ -1,4 +1,8 @@
# Curve implementations # Notice
This repository is no longer maintained, and PRs to add or modify curves should instead be made against [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra); all the curves implemented here have moved to the [`curves` folder](https://github.com/arkworks-rs/algebra/tree/master/curves) of that repository.
## Curve implementations
This repository contains implementations of some popular elliptic curves. The curve API implemented here matches the curve traits defined [here](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) in the [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra) repository. This repository contains implementations of some popular elliptic curves. The curve API implemented here matches the curve traits defined [here](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) in the [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra) repository.
@@ -20,6 +24,7 @@ This repository contains implementations of some popular elliptic curves. The cu
### BN254 and related curves ### BN254 and related curves
* [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve * [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve
* [`ark-ed-on-bn254`](ed_on_bn254): Implements a Twisted Edwards curve atop the scalar field of BN254 * [`ark-ed-on-bn254`](ed_on_bn254): Implements a Twisted Edwards curve atop the scalar field of BN254
* [`ark-grumpkin`](grumpkin): Implements the Grumpkin curve. A curve that forms a cycle with bn254.
### MNT-298 cycle of curves and related curves ### MNT-298 cycle of curves and related curves
* [`ark-mnt4-298`](mnt4_298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298 * [`ark-mnt4-298`](mnt4_298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298

View File

@@ -3,14 +3,15 @@ use ark_ec::{
bls12::Bls12Config, bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig}, hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::{ models::{
short_weierstrass::{Affine as SWAffine, SWCurveConfig}, short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig},
twisted_edwards::{ twisted_edwards::{
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig, Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
}, },
}, },
scalar_mul::glv::GLVConfig,
CurveConfig, CurveConfig,
}; };
use ark_ff::{Field, MontFp, PrimeField, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_std::{ops::Neg, One}; use ark_std::{ops::Neg, One};
use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1}; use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};
@@ -49,6 +50,12 @@ impl SWCurveConfig for Config {
Self::BaseField::zero() Self::BaseField::zero()
} }
#[inline]
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
#[inline] #[inline]
fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine { fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine {
// Using the effective cofactor. // Using the effective cofactor.
@@ -59,6 +66,34 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231")
];
const LAMBDA: Self::ScalarField =
MontFp!("8444461749428370424248824938781546531284005582649182570233710176290576793600");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(true, BigInt!("91893752504881257701523279626832445441")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(true, BigInt!("91893752504881257701523279626832445440")),
];
fn endomorphism(p: &SWProjective<Self>) -> SWProjective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &SWAffine<Self>) -> SWAffine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
fn x_minus_one() -> Fr { fn x_minus_one() -> Fr {
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X); const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
X - Fr::one() X - Fr::one()

View File

@@ -2,12 +2,12 @@ use ark_ec::{
bls12, bls12,
bls12::Bls12Config, bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig}, hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::CurveConfig, scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective, SWCurveConfig}, short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveGroup, Group, AffineRepr, CurveConfig, CurveGroup, PrimeGroup,
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_std::ops::Neg; use ark_std::ops::Neg;
use crate::*; use crate::*;
@@ -98,6 +98,36 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO
)
];
const LAMBDA: Self::ScalarField = MontFp!("91893752504881257701523279626832445440");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("91893752504881257701523279626832445440")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(false, BigInt!("91893752504881257701523279626832445441")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);

View File

@@ -5,6 +5,8 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
test_pairing!(pairing; crate::Bls12_377); test_pairing!(pairing; crate::Bls12_377);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1); test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2); test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);

View File

@@ -1,5 +1,4 @@
use ark_algebra_bench_templates::*; use ark_algebra_bench_templates::*;
use ark_bls12_381::{ use ark_bls12_381::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2, fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
}; };

View File

@@ -3,10 +3,11 @@ use ark_ec::{
bls12::Bls12Config, bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig}, hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::CurveConfig, models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, SWCurveConfig}, short_weierstrass::{Affine, SWCurveConfig},
AffineRepr, Group, AffineRepr, PrimeGroup,
}; };
use ark_ff::{Field, MontFp, PrimeField, Zero}; use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
use ark_serialize::{Compress, SerializationError}; use ark_serialize::{Compress, SerializationError};
use ark_std::{ops::Neg, One}; use ark_std::{ops::Neg, One};
@@ -52,6 +53,12 @@ impl SWCurveConfig for Config {
Self::BaseField::zero() Self::BaseField::zero()
} }
#[inline]
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
#[inline] #[inline]
fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool { fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
// Algorithm from Section 6 of https://eprint.iacr.org/2021/1130. // Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
@@ -142,6 +149,34 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350")
];
const LAMBDA: Self::ScalarField =
MontFp!("52435875175126190479447740508185965837461563690374988244538805122978187051009");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(true, BigInt!("228988810152649578064853576960394133504")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(true, BigInt!("228988810152649578064853576960394133503")),
];
fn endomorphism(p: &G1Projective) -> G1Projective {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
fn one_minus_x() -> Fr { fn one_minus_x() -> Fr {
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X); const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
Fr::one() - X Fr::one() - X
@@ -180,6 +215,7 @@ mod test {
use super::*; use super::*;
use crate::g1; use crate::g1;
use ark_serialize::CanonicalDeserialize;
use ark_std::{rand::Rng, UniformRand}; use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> Affine<g1::Config> { fn sample_unchecked() -> Affine<g1::Config> {
@@ -204,4 +240,55 @@ mod test {
assert!(p.is_in_correct_subgroup_assuming_on_curve()); assert!(p.is_in_correct_subgroup_assuming_on_curve());
} }
} }
#[test]
fn non_canonical_identity_point() {
let non_canonical_hex = "c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
let non_canonical_hex_uncompressed = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
let non_canonical_bytes = hex::decode(non_canonical_hex_uncompressed).unwrap();
assert_eq!(non_canonical_bytes.len(), 96);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_uncompressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err())
}
#[test]
fn bad_flag_combination() {
// See https://github.com/zkcrypto/pairing/tree/fa8103764a07bd273927447d434de18aace252d3/src/bls12_381#serialization
// - Bit 1 is compressed/uncompressed
// - Bit 2 is infinity
// - Bit 3 is lexicographical order for compressed point deserialization
// Hence `0b1110` ("e" in hex) or `0b0110` ("6" in hex") are both nonsensical.
// uncompressed, but lexicographically largest flag is set
let non_canonical_hex = "600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
// compressed, but infinity flag is set and lexicographically largest flag is
// set
let non_canonical_hex_2 = "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex_2).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
}
} }

View File

@@ -5,10 +5,11 @@ use ark_ec::{
bls12::Bls12Config, bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig}, hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::CurveConfig, models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective, SWCurveConfig}, short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveGroup, Group, AffineRepr, CurveGroup, PrimeGroup,
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_serialize::{Compress, SerializationError}; use ark_serialize::{Compress, SerializationError};
use super::{ use super::{
@@ -185,6 +186,36 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq::ZERO
)
];
const LAMBDA: Self::ScalarField = MontFp!("228988810152649578064853576960394133503");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("228988810152649578064853576960394133503")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(false, BigInt!("228988810152649578064853576960394133504")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);

View File

@@ -1,5 +1,5 @@
use ark_algebra_test_templates::*; use ark_algebra_test_templates::*;
use ark_ec::{AffineRepr, CurveGroup, Group}; use ark_ec::{AffineRepr, CurveGroup, PrimeGroup};
use ark_ff::{fields::Field, One, UniformRand, Zero}; use ark_ff::{fields::Field, One, UniformRand, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
use ark_std::{rand::Rng, test_rng, vec}; use ark_std::{rand::Rng, test_rng, vec};
@@ -8,6 +8,8 @@ use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projecti
test_group!(g1; G1Projective; sw); test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(g2; G2Projective; sw);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm);
test_pairing!(pairing; crate::Bls12_381); test_pairing!(pairing; crate::Bls12_381);
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1); test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);

View File

@@ -14,17 +14,28 @@ pub struct EncodingFlags {
} }
impl EncodingFlags { impl EncodingFlags {
pub fn get_flags(bytes: &[u8]) -> Self { /// Fetches the flags from the byte-string
pub fn get_flags(bytes: &[u8]) -> Result<Self, SerializationError> {
let compression_flag_set = (bytes[0] >> 7) & 1; let compression_flag_set = (bytes[0] >> 7) & 1;
let infinity_flag_set = (bytes[0] >> 6) & 1; let infinity_flag_set = (bytes[0] >> 6) & 1;
let sort_flag_set = (bytes[0] >> 5) & 1; let sort_flag_set = (bytes[0] >> 5) & 1;
Self { let is_compressed = compression_flag_set == 1;
is_compressed: compression_flag_set == 1, let is_infinity = infinity_flag_set == 1;
is_infinity: infinity_flag_set == 1, let is_lexographically_largest = sort_flag_set == 1;
is_lexographically_largest: sort_flag_set == 1,
if is_lexographically_largest && (!is_compressed || is_infinity) {
return Err(SerializationError::InvalidData);
} }
Ok(Self {
is_compressed,
is_infinity,
is_lexographically_largest,
})
} }
/// Encodes the flags into the byte-string
pub fn encode_flags(&self, bytes: &mut [u8]) { pub fn encode_flags(&self, bytes: &mut [u8]) {
if self.is_compressed { if self.is_compressed {
bytes[0] |= 1 << 7; bytes[0] |= 1 << 7;
@@ -38,6 +49,13 @@ impl EncodingFlags {
bytes[0] |= 1 << 5; bytes[0] |= 1 << 5;
} }
} }
/// Removes the flags from the byte-string.
///
/// This reverses the effects of `encode_flags`.
pub fn remove_flags(bytes: &mut [u8]) {
bytes[0] &= 0b0001_1111;
}
} }
pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> { pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> {
@@ -71,20 +89,15 @@ pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] {
result result
} }
pub(crate) fn read_fq_with_offset( fn read_bytes_with_offset(bytes: &[u8], offset: usize, mask: bool) -> [u8; G1_SERIALIZED_SIZE] {
bytes: &[u8],
offset: usize,
mask: bool,
) -> Result<Fq, ark_serialize::SerializationError> {
let mut tmp = [0; G1_SERIALIZED_SIZE]; let mut tmp = [0; G1_SERIALIZED_SIZE];
// read `G1_SERIALIZED_SIZE` bytes // read `G1_SERIALIZED_SIZE` bytes
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]); tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
if mask { if mask {
// Mask away the flag bits EncodingFlags::remove_flags(&mut tmp);
tmp[0] &= 0b0001_1111;
} }
deserialize_fq(tmp).ok_or(SerializationError::InvalidData) tmp
} }
pub(crate) fn read_g1_compressed<R: ark_serialize::Read>( pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
@@ -97,20 +110,26 @@ pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
.ok_or(SerializationError::InvalidData)?; .ok_or(SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence // Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..]); let flags = EncodingFlags::get_flags(&bytes[..])?;
// we expect to be deserializing a compressed point // We expect to be deserializing a compressed point
if !flags.is_compressed { if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags); return Err(SerializationError::UnexpectedFlags);
} }
// Attempt to obtain the x-coordinate
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
if flags.is_infinity { if flags.is_infinity {
// Check that the `x` co-ordinate was `0`
if x_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G1Affine::zero()); return Ok(G1Affine::zero());
} }
// Attempt to obtain the x-coordinate let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
let x = read_fq_with_offset(&bytes, 0, true)?;
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest) let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
.ok_or(SerializationError::InvalidData)?; .ok_or(SerializationError::InvalidData)?;
@@ -126,22 +145,27 @@ pub(crate) fn read_g1_uncompressed<R: ark_serialize::Read>(
.map_err(|_| SerializationError::InvalidData)?; .map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence // Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..]); let flags = EncodingFlags::get_flags(&bytes[..])?;
// we expect to be deserializing an uncompressed point // we expect to be deserializing an uncompressed point
if flags.is_compressed { if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags); return Err(SerializationError::UnexpectedFlags);
} }
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
let y_bytes = read_bytes_with_offset(&bytes, 1, false);
if flags.is_infinity { if flags.is_infinity {
if x_bytes != [0u8; 48] || y_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G1Affine::zero()); return Ok(G1Affine::zero());
} }
// Attempt to obtain the x-coordinate // Attempt to obtain the x-coordinate
let x = read_fq_with_offset(&bytes, 0, true)?; let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
// Attempt to obtain the y-coordinate // Attempt to obtain the y-coordinate
let y = read_fq_with_offset(&bytes, 1, false)?; let y = deserialize_fq(y_bytes).ok_or(SerializationError::InvalidData)?;
let p = G1Affine::new_unchecked(x, y); let p = G1Affine::new_unchecked(x, y);
Ok(p) Ok(p)
@@ -156,21 +180,26 @@ pub(crate) fn read_g2_compressed<R: ark_serialize::Read>(
.map_err(|_| SerializationError::InvalidData)?; .map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence // Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes); let flags = EncodingFlags::get_flags(&bytes)?;
// we expect to be deserializing a compressed point // we expect to be deserializing a compressed point
if !flags.is_compressed { if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags); return Err(SerializationError::UnexpectedFlags);
} }
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
if flags.is_infinity { if flags.is_infinity {
if xc1_bytes != [0u8; 48] || xc0_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G2Affine::zero()); return Ok(G2Affine::zero());
} }
// Attempt to obtain the x-coordinate // Attempt to obtain the x-coordinate
let xc1 = read_fq_with_offset(&bytes, 0, true)?; let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
let xc0 = read_fq_with_offset(&bytes, 1, false)?; let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
let x = Fq2::new(xc0, xc1); let x = Fq2::new(xc0, xc1);
let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest) let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
@@ -188,25 +217,39 @@ pub(crate) fn read_g2_uncompressed<R: ark_serialize::Read>(
.map_err(|_| SerializationError::InvalidData)?; .map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence // Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes); let flags = EncodingFlags::get_flags(&bytes)?;
// we expect to be deserializing an uncompressed point // we expect to be deserializing an uncompressed point
if flags.is_compressed { if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags); return Err(SerializationError::UnexpectedFlags);
} }
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
let yc1_bytes = read_bytes_with_offset(&bytes, 2, false);
let yc0_bytes = read_bytes_with_offset(&bytes, 3, false);
if flags.is_infinity { if flags.is_infinity {
if xc1_bytes != [0u8; 48]
|| xc0_bytes != [0u8; 48]
|| yc1_bytes != [0u8; 48]
|| yc0_bytes != [0u8; 48]
{
return Err(SerializationError::InvalidData);
}
return Ok(G2Affine::zero()); return Ok(G2Affine::zero());
} }
let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
let yc1 = deserialize_fq(yc1_bytes).ok_or(SerializationError::InvalidData)?;
let yc0 = deserialize_fq(yc0_bytes).ok_or(SerializationError::InvalidData)?;
// Attempt to obtain the x-coordinate // Attempt to obtain the x-coordinate
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
let x = Fq2::new(xc0, xc1); let x = Fq2::new(xc0, xc1);
// Attempt to obtain the y-coordinate // Attempt to obtain the y-coordinate
let yc1 = read_fq_with_offset(&bytes, 2, false)?;
let yc0 = read_fq_with_offset(&bytes, 3, false)?;
let y = Fq2::new(yc0, yc1); let y = Fq2::new(yc0, yc1);
let p = G2Affine::new_unchecked(x, y); let p = G2Affine::new_unchecked(x, y);

View File

@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
use ark_ff::{ use ark_ff::{
biginteger::{BigInt, BigInteger, BigInteger384}, biginteger::{BigInt, BigInteger, BigInteger384},
fields::{FftField, Field, Fp12Config, Fp2Config, Fp6Config, PrimeField}, fields::{FftField, Field, Fp12Config, Fp2Config, Fp6Config, PrimeField},
One, UniformRand, Zero, AdditiveGroup, One, UniformRand, Zero,
}; };
use ark_std::{ use ark_std::{
cmp::Ordering, cmp::Ordering,

View File

@@ -1,8 +1,10 @@
use ark_ec::{ use ark_ec::{
bn,
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::Affine, scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
@@ -36,6 +38,42 @@ impl SWCurveConfig for Config {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
#[inline]
fn mul_projective(
p: &bn::G1Projective<crate::Config>,
scalar: &[u64],
) -> bn::G1Projective<crate::Config> {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
)];
const LAMBDA: Self::ScalarField =
MontFp!("21888242871839275217838484774961031246154997185409878258781734729429964517155");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("147946756881789319000765030803803410728")),
(true, BigInt!("9931322734385697763")),
(false, BigInt!("9931322734385697763")),
(false, BigInt!("147946756881789319010696353538189108491")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
} }
/// G1_GENERATOR_X = 1 /// G1_GENERATOR_X = 1

View File

@@ -1,8 +1,9 @@
use ark_ec::{ use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::Affine, scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
use crate::{Fq, Fq2, Fr}; use crate::{Fq, Fq2, Fr};
@@ -50,6 +51,35 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[Fq2::new(
MontFp!("21888242871839275220042445260109153167277707414472061641714758635765020556616"),
Fq::ZERO,
)];
const LAMBDA: Self::ScalarField =
MontFp!("4407920970296243842393367215006156084916469457145843978461");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("147946756881789319010696353538189108491")),
(false, BigInt!("9931322734385697763")),
(true, BigInt!("9931322734385697763")),
(false, BigInt!("147946756881789319000765030803803410728")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);

View File

@@ -7,3 +7,5 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
test_pairing!(pairing; crate::Bn254); test_pairing!(pairing; crate::Bn254);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);

View File

@@ -3,5 +3,7 @@ use ark_ff::fields::{Fp256, MontBackend, MontConfig};
#[derive(MontConfig)] #[derive(MontConfig)]
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"] #[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
#[generator = "5"] #[generator = "5"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "2"]
pub struct FrConfig; pub struct FrConfig;
pub type Fr = Fp256<MontBackend<FrConfig, 4>>; pub type Fr = Fp256<MontBackend<FrConfig, 4>>;

View File

@@ -1,8 +1,9 @@
use ark_ec::{ use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective}, short_weierstrass::{Affine, Projective},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
@@ -49,6 +50,46 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"
)];
const LAMBDA: Self::ScalarField =
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(
true,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
false,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
true,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
true,
BigInt!("587269870971281361444171168277668240640243801025419411456"),
),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G1_GENERATOR_X = /// G1_GENERATOR_X =
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237 /// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237"); pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");

View File

@@ -1,8 +1,9 @@
use ark_ec::{ use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective}, short_weierstrass::{Affine, Projective},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
@@ -50,6 +51,46 @@ impl SWCurveConfig for Config {
} }
} }
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
];
const LAMBDA: Self::ScalarField =
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(
true,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
false,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
true,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
true,
BigInt!("587269870971281361444171168277668240640243801025419411456"),
),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G2_GENERATOR_X = /// G2_GENERATOR_X =
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428 /// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428"); pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");

View File

@@ -2,7 +2,9 @@ use ark_ec::{
bw6, bw6,
bw6::{BW6Config, TwistType, BW6}, bw6::{BW6Config, TwistType, BW6},
}; };
use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt}; use ark_ff::{
biginteger::BigInteger768 as BigInteger, fp6_2over3::Fp6, BigInt, CyclotomicMultSubgroup, Field,
};
use crate::*; use crate::*;
@@ -16,42 +18,141 @@ mod tests;
pub struct Config; pub struct Config;
impl BW6Config for Config { impl BW6Config for Config {
const X: BigInteger = BigInt::new([ const X: BigInteger = BigInt!("0x8508c00000000001");
0x8508c00000000001,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
]);
/// `x` is positive. /// `x` is positive.
const X_IS_NEGATIVE: bool = false; const X_IS_NEGATIVE: bool = false;
// X
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000001];
// (X-1)/3
const X_MINUS_1_DIV_3: BigInteger = BigInt!("0x2c58400000000000");
// X+1 // X+1
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002];
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false; const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false;
// X^3-X^2-X // X^2-X-1
const ATE_LOOP_COUNT_2: &'static [i8] = &[ const ATE_LOOP_COUNT_2: &'static [i8] = &[
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1,
1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 1, 0, 0, 0, 1,
0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
]; ];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false; const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::M; const TWIST_TYPE: TwistType = TwistType::M;
const H_T: i64 = 13;
const H_Y: i64 = 9;
const T_MOD_R_IS_ZERO: bool = false;
type Fp = Fq; type Fp = Fq;
type Fp3Config = Fq3Config; type Fp3Config = Fq3Config;
type Fp6Config = Fq6Config; type Fp6Config = Fq6Config;
type G1Config = g1::Config; type G1Config = g1::Config;
type G2Config = g2::Config; type G2Config = g2::Config;
fn final_exponentiation_hard_part(f: &Fp6<Self::Fp6Config>) -> Fp6<Self::Fp6Config> {
// hard_part
// From https://eprint.iacr.org/2020/351.pdf, Alg.6
#[rustfmt::skip]
// R0(x) := (-103*x^7 + 70*x^6 + 269*x^5 - 197*x^4 - 314*x^3 - 73*x^2 - 263*x - 220)
// R1(x) := (103*x^9 - 276*x^8 + 77*x^7 + 492*x^6 - 445*x^5 - 65*x^4 + 452*x^3 - 181*x^2 + 34*x + 229)
// f ^ R0(u) * (f ^ q) ^ R1(u) in a 2-NAF multi-exp fashion.
// steps 1,2,3
let f0 = *f;
let mut f0p = f0;
f0p.frobenius_map_in_place(1);
let f1 = Self::exp_by_x(&f0);
let mut f1p = f1;
f1p.frobenius_map_in_place(1);
let f2 = Self::exp_by_x(&f1);
let mut f2p = f2;
f2p.frobenius_map_in_place(1);
let f3 = Self::exp_by_x(&f2);
let mut f3p = f3;
f3p.frobenius_map_in_place(1);
let f4 = Self::exp_by_x(&f3);
let mut f4p = f4;
f4p.frobenius_map_in_place(1);
let f5 = Self::exp_by_x(&f4);
let mut f5p = f5;
f5p.frobenius_map_in_place(1);
let f6 = Self::exp_by_x(&f5);
let mut f6p = f6;
f6p.frobenius_map_in_place(1);
let f7 = Self::exp_by_x(&f6);
let mut f7p = f7;
f7p.frobenius_map_in_place(1);
// step 4
let f8p = Self::exp_by_x(&f7p);
let f9p = Self::exp_by_x(&f8p);
// step 5
let mut f5p_p3 = f5p;
f5p_p3.cyclotomic_inverse_in_place();
let result1 = f3p * &f6p * &f5p_p3;
// step 6
let result2 = result1.square();
let f4_2p = f4 * &f2p;
let mut tmp1_p3 = f0 * &f1 * &f3 * &f4_2p * &f8p;
tmp1_p3.cyclotomic_inverse_in_place();
let result3 = result2 * &f5 * &f0p * &tmp1_p3;
// step 7
let result4 = result3.square();
let mut f7_p3 = f7;
f7_p3.cyclotomic_inverse_in_place();
let result5 = result4 * &f9p * &f7_p3;
// step 8
let result6 = result5.square();
let f2_4p = f2 * &f4p;
let f4_2p_5p = f4_2p * &f5p;
let mut tmp2_p3 = f2_4p * &f3 * &f3p;
tmp2_p3.cyclotomic_inverse_in_place();
let result7 = result6 * &f4_2p_5p * &f6 * &f7p * &tmp2_p3;
// step 9
let result8 = result7.square();
let mut tmp3_p3 = f0p * &f9p;
tmp3_p3.cyclotomic_inverse_in_place();
let result9 = result8 * &f0 * &f7 * &f1p * &tmp3_p3;
// step 10
let result10 = result9.square();
let f6p_8p = f6p * &f8p;
let f5_7p = f5 * &f7p;
let mut tmp4_p3 = f6p_8p;
tmp4_p3.cyclotomic_inverse_in_place();
let result11 = result10 * &f5_7p * &f2p * &tmp4_p3;
// step 11
let result12 = result11.square();
let f3_6 = f3 * &f6;
let f1_7 = f1 * &f7;
let mut tmp5_p3 = f1_7 * &f2;
tmp5_p3.cyclotomic_inverse_in_place();
let result13 = result12 * &f3_6 * &f9p * &tmp5_p3;
// step 12
let result14 = result13.square();
let mut tmp6_p3 = f4_2p * &f5_7p * &f6p_8p;
tmp6_p3.cyclotomic_inverse_in_place();
let result15 = result14 * &f0 * &f0p * &f3p * &f5p * &tmp6_p3;
// step 13
let result16 = result15.square();
let mut tmp7_p3 = f3_6;
tmp7_p3.cyclotomic_inverse_in_place();
let result17 = result16 * &f1p * &tmp7_p3;
// step 14
let result18 = result17.square();
let mut tmp8_p3 = f2_4p * &f4_2p_5p * &f9p;
tmp8_p3.cyclotomic_inverse_in_place();
let result19 = result18 * &f1_7 * &f5_7p * &f0p * &tmp8_p3;
result19
}
} }
pub type BW6_761 = BW6<Config>; pub type BW6_761 = BW6<Config>;

View File

@@ -6,3 +6,5 @@ test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw); test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm); test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
test_pairing!(pairing; crate::BW6_761); test_pairing!(pairing; crate::BW6_761);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp3::{Fp3, Fp3Config}, fields::fp3::{Fp3, Fp3Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::Fq; use crate::Fq;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config}, fields::fp6_2over3::{Fp6, Fp6Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq3, Fq3Config}; use crate::{Fq, Fq3, Fq3Config};

33
bw6_767/Cargo.toml Normal file
View File

@@ -0,0 +1,33 @@
[package]
name = "ark-bw6-767"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BW6-767 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bw6-767/"
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2021"
[dependencies]
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0", default-features = false }
ark-std = { version = "0.4.0", default-features = false }
ark-bls12-381 = { version = "0.4.0", path = "../bls12_381", default-features = false, features = [ "curve" ] }
[dev-dependencies]
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-381/std" ]
[[bench]]
name = "bw6_767"
path = "benches/bw6_767.rs"
harness = false

1
bw6_767/LICENSE-APACHE Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-APACHE

1
bw6_767/LICENSE-MIT Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-MIT

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bw6_767::{
fq::Fq, fq3::Fq3, fq6::Fq6, fr::Fr, g1::G1Projective as G1, g2::G2Projective as G2, BW6_767,
};
bench!(
Name = "BW6_767",
Pairing = BW6_767,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq3,
TargetField = Fq6,
);

View File

@@ -0,0 +1,28 @@
modulus = 496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

59
bw6_767/src/curves/g1.rs Normal file
View File

@@ -0,0 +1,59 @@
use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fr};
pub type G1Affine = Affine<Config>;
pub type G1Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Config;
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR =
/// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934844
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x9fed0006fffaaabc,
0xfae29bffb34d7c0d,
0xc51e35fba8145036,
0x58c9927410ca3a62,
0x7772b64205a0bc67,
0x26212b5cf67cecaf,
0x3,
];
/// COFACTOR^(-1) mod r =
/// 1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812
const COFACTOR_INV: Fr = MontFp!("1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 1
const COEFF_B: Fq = MontFp!("1");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218
pub const G1_GENERATOR_X: Fq = MontFp!("127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218");
/// G1_GENERATOR_Y =
/// 415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204
pub const G1_GENERATOR_Y: Fq = MontFp!("415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204");

60
bw6_767/src/curves/g2.rs Normal file
View File

@@ -0,0 +1,60 @@
use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fr};
pub type G2Affine = Affine<Config>;
pub type G2Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Config;
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR =
/// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934833
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x9fed0006fffaaab1,
0xfae29bffb34d7c0d,
0xc51e35fba8145036,
0x58c9927410ca3a62,
0x7772b64205a0bc67,
0x26212b5cf67cecaf,
0x3,
];
/// COFACTOR^(-1) mod r =
/// 1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313
const COFACTOR_INV: Fr = MontFp!("1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 4
const COEFF_B: Fq = MontFp!("3");
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G2_GENERATOR_X =
/// 370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222
pub const G2_GENERATOR_X: Fq = MontFp!("370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222");
/// G2_GENERATOR_Y =
/// 455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603
pub const G2_GENERATOR_Y: Fq = MontFp!("455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603");

51
bw6_767/src/curves/mod.rs Normal file
View File

@@ -0,0 +1,51 @@
use ark_ec::{
bw6,
bw6::{BW6Config, TwistType, BW6},
};
use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt};
use crate::*;
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
#[derive(PartialEq, Eq)]
pub struct Config;
impl BW6Config for Config {
// X is the same as in bls12_381
const X: BigInteger = BigInt!("0xd201000000010000");
const X_IS_NEGATIVE: bool = true;
// X
const ATE_LOOP_COUNT_1: &'static [u64] = &[0xd201000000010000];
const X_MINUS_1_DIV_3: BigInteger = BigInt!("0x460055555555aaab");
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = true;
// X^2-X-1
const ATE_LOOP_COUNT_2: &'static [i8] = &[
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, -1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, -1, 0, 1, 0, 0, 1,
0, 0, 0, -1, 0, -1, 0, -1, 0, 1,
];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::M;
const H_T: i64 = -4;
const H_Y: i64 = -6;
const T_MOD_R_IS_ZERO: bool = true;
type Fp = Fq;
type Fp3Config = Fq3Config;
type Fp6Config = Fq6Config;
type G1Config = g1::Config;
type G2Config = g2::Config;
}
pub type BW6_767 = BW6<Config>;
pub type G1Affine = bw6::G1Affine<Config>;
pub type G1Projective = bw6::G1Projective<Config>;
pub type G2Affine = bw6::G2Affine<Config>;
pub type G2Projective = bw6::G2Projective<Config>;

View File

@@ -0,0 +1,8 @@
use crate::*;
use ark_algebra_test_templates::*;
use ark_ff::Field;
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_767>; msm);
test_pairing!(pairing; crate::BW6_767);

7
bw6_767/src/fields/fq.rs Normal file
View File

@@ -0,0 +1,7 @@
use ark_ff::fields::{Fp768, MontBackend, MontConfig};
#[derive(MontConfig)]
#[modulus = "496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431"]
#[generator = "3"]
pub struct FqConfig;
pub type Fq = Fp768<MontBackend<FqConfig, 12>>;

79
bw6_767/src/fields/fq3.rs Normal file
View File

@@ -0,0 +1,79 @@
use ark_ff::{
fields::fp3::{Fp3, Fp3Config},
AdditiveGroup, Field, MontFp,
};
use crate::Fq;
pub type Fq3 = Fp3<Fq3Config>;
pub struct Fq3Config;
impl Fp3Config for Fq3Config {
type Fp = Fq;
/// NONRESIDUE = 3
// Fq3 = Fq\[u\]/u^3-3
const NONRESIDUE: Fq = MontFp!("3");
// (MODULUS^3 - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// (T-1)/2 with T = (MODULUS^3-1) / 2^TWO_ADICITY
#[rustfmt::skip]
const TRACE_MINUS_ONE_DIV_TWO: &'static [u64] = &[
0x22d18a101ce54f7d,
0x354335b0e7c460e8,
0x8014efd2b7ade04d,
0x3a3c62ab52e0a2c1,
0x79ce8405b95dd2ee,
0x24f75cbd8559a2b6,
0x2519d1267e548214,
0xea0034421965f6c8,
0xbbaa92b6aca7d134,
0x9ec0892af11e70cc,
0x06e6ab40a2fd09ec,
0xd333987617c1542a,
0xdcb52167b1f0ae0f,
0xeffa098d77a86e52,
0x9fe0d744c24ed062,
0x7df249c9ef981da1,
0x01337d754cef36fa,
0xf84c4f79c259bd8b,
0x6552e19d7dc57335,
0x9f2cab11727d9c89,
0xe5cc4da17a684263,
0xaab0632027470c14,
0xb841a2fe447f48a3,
0x6e705db09cb2c6c9,
0x51d3c82bd5de018d,
0xf0bb21ffbef26bd1,
0x294ce678e6a4c0ff,
0x130ad731f57d4c85,
0xa1e367e5eb70a85b,
0xd1b2d73d567515cd,
0x0527dddbc3e9f165,
0x1d9c04e0098344e7,
0x5db616f391729475,
0xd2834b1fae1c2c1b,
0x7cf1b8c728557851,
0x218325db61d6ebd,
];
// NONRESIDUE^T % q
const QUADRATIC_NONRESIDUE_TO_T: Fq3 = Fq3::new(Fq::ONE, Fq::ZERO, Fq::ZERO);
// NQR ^ (MODULUS^i - 1)/3, i=0,1,2 with NQR = u = (0,1,0)
const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[
Fq::ONE,
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
];
// NQR ^ (2*MODULUS^i - 2)/3, i=0,1,2 with NQR = u = (0,1,0)
const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[
Fq::ONE,
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
];
}

26
bw6_767/src/fields/fq6.rs Normal file
View File

@@ -0,0 +1,26 @@
use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config},
AdditiveGroup, Field, MontFp,
};
use crate::{Fq, Fq3, Fq3Config};
pub type Fq6 = Fp6<Fq6Config>;
pub struct Fq6Config;
impl Fp6Config for Fq6Config {
type Fp3Config = Fq3Config;
/// NONRESIDUE = (0, 1, 0)
const NONRESIDUE: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO);
const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[
Fq::ONE,
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550171"),
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
MontFp!("-1"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349261"),
];
}

1
bw6_767/src/fields/fr.rs Normal file
View File

@@ -0,0 +1 @@
pub use ark_bls12_381::{Fq as Fr, FqConfig as FrConfig};

14
bw6_767/src/fields/mod.rs Normal file
View File

@@ -0,0 +1,14 @@
pub mod fr;
pub use self::fr::*;
pub mod fq;
pub use self::fq::*;
pub mod fq3;
pub use self::fq3::*;
pub mod fq6;
pub use self::fq6::*;
#[cfg(test)]
mod tests;

View File

@@ -0,0 +1,7 @@
use crate::*;
use ark_algebra_test_templates::*;
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);
test_field!(fq3; Fq3);
test_field!(fq6; Fq6);

36
bw6_767/src/lib.rs Executable file
View File

@@ -0,0 +1,36 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This module implements the BW6_767 curve generated by [\[El Housni and Guillevic\]](https://hackmd.io/@gnark/bw6_bls12381),
//! using their generic approach described in [\[HG21\]](https://eprint.iacr.org/2021/1359).
//! The name denotes that it is a curve generated using the Brezing--Weng
//! method, and that its embedding degree is 6.
//! The main feature of this curve is that the scalar field equals the base
//! field of the BLS12_381 curve.
//!
//! Curve information:
//! * Base field: q = 496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431
//! * Scalar field: r = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 1
//!
//! G1 curve equation: y^2 = x^3 + Ax + B, where
//! * A = 0,
//! * B = 1
//!
//! G2 curve equation: y^2 = x^3 + Ax + B, where
//! * A = 0
//! * B = 3
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

View File

@@ -3,7 +3,7 @@ use ark_ec::{
short_weierstrass::{Affine, Projective, SWCurveConfig}, short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveGroup, AffineRepr, CurveGroup,
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::vec::Vec; use ark_std::vec::Vec;

View File

@@ -3,7 +3,8 @@ use ark_ec::{
pairing::{MillerLoopOutput, Pairing, PairingOutput}, pairing::{MillerLoopOutput, Pairing, PairingOutput},
}; };
use ark_ff::{ use ark_ff::{
biginteger::BigInteger832, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field, One, biginteger::BigInteger832, AdditiveGroup, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field,
One,
}; };
use itertools::Itertools; use itertools::Itertools;
@@ -181,38 +182,6 @@ pub const ATE_LOOP_COUNT: [u64; 13] = [
/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true /// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true; pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 = pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt!("7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033");
/// 7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033
pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt::new([
0xb62ef36af72855d1,
0x676b5cef49d290fa,
0xd17fcf3c60947427,
0x5b93d992bc1b2849,
0x2171887cecd072cb,
0x879a2873f1516f4a,
0x8cc6856bd2cdf24e,
0xbff4fb6644d01993,
0x5dcbeea3e31ea667,
0x5f256f47681649f3,
0x2355a2b0839967fe,
0x144ed,
0x0,
]);
/// FINAL_EXPONENT_LAST_CHUNK_W1 = pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt!("86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986");
/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt::new([
0x5657b9b57b942aea,
0x84f9a65f3bd54eaf,
0x5ea4214e35cd127,
0xe3cbcbc14ec1501d,
0xf196cb845a3092ab,
0x7e14627ad0e19017,
0x217db4,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
]);

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp3::{Fp3, Fp3Config}, fields::fp3::{Fp3, Fp3Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::Fq; use crate::Fq;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config}, fields::fp6_2over3::{Fp6, Fp6Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq3, Fq3Config}; use crate::{Fq, Fq3, Fq3Config};

View File

@@ -225,7 +225,7 @@ pub mod fields {
pub mod curves { pub mod curves {
use ark_ec::{ use ark_ec::{
short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective, short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective,
CurveGroup, Group, AdditiveGroup, CurveGroup,
}; };
use ark_ff::{BitIteratorLE, Field, One, PrimeField}; use ark_ff::{BitIteratorLE, Field, One, PrimeField};
use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
@@ -315,12 +315,14 @@ pub mod curves {
} }
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
let modulus = <C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec(); let modulus = C::ScalarField::MODULUS.as_ref().to_vec();
let mut max = modulus.clone(); let mut max = modulus.clone();
for limb in &mut max { for limb in &mut max {
*limb = u64::MAX; *limb = u64::MAX;
} }
let num_limbs = max.len();
let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64; let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
if modulus_num_bits_mod_64 != 0 { if modulus_num_bits_mod_64 != 0 {
*max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64; *max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
@@ -332,10 +334,10 @@ pub mod curves {
.to_vec(), .to_vec(),
vec![u64::rand(&mut rng)], vec![u64::rand(&mut rng)],
(-C::ScalarField::one()).into_bigint().as_ref().to_vec(), (-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
<C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec(), modulus,
max, max,
vec![0; 50], vec![0u64; num_limbs],
vec![1000012341233u64; 36], vec![1000012341233u64; num_limbs],
]; ];
let mut input = vec![]; let mut input = vec![];

View File

@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
use ark_ff::{ use ark_ff::{
biginteger::BigInteger256 as BigInteger, biginteger::BigInteger256 as BigInteger,
fields::{Field, LegendreSymbol::*}, fields::{Field, LegendreSymbol::*},
One, Zero, AdditiveGroup, One, Zero,
}; };
use ark_std::str::FromStr; use ark_std::str::FromStr;

View File

@@ -3,7 +3,7 @@ use ark_ec::{
short_weierstrass::{self, SWCurveConfig}, short_weierstrass::{self, SWCurveConfig},
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig}, twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
@@ -110,19 +110,19 @@ impl MontCurveConfig for BandersnatchConfig {
// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage> // <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
/// x coordinate for TE curve generator /// x coordinate for TE curve generator
const TE_GENERATOR_X: Fq = pub const TE_GENERATOR_X: Fq =
MontFp!("18886178867200960497001835917649091219057080094937609519140440539760939937304"); MontFp!("18886178867200960497001835917649091219057080094937609519140440539760939937304");
/// y coordinate for TE curve generator /// y coordinate for TE curve generator
const TE_GENERATOR_Y: Fq = pub const TE_GENERATOR_Y: Fq =
MontFp!("19188667384257783945677642223292697773471335439753913231509108946878080696678"); MontFp!("19188667384257783945677642223292697773471335439753913231509108946878080696678");
/// x coordinate for SW curve generator /// x coordinate for SW curve generator
const SW_GENERATOR_X: Fq = pub const SW_GENERATOR_X: Fq =
MontFp!("30900340493481298850216505686589334086208278925799850409469406976849338430199"); MontFp!("30900340493481298850216505686589334086208278925799850409469406976849338430199");
/// y coordinate for SW curve generator /// y coordinate for SW curve generator
const SW_GENERATOR_Y: Fq = pub const SW_GENERATOR_Y: Fq =
MontFp!("12663882780877899054958035777720958383845500985908634476792678820121468453298"); MontFp!("12663882780877899054958035777720958383845500985908634476792678820121468453298");
impl SWCurveConfig for BandersnatchConfig { impl SWCurveConfig for BandersnatchConfig {

View File

@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
use ark_ff::{ use ark_ff::{
biginteger::BigInteger256 as BigInteger, biginteger::BigInteger256 as BigInteger,
fields::{Field, LegendreSymbol::*}, fields::{Field, LegendreSymbol::*},
One, Zero, AdditiveGroup, One, Zero,
}; };
use ark_std::str::FromStr; use ark_std::str::FromStr;

View File

@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
use ark_ff::{ use ark_ff::{
biginteger::BigInteger256 as BigInteger, biginteger::BigInteger256 as BigInteger,
fields::{Field, LegendreSymbol::*}, fields::{Field, LegendreSymbol::*},
One, Zero, AdditiveGroup, One, Zero,
}; };
use ark_std::str::FromStr; use ark_std::str::FromStr;

37
grumpkin/Cargo.toml Normal file
View File

@@ -0,0 +1,37 @@
[package]
name = "ark-grumpkin"
version = "0.4.0"
authors = [ "CPerezz", "arkworks contributors" ]
description = "The Grumpkin prime-order elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-grumpkin/"
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src"]
license = "MIT/Apache-2.0"
edition = "2021"
[dependencies]
ark-ff = { version = "0.4.0", default-features = false }
ark-ec = { version = "0.4.0", default-features = false }
ark-r1cs-std = { version = "0.4.0", default-features = false, optional = true }
ark-std = { version = "0.4.0", default-features = false }
ark-bn254 = { version = "0.4.0", path = "../bn254", default-features = false, features = [ "scalar_field", "curve" ] }
[dev-dependencies]
ark-relations = { version = "0.4.0", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false }
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
r1cs = [ "ark-r1cs-std" ]
[[bench]]
name = "grumpkin"
path = "benches/grumpkin.rs"
harness = false

1
grumpkin/LICENSE-APACHE Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-APACHE

1
grumpkin/LICENSE-MIT Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-MIT

View File

@@ -0,0 +1,9 @@
use ark_algebra_bench_templates::*;
use ark_grumpkin::{fq::Fq, fr::Fr, Projective as G};
bench!(
Name = "Grumpkin",
Group = G,
ScalarField = Fr,
PrimeBaseField = Fq,
);

View File

@@ -0,0 +1,28 @@
modulus = 21888242871839275222246405745257275088548364400416034343698204186575808495617
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,11 @@
use ark_r1cs_std::groups::curves::short_weierstrass::ProjectiveVar;
use crate::{constraints::FBaseVar, *};
/// A group element in the Grumpkin prime-order group.
pub type GVar = ProjectiveVar<GrumpkinConfig, FBaseVar>;
#[test]
fn test() {
ark_curve_constraint_tests::curves::sw_test::<GrumpkinConfig, GVar>().unwrap();
}

View File

@@ -0,0 +1,11 @@
use ark_r1cs_std::fields::fp::FpVar;
use crate::fq::Fq;
/// A variable that is the R1CS equivalent of `crate::Fq`.
pub type FBaseVar = FpVar<Fq>;
#[test]
fn test() {
ark_curve_constraint_tests::fields::field_test::<_, _, FBaseVar>().unwrap();
}

View File

@@ -0,0 +1,107 @@
//! This module implements the R1CS equivalent of `ark_grumpkin`.
//!
//! It implements field variables for `crate::Fq`,
//! and group variables for `crate::Projective`.
//!
//! The field underlying these constraints is `crate::Fq`.
//!
//! # Examples
//!
//! One can perform standard algebraic operations on `FBaseVar`:
//!
//! ```
//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
//! use ark_std::UniformRand;
//! use ark_relations::r1cs::*;
//! use ark_r1cs_std::prelude::*;
//! use ark_grumpkin::{*, constraints::*};
//!
//! let cs = ConstraintSystem::<Fq>::new_ref();
//! // This rng is just for test purposes; do not use it
//! // in real applications.
//! let mut rng = ark_std::test_rng();
//!
//! // Generate some random `Fq` elements.
//! let a_native = Fq::rand(&mut rng);
//! let b_native = Fq::rand(&mut rng);
//!
//! // Allocate `a_native` and `b_native` as witness variables in `cs`.
//! let a = FBaseVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?;
//! let b = FBaseVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?;
//!
//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any
//! // constraints or variables.
//! let a_const = FBaseVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?;
//! let b_const = FBaseVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?;
//!
//! let one = FBaseVar::one();
//! let zero = FBaseVar::zero();
//!
//! // Sanity check one + one = two
//! let two = &one + &one + &zero;
//! two.enforce_equal(&one.double()?)?;
//!
//! assert!(cs.is_satisfied()?);
//!
//! // Check that the value of &a + &b is correct.
//! assert_eq!((&a + &b).value()?, a_native + &b_native);
//!
//! // Check that the value of &a * &b is correct.
//! assert_eq!((&a * &b).value()?, a_native * &b_native);
//!
//! // Check that operations on variables and constants are equivalent.
//! (&a + &b).enforce_equal(&(&a_const + &b_const))?;
//! assert!(cs.is_satisfied()?);
//! # Ok(())
//! # }
//! ```
//!
//! One can also perform standard algebraic operations on `GVar`:
//!
//! ```
//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
//! # use ark_std::UniformRand;
//! # use ark_relations::r1cs::*;
//! # use ark_r1cs_std::prelude::*;
//! # use ark_grumpkin::{*, constraints::*};
//!
//! # let cs = ConstraintSystem::<Fq>::new_ref();
//! # let mut rng = ark_std::test_rng();
//!
//! // Generate some random `Projective` elements.
//! let a_native = Projective::rand(&mut rng);
//! let b_native = Projective::rand(&mut rng);
//!
//! // Allocate `a_native` and `b_native` as witness variables in `cs`.
//! let a = GVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?;
//! let b = GVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?;
//!
//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any
//! // constraints or variables.
//! let a_const = GVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?;
//! let b_const = GVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?;
//!
//! // This returns the identity.
//! let zero = GVar::zero();
//!
//! // Sanity check one + one = two
//! let two_a = &a + &a + &zero;
//! two_a.enforce_equal(&a.double()?)?;
//!
//! assert!(cs.is_satisfied()?);
//!
//! // Check that the value of &a + &b is correct.
//! assert_eq!((&a + &b).value()?, a_native + &b_native);
//!
//! // Check that operations on variables and constants are equivalent.
//! (&a + &b).enforce_equal(&(&a_const + &b_const))?;
//! assert!(cs.is_satisfied()?);
//! # Ok(())
//! # }
//! ```
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

View File

@@ -0,0 +1,52 @@
// The parameters for the curve have been taken from
// https://github.com/AztecProtocol/barretenberg/blob/97ccf76c42db581a8b8f8bfbcffe8ca015a3dd22/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp
use crate::{fq::Fq, fr::Fr};
use ark_ec::{
models::CurveConfig,
short_weierstrass::{self as sw, SWCurveConfig},
};
use ark_ff::{AdditiveGroup, Field, MontFp, Zero};
#[cfg(test)]
mod tests;
#[derive(Copy, Clone, Default, PartialEq, Eq)]
pub struct GrumpkinConfig;
impl CurveConfig for GrumpkinConfig {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR = 1
const COFACTOR: &'static [u64] = &[0x1];
/// COFACTOR_INV = 1
const COFACTOR_INV: Fr = Fr::ONE;
}
pub type Affine = sw::Affine<GrumpkinConfig>;
pub type Projective = sw::Projective<GrumpkinConfig>;
impl SWCurveConfig for GrumpkinConfig {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = -17
const COEFF_B: Fq = MontFp!("-17");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: Affine = Affine::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
/// G_GENERATOR_X = 1
pub const G_GENERATOR_X: Fq = MontFp!("1");
/// G_GENERATOR_Y = sqrt(-16)
pub const G_GENERATOR_Y: Fq =
MontFp!("17631683881184975370165255887551781615748388533673675138860");

4
grumpkin/src/curves/tests.rs Executable file
View File

@@ -0,0 +1,4 @@
use crate::Projective;
use ark_algebra_test_templates::*;
test_group!(g1; Projective; sw);

View File

@@ -0,0 +1 @@
pub use ark_bn254::{Fr as Fq, FrConfig as FqConfig};

View File

@@ -0,0 +1 @@
pub use ark_bn254::{Fq as Fr, FqConfig as FrConfig};

View File

@@ -0,0 +1,8 @@
pub mod fq;
pub use self::fq::*;
pub mod fr;
pub use self::fr::*;
#[cfg(test)]
mod tests;

View File

@@ -0,0 +1,5 @@
use crate::{Fq, Fr};
use ark_algebra_test_templates::*;
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);

33
grumpkin/src/lib.rs Normal file
View File

@@ -0,0 +1,33 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the prime-order curve Grumpkin, generated by
//! Zachary J. Williamson from Aztec protocol. The main feature of this
//! curve is that it forms a cycle with bn254, i.e. its scalar field and base
//! field respectively are the base field and scalar field of bn254.
//!
//!
//! Curve information:
//! Grumpkin:
//! * Base field: q =
//! 21888242871839275222246405745257275088548364400416034343698204186575808495617
//! * Scalar field: r =
//! 21888242871839275222246405745257275088696311157297823662689037894645226208583
//! * Curve equation: y^2 = x^3 - 17
//! * Valuation(q - 1, 2) = 28
//! * Valuation(r - 1, 2) = 1
#[cfg(feature = "r1cs")]
pub mod constraints;
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

View File

@@ -3,7 +3,7 @@ use ark_ec::{
mnt4::MNT4Config, mnt4::MNT4Config,
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE}; use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};

View File

@@ -1,5 +1,5 @@
use ark_ec::models::mnt4::{MNT4Config, MNT4}; use ark_ec::models::mnt4::{MNT4Config, MNT4};
use ark_ff::{biginteger::BigInteger320, BigInt, Field, MontFp}; use ark_ff::{biginteger::BigInteger320, AdditiveGroup, BigInt, Field, MontFp};
use crate::{Fq, Fq2, Fq2Config, Fq4Config, Fr}; use crate::{Fq, Fq2, Fq2Config, Fq4Config, Fr};
@@ -38,10 +38,11 @@ impl MNT4Config for Config {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
const ATE_IS_LOOP_COUNT_NEG: bool = false; const ATE_IS_LOOP_COUNT_NEG: bool = false;
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0]); const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt!("0x1");
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4_80.ml#L96
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 = const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
BigInt::new([993502997770534913, 5071219579242586943, 2027349, 0, 0]); BigInt!("689871209842287392837045615510547309923794945");
type Fp = Fq; type Fp = Fq;
type Fr = Fr; type Fr = Fr;
type Fp2Config = Fq2Config; type Fp2Config = Fq2Config;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp4::{Fp4, Fp4Config}, fields::fp4::{Fp4, Fp4Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq2, Fq2Config}; use crate::{Fq, Fq2, Fq2Config};

View File

@@ -3,7 +3,7 @@ use ark_ec::{
mnt4::MNT4Config, mnt4::MNT4Config,
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE}; use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};

View File

@@ -1,8 +1,5 @@
use ark_ec::models::mnt4::{MNT4Config, MNT4}; use ark_ec::models::mnt4::{MNT4Config, MNT4};
use ark_ff::{ use ark_ff::{biginteger::BigInteger768, AdditiveGroup, BigInt, Field, Fp2, MontFp};
biginteger::{BigInt, BigInteger768},
Field, Fp2, MontFp,
};
use crate::{Fq, Fq2Config, Fq4Config, Fr}; use crate::{Fq, Fq2Config, Fq4Config, Fr};
@@ -48,23 +45,10 @@ impl MNT4Config for Config {
0, 0, 0, 0, 0, 0,
]; ];
const ATE_IS_LOOP_COUNT_NEG: bool = true; const ATE_IS_LOOP_COUNT_NEG: bool = true;
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([ // https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4753.ml#L100
8824542903220142079, const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470399");
7711082599397206192,
8303354903384568230,
5874150271971943936,
9717849827920685054,
95829799234282493,
0,
0,
0,
0,
0,
0,
]);
type Fp = Fq; type Fp = Fq;
type Fr = Fr; type Fr = Fr;
type Fp2Config = Fq2Config; type Fp2Config = Fq2Config;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp4::{Fp4, Fp4Config}, fields::fp4::{Fp4, Fp4Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq2, Fq2Config}; use crate::{Fq, Fq2, Fq2Config};

View File

@@ -3,7 +3,7 @@ use ark_ec::{
mnt6::MNT6Config, mnt6::MNT6Config,
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use crate::{g1, Fq, Fq3, Fr}; use crate::{g1, Fq, Fq3, Fr};

View File

@@ -2,7 +2,7 @@ use ark_ec::{
models::mnt6::{MNT6Config, MNT6}, models::mnt6::{MNT6Config, MNT6},
short_weierstrass::SWCurveConfig, short_weierstrass::SWCurveConfig,
}; };
use ark_ff::{biginteger::BigInteger320, BigInt, Field, Fp3}; use ark_ff::{biginteger::BigInteger320, AdditiveGroup, BigInt, Field, Fp3};
use crate::{Fq, Fq3Config, Fq6Config, Fr}; use crate::{Fq, Fq3Config, Fq6Config, Fr};
@@ -26,7 +26,7 @@ impl MNT6Config for Config {
const TWIST_COEFF_A: Fp3<Self::Fp3Config> = const TWIST_COEFF_A: Fp3<Self::Fp3Config> =
Fp3::<Self::Fp3Config>::new(Fq::ZERO, Fq::ZERO, g1::Config::COEFF_A); Fp3::<Self::Fp3Config>::new(Fq::ZERO, Fq::ZERO, g1::Config::COEFF_A);
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4_80.ml#L88 // https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6_80.ml#L118
const ATE_LOOP_COUNT: &'static [i8] = &[ const ATE_LOOP_COUNT: &'static [i8] = &[
1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -1,
0, 1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0,
@@ -36,10 +36,11 @@ impl MNT6Config for Config {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
const ATE_IS_LOOP_COUNT_NEG: bool = true; const ATE_IS_LOOP_COUNT_NEG: bool = true;
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0]); const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt!("0x1");
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6_80.ml#L126
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 = const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
BigInt::new([0xdc9a1b671660000, 0x46609756bec2a33f, 0x1eef55, 0x0, 0x0]); BigInt!("689871209842287392837045615510547309923794944");
type Fp = Fq; type Fp = Fq;
type Fr = Fr; type Fr = Fr;
type Fp3Config = Fq3Config; type Fp3Config = Fq3Config;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp3::{Fp3, Fp3Config}, fields::fp3::{Fp3, Fp3Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::fq::Fq; use crate::fq::Fq;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config}, fields::fp6_2over3::{Fp6, Fp6Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq3, Fq3Config}; use crate::{Fq, Fq3, Fq3Config};

View File

@@ -3,7 +3,7 @@ use ark_ec::{
mnt6::MNT6Config, mnt6::MNT6Config,
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{AdditiveGroup, MontFp};
use crate::{g1, Fq, Fq3, Fr}; use crate::{g1, Fq, Fq3, Fr};

View File

@@ -2,7 +2,7 @@ use ark_ec::models::{
mnt6::{MNT6Config, MNT6}, mnt6::{MNT6Config, MNT6},
short_weierstrass::SWCurveConfig, short_weierstrass::SWCurveConfig,
}; };
use ark_ff::{biginteger::BigInteger768, BigInt, Field, Fp3}; use ark_ff::{biginteger::BigInteger768, AdditiveGroup, BigInt, Field, Fp3};
use crate::{Fq, Fq3Config, Fq6Config, Fr}; use crate::{Fq, Fq3Config, Fq6Config, Fr};
@@ -49,23 +49,10 @@ impl MNT6Config for Config {
0, 0, 0, 0, 0, 0,
]; ];
const ATE_IS_LOOP_COUNT_NEG: bool = false; const ATE_IS_LOOP_COUNT_NEG: bool = false;
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([ // https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6753.ml#L130C1-L130C1
8824542903220142080, const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470400");
7711082599397206192,
8303354903384568230,
5874150271971943936,
9717849827920685054,
95829799234282493,
0,
0,
0,
0,
0,
0,
]);
type Fp = Fq; type Fp = Fq;
type Fr = Fr; type Fr = Fr;
type Fp3Config = Fq3Config; type Fp3Config = Fq3Config;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp3::{Fp3, Fp3Config}, fields::fp3::{Fp3, Fp3Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::fq::Fq; use crate::fq::Fq;

View File

@@ -1,6 +1,6 @@
use ark_ff::{ use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config}, fields::fp6_2over3::{Fp6, Fp6Config},
Field, MontFp, AdditiveGroup, Field, MontFp,
}; };
use crate::{Fq, Fq3, Fq3Config}; use crate::{Fq, Fq3, Fq3Config};

View File

@@ -1,8 +1,9 @@
use ark_ec::{ use ark_ec::{
models::CurveConfig, models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{self as sw, SWCurveConfig}, short_weierstrass::{self as sw, SWCurveConfig},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use crate::{fq::Fq, fr::Fr}; use crate::{fq::Fq, fr::Fr};
@@ -42,6 +43,40 @@ impl SWCurveConfig for PallasConfig {
} }
} }
impl GLVConfig for PallasConfig {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"20444556541222657078399132219657928148671392403212669005631716460534733845831"
)];
const LAMBDA: Self::ScalarField =
MontFp!("26005156700822196841419187675678338661165322343552424574062261873906994770353");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("98231058071100081932162823354453065728")),
(true, BigInt!("98231058071186745657228807397848383489")),
(false, BigInt!("196462116142286827589391630752301449217")),
(false, BigInt!("98231058071100081932162823354453065728")),
];
fn endomorphism(p: &Projective) -> Projective {
// Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq.
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine) -> Affine {
// Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq.
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G_GENERATOR_X = -1 /// G_GENERATOR_X = -1
pub const G_GENERATOR_X: Fq = MontFp!("-1"); pub const G_GENERATOR_X: Fq = MontFp!("-1");

View File

@@ -2,3 +2,4 @@ use crate::Projective;
use ark_algebra_test_templates::*; use ark_algebra_test_templates::*;
test_group!(g1; Projective; sw); test_group!(g1; Projective; sw);
test_group!(g1_glv; Projective; glv);

View File

@@ -2,7 +2,7 @@ use ark_ec::{
models::CurveConfig, models::CurveConfig,
short_weierstrass::{self as sw, SWCurveConfig}, short_weierstrass::{self as sw, SWCurveConfig},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, Field, MontFp, Zero};
use crate::{fq::Fq, fr::Fr}; use crate::{fq::Fq, fr::Fr};

View File

@@ -2,7 +2,7 @@ use ark_ec::{
models::CurveConfig, models::CurveConfig,
short_weierstrass::{self as sw, SWCurveConfig}, short_weierstrass::{self as sw, SWCurveConfig},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, Field, MontFp, Zero};
use crate::{fq::Fq, fr::Fr}; use crate::{fq::Fq, fr::Fr};

View File

@@ -1,9 +1,10 @@
use crate::{fq::Fq, fr::Fr}; use crate::{fq::Fq, fr::Fr};
use ark_ec::{ use ark_ec::{
models::CurveConfig, models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{self as sw, SWCurveConfig}, short_weierstrass::{self as sw, SWCurveConfig},
}; };
use ark_ff::{Field, MontFp, Zero}; use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -41,6 +42,40 @@ impl SWCurveConfig for VestaConfig {
} }
} }
impl GLVConfig for VestaConfig {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"26005156700822196841419187675678338661165322343552424574062261873906994770353"
)];
const LAMBDA: Self::ScalarField =
MontFp!("20444556541222657078399132219657928148671392403212669005631716460534733845831");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("98231058071100081932162823354453065729")),
(true, BigInt!("98231058071186745657228807397848383488")),
(false, BigInt!("196462116142286827589391630752301449217")),
(false, BigInt!("98231058071100081932162823354453065729")),
];
fn endomorphism(p: &Projective) -> Projective {
// Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq.
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine) -> Affine {
// Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq.
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G_GENERATOR_X = -1 /// G_GENERATOR_X = -1
/// Encoded in Montgomery form, so the value here is -R mod p. /// Encoded in Montgomery form, so the value here is -R mod p.
pub const G_GENERATOR_X: Fq = MontFp!("-1"); pub const G_GENERATOR_X: Fq = MontFp!("-1");

View File

@@ -2,3 +2,4 @@ use crate::Projective;
use ark_algebra_test_templates::*; use ark_algebra_test_templates::*;
test_group!(g1; Projective; sw); test_group!(g1; Projective; sw);
test_group!(g1_glv; Projective; glv);