mirror of
https://github.com/arnaucube/ark-curves-cherry-picked.git
synced 2026-01-27 14:13:46 +01:00
Compare commits
16 Commits
use-algebr
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2d16a27e2 | ||
|
|
7854883b47 | ||
|
|
ccf83923f8 | ||
|
|
0a64024ebc | ||
|
|
8c0256ac9c | ||
|
|
72a18b6ecf | ||
|
|
8765798eb0 | ||
|
|
7e4b4bf027 | ||
|
|
4d1e504025 | ||
|
|
fc8379d9ed | ||
|
|
a0bd36f781 | ||
|
|
1ce1fcf70f | ||
|
|
379f23070c | ||
|
|
7e58260618 | ||
|
|
3fded1fbcc | ||
|
|
32b487e7fd |
97
.github/workflows/ci.yml
vendored
97
.github/workflows/ci.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
override: true
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
@@ -104,6 +104,7 @@ jobs:
|
||||
- dir: curve-constraint-tests/
|
||||
- dir: mnt4_753/
|
||||
- dir: mnt6_753/
|
||||
- dir: cp6_782/
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
@@ -115,11 +116,34 @@ jobs:
|
||||
test-mnt4-753:
|
||||
name: Test (mnt4_753/)
|
||||
runs-on: macos-latest
|
||||
needs: [directories] # Waits for the directory listing job
|
||||
steps:
|
||||
- name: Checkout
|
||||
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: |
|
||||
cd mnt4_753/
|
||||
cargo test --all-features
|
||||
@@ -127,15 +151,74 @@ jobs:
|
||||
test-mnt6-753:
|
||||
name: Test (mnt6_753/)
|
||||
runs-on: macos-latest
|
||||
needs: [directories] # Waits for the directory listing job
|
||||
steps:
|
||||
- name: Checkout
|
||||
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: |
|
||||
cd mnt6_753/
|
||||
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:
|
||||
name: Check Documentation
|
||||
runs-on: ubuntu-latest
|
||||
@@ -164,14 +247,14 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Rust (${{ matrix.rust }})
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: thumbv6m-none-eabi
|
||||
override: true
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
|
||||
@@ -6,10 +6,19 @@
|
||||
|
||||
### 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
|
||||
|
||||
- [\#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
|
||||
|
||||
- [\#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
|
||||
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
|
||||
- Fixed curve benches
|
||||
|
||||
@@ -9,6 +9,8 @@ members = [
|
||||
"bw6_761",
|
||||
"ed_on_bw6_761",
|
||||
|
||||
"bw6_767",
|
||||
|
||||
"cp6_782",
|
||||
"ed_on_cp6_782",
|
||||
|
||||
@@ -18,6 +20,7 @@ members = [
|
||||
|
||||
"bn254",
|
||||
"ed_on_bn254",
|
||||
"grumpkin",
|
||||
|
||||
"mnt4_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-serialize = { 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/" }
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -20,6 +24,7 @@ This repository contains implementations of some popular elliptic curves. The cu
|
||||
### BN254 and related curves
|
||||
* [`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-grumpkin`](grumpkin): Implements the Grumpkin curve. A curve that forms a cycle with bn254.
|
||||
|
||||
### 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
|
||||
|
||||
@@ -3,14 +3,15 @@ use ark_ec::{
|
||||
bls12::Bls12Config,
|
||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||
models::{
|
||||
short_weierstrass::{Affine as SWAffine, SWCurveConfig},
|
||||
short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig},
|
||||
twisted_edwards::{
|
||||
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
|
||||
},
|
||||
},
|
||||
scalar_mul::glv::GLVConfig,
|
||||
CurveConfig,
|
||||
};
|
||||
use ark_ff::{Field, MontFp, PrimeField, Zero};
|
||||
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||
use ark_std::{ops::Neg, One};
|
||||
|
||||
use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};
|
||||
@@ -49,6 +50,12 @@ impl SWCurveConfig for Config {
|
||||
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]
|
||||
fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine {
|
||||
// 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 {
|
||||
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
||||
X - Fr::one()
|
||||
|
||||
@@ -2,12 +2,12 @@ use ark_ec::{
|
||||
bls12,
|
||||
bls12::Bls12Config,
|
||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||
models::CurveConfig,
|
||||
scalar_mul::glv::GLVConfig,
|
||||
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 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_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ test_group!(g1; G1Projective; sw);
|
||||
test_group!(g2; G2Projective; sw);
|
||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
|
||||
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!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use ark_algebra_bench_templates::*;
|
||||
|
||||
use ark_bls12_381::{
|
||||
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
|
||||
};
|
||||
|
||||
@@ -3,10 +3,11 @@ use ark_ec::{
|
||||
bls12::Bls12Config,
|
||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||
models::CurveConfig,
|
||||
scalar_mul::glv::GLVConfig,
|
||||
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_std::{ops::Neg, One};
|
||||
|
||||
@@ -52,6 +53,12 @@ impl SWCurveConfig for Config {
|
||||
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]
|
||||
fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
|
||||
// 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 {
|
||||
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
||||
Fr::one() - X
|
||||
@@ -180,6 +215,7 @@ mod test {
|
||||
|
||||
use super::*;
|
||||
use crate::g1;
|
||||
use ark_serialize::CanonicalDeserialize;
|
||||
use ark_std::{rand::Rng, UniformRand};
|
||||
|
||||
fn sample_unchecked() -> Affine<g1::Config> {
|
||||
@@ -204,4 +240,55 @@ mod test {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ use ark_ec::{
|
||||
bls12::Bls12Config,
|
||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||
models::CurveConfig,
|
||||
scalar_mul::glv::GLVConfig,
|
||||
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 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_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
|
||||
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!(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_pairing!(pairing; crate::Bls12_381);
|
||||
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
|
||||
|
||||
@@ -14,17 +14,28 @@ pub struct 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 infinity_flag_set = (bytes[0] >> 6) & 1;
|
||||
let sort_flag_set = (bytes[0] >> 5) & 1;
|
||||
|
||||
Self {
|
||||
is_compressed: compression_flag_set == 1,
|
||||
is_infinity: infinity_flag_set == 1,
|
||||
is_lexographically_largest: sort_flag_set == 1,
|
||||
let is_compressed = compression_flag_set == 1;
|
||||
let is_infinity = infinity_flag_set == 1;
|
||||
let 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]) {
|
||||
if self.is_compressed {
|
||||
bytes[0] |= 1 << 7;
|
||||
@@ -38,6 +49,13 @@ impl EncodingFlags {
|
||||
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> {
|
||||
@@ -71,20 +89,15 @@ pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] {
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn read_fq_with_offset(
|
||||
bytes: &[u8],
|
||||
offset: usize,
|
||||
mask: bool,
|
||||
) -> Result<Fq, ark_serialize::SerializationError> {
|
||||
fn read_bytes_with_offset(bytes: &[u8], offset: usize, mask: bool) -> [u8; G1_SERIALIZED_SIZE] {
|
||||
let mut tmp = [0; G1_SERIALIZED_SIZE];
|
||||
// read `G1_SERIALIZED_SIZE` bytes
|
||||
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
|
||||
|
||||
if mask {
|
||||
// Mask away the flag bits
|
||||
tmp[0] &= 0b0001_1111;
|
||||
EncodingFlags::remove_flags(&mut tmp);
|
||||
}
|
||||
deserialize_fq(tmp).ok_or(SerializationError::InvalidData)
|
||||
tmp
|
||||
}
|
||||
|
||||
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)?;
|
||||
|
||||
// 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 {
|
||||
return Err(SerializationError::UnexpectedFlags);
|
||||
}
|
||||
|
||||
// Attempt to obtain the x-coordinate
|
||||
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// 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)?;
|
||||
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
|
||||
.ok_or(SerializationError::InvalidData)?;
|
||||
|
||||
@@ -126,22 +145,27 @@ pub(crate) fn read_g1_uncompressed<R: ark_serialize::Read>(
|
||||
.map_err(|_| SerializationError::InvalidData)?;
|
||||
|
||||
// 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
|
||||
if flags.is_compressed {
|
||||
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 x_bytes != [0u8; 48] || y_bytes != [0u8; 48] {
|
||||
return Err(SerializationError::InvalidData);
|
||||
}
|
||||
return Ok(G1Affine::zero());
|
||||
}
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
Ok(p)
|
||||
@@ -156,21 +180,26 @@ pub(crate) fn read_g2_compressed<R: ark_serialize::Read>(
|
||||
.map_err(|_| SerializationError::InvalidData)?;
|
||||
|
||||
// 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
|
||||
if !flags.is_compressed {
|
||||
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 xc1_bytes != [0u8; 48] || xc0_bytes != [0u8; 48] {
|
||||
return Err(SerializationError::InvalidData);
|
||||
}
|
||||
return Ok(G2Affine::zero());
|
||||
}
|
||||
|
||||
// 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 xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
|
||||
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
|
||||
let x = Fq2::new(xc0, xc1);
|
||||
|
||||
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)?;
|
||||
|
||||
// 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
|
||||
if flags.is_compressed {
|
||||
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 xc1_bytes != [0u8; 48]
|
||||
|| xc0_bytes != [0u8; 48]
|
||||
|| yc1_bytes != [0u8; 48]
|
||||
|| yc0_bytes != [0u8; 48]
|
||||
{
|
||||
return Err(SerializationError::InvalidData);
|
||||
}
|
||||
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
|
||||
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
|
||||
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
|
||||
let x = Fq2::new(xc0, xc1);
|
||||
|
||||
// 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 p = G2Affine::new_unchecked(x, y);
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
|
||||
use ark_ff::{
|
||||
biginteger::{BigInt, BigInteger, BigInteger384},
|
||||
fields::{FftField, Field, Fp12Config, Fp2Config, Fp6Config, PrimeField},
|
||||
One, UniformRand, Zero,
|
||||
AdditiveGroup, One, UniformRand, Zero,
|
||||
};
|
||||
use ark_std::{
|
||||
cmp::Ordering,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use ark_ec::{
|
||||
bn,
|
||||
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};
|
||||
|
||||
@@ -36,6 +38,42 @@ impl SWCurveConfig for Config {
|
||||
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
|
||||
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
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use ark_ec::{
|
||||
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};
|
||||
|
||||
@@ -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_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||
|
||||
|
||||
@@ -7,3 +7,5 @@ test_group!(g1; G1Projective; sw);
|
||||
test_group!(g2; G2Projective; sw);
|
||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
|
||||
test_pairing!(pairing; crate::Bn254);
|
||||
test_group!(g1_glv; G1Projective; glv);
|
||||
test_group!(g2_glv; G2Projective; glv);
|
||||
|
||||
@@ -3,5 +3,7 @@ use ark_ff::fields::{Fp256, MontBackend, MontConfig};
|
||||
#[derive(MontConfig)]
|
||||
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
|
||||
#[generator = "5"]
|
||||
#[small_subgroup_base = "3"]
|
||||
#[small_subgroup_power = "2"]
|
||||
pub struct FrConfig;
|
||||
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use ark_ec::{
|
||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||
scalar_mul::glv::GLVConfig,
|
||||
short_weierstrass::{Affine, Projective},
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
|
||||
|
||||
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 =
|
||||
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
|
||||
pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use ark_ec::{
|
||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||
scalar_mul::glv::GLVConfig,
|
||||
short_weierstrass::{Affine, Projective},
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
|
||||
|
||||
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 =
|
||||
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
|
||||
pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");
|
||||
|
||||
@@ -2,7 +2,9 @@ use ark_ec::{
|
||||
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::*;
|
||||
|
||||
@@ -16,42 +18,141 @@ mod tests;
|
||||
pub struct Config;
|
||||
|
||||
impl BW6Config for Config {
|
||||
const X: BigInteger = BigInt::new([
|
||||
0x8508c00000000001,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
]);
|
||||
const X: BigInteger = BigInt!("0x8508c00000000001");
|
||||
/// `x` is positive.
|
||||
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
|
||||
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002];
|
||||
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] = &[
|
||||
-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, 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, 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,
|
||||
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,
|
||||
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, 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, 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, 1, 0, 0, 0, 1,
|
||||
];
|
||||
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
|
||||
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 Fp3Config = Fq3Config;
|
||||
type Fp6Config = Fq6Config;
|
||||
type G1Config = g1::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>;
|
||||
|
||||
@@ -6,3 +6,5 @@ test_group!(g1; G1Projective; sw);
|
||||
test_group!(g2; G2Projective; sw);
|
||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
|
||||
test_pairing!(pairing; crate::BW6_761);
|
||||
test_group!(g1_glv; G1Projective; glv);
|
||||
test_group!(g2_glv; G2Projective; glv);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp3::{Fp3, Fp3Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::Fq;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq3, Fq3Config};
|
||||
|
||||
33
bw6_767/Cargo.toml
Normal file
33
bw6_767/Cargo.toml
Normal 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
1
bw6_767/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
||||
1
bw6_767/LICENSE-MIT
Symbolic link
1
bw6_767/LICENSE-MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
||||
16
bw6_767/benches/bw6_767.rs
Normal file
16
bw6_767/benches/bw6_767.rs
Normal 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,
|
||||
);
|
||||
28
bw6_767/scripts/base_field.sage
Normal file
28
bw6_767/scripts/base_field.sage
Normal 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)
|
||||
28
bw6_767/scripts/scalar_field.sage
Normal file
28
bw6_767/scripts/scalar_field.sage
Normal 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
59
bw6_767/src/curves/g1.rs
Normal 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
60
bw6_767/src/curves/g2.rs
Normal 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
51
bw6_767/src/curves/mod.rs
Normal 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>;
|
||||
8
bw6_767/src/curves/tests.rs
Normal file
8
bw6_767/src/curves/tests.rs
Normal 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
7
bw6_767/src/fields/fq.rs
Normal 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
79
bw6_767/src/fields/fq3.rs
Normal 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
26
bw6_767/src/fields/fq6.rs
Normal 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
1
bw6_767/src/fields/fr.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub use ark_bls12_381::{Fq as Fr, FqConfig as FrConfig};
|
||||
14
bw6_767/src/fields/mod.rs
Normal file
14
bw6_767/src/fields/mod.rs
Normal 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;
|
||||
7
bw6_767/src/fields/tests.rs
Normal file
7
bw6_767/src/fields/tests.rs
Normal 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
36
bw6_767/src/lib.rs
Executable 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::*;
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
||||
AffineRepr, CurveGroup,
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, MontFp};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use ark_std::vec::Vec;
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ use ark_ec::{
|
||||
pairing::{MillerLoopOutput, Pairing, PairingOutput},
|
||||
};
|
||||
use ark_ff::{
|
||||
biginteger::BigInteger832, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field, One,
|
||||
biginteger::BigInteger832, AdditiveGroup, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field,
|
||||
One,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
|
||||
@@ -181,38 +182,6 @@ pub const ATE_LOOP_COUNT: [u64; 13] = [
|
||||
/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
|
||||
pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
||||
|
||||
/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 =
|
||||
/// 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,
|
||||
]);
|
||||
pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt!("7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033");
|
||||
|
||||
/// FINAL_EXPONENT_LAST_CHUNK_W1 =
|
||||
/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
|
||||
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt::new([
|
||||
0x5657b9b57b942aea,
|
||||
0x84f9a65f3bd54eaf,
|
||||
0x5ea4214e35cd127,
|
||||
0xe3cbcbc14ec1501d,
|
||||
0xf196cb845a3092ab,
|
||||
0x7e14627ad0e19017,
|
||||
0x217db4,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
]);
|
||||
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt!("86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp3::{Fp3, Fp3Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::Fq;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq3, Fq3Config};
|
||||
|
||||
@@ -225,7 +225,7 @@ pub mod fields {
|
||||
pub mod curves {
|
||||
use ark_ec::{
|
||||
short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective,
|
||||
CurveGroup, Group,
|
||||
AdditiveGroup, CurveGroup,
|
||||
};
|
||||
use ark_ff::{BitIteratorLE, Field, One, PrimeField};
|
||||
use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
|
||||
@@ -315,12 +315,14 @@ pub mod curves {
|
||||
}
|
||||
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();
|
||||
for limb in &mut max {
|
||||
*limb = u64::MAX;
|
||||
}
|
||||
|
||||
let num_limbs = max.len();
|
||||
|
||||
let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
|
||||
if modulus_num_bits_mod_64 != 0 {
|
||||
*max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
|
||||
@@ -332,10 +334,10 @@ pub mod curves {
|
||||
.to_vec(),
|
||||
vec![u64::rand(&mut rng)],
|
||||
(-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
|
||||
<C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec(),
|
||||
modulus,
|
||||
max,
|
||||
vec![0; 50],
|
||||
vec![1000012341233u64; 36],
|
||||
vec![0u64; num_limbs],
|
||||
vec![1000012341233u64; num_limbs],
|
||||
];
|
||||
|
||||
let mut input = vec![];
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
|
||||
use ark_ff::{
|
||||
biginteger::BigInteger256 as BigInteger,
|
||||
fields::{Field, LegendreSymbol::*},
|
||||
One, Zero,
|
||||
AdditiveGroup, One, Zero,
|
||||
};
|
||||
use ark_std::str::FromStr;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
short_weierstrass::{self, SWCurveConfig},
|
||||
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, MontFp};
|
||||
|
||||
use crate::{Fq, Fr};
|
||||
|
||||
@@ -110,19 +110,19 @@ impl MontCurveConfig for BandersnatchConfig {
|
||||
// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
|
||||
|
||||
/// x coordinate for TE curve generator
|
||||
const TE_GENERATOR_X: Fq =
|
||||
pub const TE_GENERATOR_X: Fq =
|
||||
MontFp!("18886178867200960497001835917649091219057080094937609519140440539760939937304");
|
||||
|
||||
/// y coordinate for TE curve generator
|
||||
const TE_GENERATOR_Y: Fq =
|
||||
pub const TE_GENERATOR_Y: Fq =
|
||||
MontFp!("19188667384257783945677642223292697773471335439753913231509108946878080696678");
|
||||
|
||||
/// x coordinate for SW curve generator
|
||||
const SW_GENERATOR_X: Fq =
|
||||
pub const SW_GENERATOR_X: Fq =
|
||||
MontFp!("30900340493481298850216505686589334086208278925799850409469406976849338430199");
|
||||
|
||||
/// y coordinate for SW curve generator
|
||||
const SW_GENERATOR_Y: Fq =
|
||||
pub const SW_GENERATOR_Y: Fq =
|
||||
MontFp!("12663882780877899054958035777720958383845500985908634476792678820121468453298");
|
||||
|
||||
impl SWCurveConfig for BandersnatchConfig {
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
|
||||
use ark_ff::{
|
||||
biginteger::BigInteger256 as BigInteger,
|
||||
fields::{Field, LegendreSymbol::*},
|
||||
One, Zero,
|
||||
AdditiveGroup, One, Zero,
|
||||
};
|
||||
use ark_std::str::FromStr;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
|
||||
use ark_ff::{
|
||||
biginteger::BigInteger256 as BigInteger,
|
||||
fields::{Field, LegendreSymbol::*},
|
||||
One, Zero,
|
||||
AdditiveGroup, One, Zero,
|
||||
};
|
||||
use ark_std::str::FromStr;
|
||||
|
||||
|
||||
37
grumpkin/Cargo.toml
Normal file
37
grumpkin/Cargo.toml
Normal 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
1
grumpkin/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
||||
1
grumpkin/LICENSE-MIT
Symbolic link
1
grumpkin/LICENSE-MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
||||
9
grumpkin/benches/grumpkin.rs
Normal file
9
grumpkin/benches/grumpkin.rs
Normal 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,
|
||||
);
|
||||
28
grumpkin/scripts/base_field.sage
Normal file
28
grumpkin/scripts/base_field.sage
Normal 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)
|
||||
28
grumpkin/scripts/scalar_field.sage
Normal file
28
grumpkin/scripts/scalar_field.sage
Normal 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)
|
||||
11
grumpkin/src/constraints/curves.rs
Normal file
11
grumpkin/src/constraints/curves.rs
Normal 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();
|
||||
}
|
||||
11
grumpkin/src/constraints/fields.rs
Normal file
11
grumpkin/src/constraints/fields.rs
Normal 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();
|
||||
}
|
||||
107
grumpkin/src/constraints/mod.rs
Normal file
107
grumpkin/src/constraints/mod.rs
Normal 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::*;
|
||||
52
grumpkin/src/curves/mod.rs
Normal file
52
grumpkin/src/curves/mod.rs
Normal 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
4
grumpkin/src/curves/tests.rs
Executable file
@@ -0,0 +1,4 @@
|
||||
use crate::Projective;
|
||||
use ark_algebra_test_templates::*;
|
||||
|
||||
test_group!(g1; Projective; sw);
|
||||
1
grumpkin/src/fields/fq.rs
Normal file
1
grumpkin/src/fields/fq.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub use ark_bn254::{Fr as Fq, FrConfig as FqConfig};
|
||||
1
grumpkin/src/fields/fr.rs
Normal file
1
grumpkin/src/fields/fr.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub use ark_bn254::{Fq as Fr, FqConfig as FrConfig};
|
||||
8
grumpkin/src/fields/mod.rs
Normal file
8
grumpkin/src/fields/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
pub mod fq;
|
||||
pub use self::fq::*;
|
||||
|
||||
pub mod fr;
|
||||
pub use self::fr::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
5
grumpkin/src/fields/tests.rs
Normal file
5
grumpkin/src/fields/tests.rs
Normal 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
33
grumpkin/src/lib.rs
Normal 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::*;
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
mnt4::MNT4Config,
|
||||
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};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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};
|
||||
|
||||
@@ -38,10 +38,11 @@ impl MNT4Config for Config {
|
||||
0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
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;
|
||||
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4_80.ml#L96
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
||||
BigInt::new([993502997770534913, 5071219579242586943, 2027349, 0, 0]);
|
||||
BigInt!("689871209842287392837045615510547309923794945");
|
||||
type Fp = Fq;
|
||||
type Fr = Fr;
|
||||
type Fp2Config = Fq2Config;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp4::{Fp4, Fp4Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq2, Fq2Config};
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
mnt4::MNT4Config,
|
||||
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};
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use ark_ec::models::mnt4::{MNT4Config, MNT4};
|
||||
use ark_ff::{
|
||||
biginteger::{BigInt, BigInteger768},
|
||||
Field, Fp2, MontFp,
|
||||
};
|
||||
use ark_ff::{biginteger::BigInteger768, AdditiveGroup, BigInt, Field, Fp2, MontFp};
|
||||
|
||||
use crate::{Fq, Fq2Config, Fq4Config, Fr};
|
||||
|
||||
@@ -48,23 +45,10 @@ impl MNT4Config for Config {
|
||||
0, 0, 0,
|
||||
];
|
||||
const ATE_IS_LOOP_COUNT_NEG: bool = true;
|
||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 =
|
||||
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
|
||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
|
||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([
|
||||
8824542903220142079,
|
||||
7711082599397206192,
|
||||
8303354903384568230,
|
||||
5874150271971943936,
|
||||
9717849827920685054,
|
||||
95829799234282493,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]);
|
||||
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4753.ml#L100
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470399");
|
||||
type Fp = Fq;
|
||||
type Fr = Fr;
|
||||
type Fp2Config = Fq2Config;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp4::{Fp4, Fp4Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq2, Fq2Config};
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
mnt6::MNT6Config,
|
||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, MontFp};
|
||||
|
||||
use crate::{g1, Fq, Fq3, Fr};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
||||
models::mnt6::{MNT6Config, MNT6},
|
||||
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};
|
||||
|
||||
@@ -26,7 +26,7 @@ impl MNT6Config for Config {
|
||||
const TWIST_COEFF_A: Fp3<Self::Fp3Config> =
|
||||
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] = &[
|
||||
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,
|
||||
@@ -36,10 +36,11 @@ impl MNT6Config for Config {
|
||||
0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
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;
|
||||
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6_80.ml#L126
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
||||
BigInt::new([0xdc9a1b671660000, 0x46609756bec2a33f, 0x1eef55, 0x0, 0x0]);
|
||||
BigInt!("689871209842287392837045615510547309923794944");
|
||||
type Fp = Fq;
|
||||
type Fr = Fr;
|
||||
type Fp3Config = Fq3Config;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp3::{Fp3, Fp3Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::fq::Fq;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq3, Fq3Config};
|
||||
|
||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
||||
mnt6::MNT6Config,
|
||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||
};
|
||||
use ark_ff::{Field, MontFp};
|
||||
use ark_ff::{AdditiveGroup, MontFp};
|
||||
|
||||
use crate::{g1, Fq, Fq3, Fr};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_ec::models::{
|
||||
mnt6::{MNT6Config, MNT6},
|
||||
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};
|
||||
|
||||
@@ -49,23 +49,10 @@ impl MNT6Config for Config {
|
||||
0, 0, 0,
|
||||
];
|
||||
const ATE_IS_LOOP_COUNT_NEG: bool = false;
|
||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 =
|
||||
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
|
||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
|
||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([
|
||||
8824542903220142080,
|
||||
7711082599397206192,
|
||||
8303354903384568230,
|
||||
5874150271971943936,
|
||||
9717849827920685054,
|
||||
95829799234282493,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]);
|
||||
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6753.ml#L130C1-L130C1
|
||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470400");
|
||||
type Fp = Fq;
|
||||
type Fr = Fr;
|
||||
type Fp3Config = Fq3Config;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp3::{Fp3, Fp3Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::fq::Fq;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ark_ff::{
|
||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||
Field, MontFp,
|
||||
AdditiveGroup, Field, MontFp,
|
||||
};
|
||||
|
||||
use crate::{Fq, Fq3, Fq3Config};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use ark_ec::{
|
||||
models::CurveConfig,
|
||||
scalar_mul::glv::GLVConfig,
|
||||
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};
|
||||
|
||||
@@ -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
|
||||
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@ use crate::Projective;
|
||||
use ark_algebra_test_templates::*;
|
||||
|
||||
test_group!(g1; Projective; sw);
|
||||
test_group!(g1_glv; Projective; glv);
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
||||
models::CurveConfig,
|
||||
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};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
||||
models::CurveConfig,
|
||||
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};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::{fq::Fq, fr::Fr};
|
||||
use ark_ec::{
|
||||
models::CurveConfig,
|
||||
scalar_mul::glv::GLVConfig,
|
||||
short_weierstrass::{self as sw, SWCurveConfig},
|
||||
};
|
||||
use ark_ff::{Field, MontFp, Zero};
|
||||
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||
|
||||
#[cfg(test)]
|
||||
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
|
||||
/// Encoded in Montgomery form, so the value here is -R mod p.
|
||||
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
||||
|
||||
@@ -2,3 +2,4 @@ use crate::Projective;
|
||||
use ark_algebra_test_templates::*;
|
||||
|
||||
test_group!(g1; Projective; sw);
|
||||
test_group!(g1_glv; Projective; glv);
|
||||
|
||||
Reference in New Issue
Block a user