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 |
103
.github/workflows/ci.yml
vendored
103
.github/workflows/ci.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
|||||||
toolchain: ${{ matrix.rust }}
|
toolchain: ${{ matrix.rust }}
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -104,6 +104,7 @@ jobs:
|
|||||||
- dir: curve-constraint-tests/
|
- dir: curve-constraint-tests/
|
||||||
- dir: mnt4_753/
|
- dir: mnt4_753/
|
||||||
- dir: mnt6_753/
|
- dir: mnt6_753/
|
||||||
|
- dir: cp6_782/
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -115,11 +116,34 @@ jobs:
|
|||||||
test-mnt4-753:
|
test-mnt4-753:
|
||||||
name: Test (mnt4_753/)
|
name: Test (mnt4_753/)
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
needs: [directories] # Waits for the directory listing job
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Run tests
|
|
||||||
|
- name: Check if source code updated
|
||||||
|
uses: dorny/paths-filter@v2.11.1
|
||||||
|
id: check-diff
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
mnt4_753_is_updated:
|
||||||
|
- 'mnt4_753/**'
|
||||||
|
|
||||||
|
- name: Generate lockfile
|
||||||
|
run: cargo generate-lockfile
|
||||||
|
|
||||||
|
- name: Check if deps updated
|
||||||
|
id: deps-updated
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Conditionally run the tests
|
||||||
|
# if source code updated OR dependencies updated
|
||||||
|
if: ${{ steps.check-diff.outputs.mnt4_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
cd mnt4_753/
|
cd mnt4_753/
|
||||||
cargo test --all-features
|
cargo test --all-features
|
||||||
@@ -127,15 +151,74 @@ jobs:
|
|||||||
test-mnt6-753:
|
test-mnt6-753:
|
||||||
name: Test (mnt6_753/)
|
name: Test (mnt6_753/)
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
needs: [directories] # Waits for the directory listing job
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Run tests
|
|
||||||
|
- name: Check if source code updated
|
||||||
|
uses: dorny/paths-filter@v2.11.1
|
||||||
|
id: check-diff
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
mnt6_753_is_updated:
|
||||||
|
- 'mnt6_753/**'
|
||||||
|
|
||||||
|
- name: Generate lockfile
|
||||||
|
run: cargo generate-lockfile
|
||||||
|
|
||||||
|
- name: Check if deps updated
|
||||||
|
id: deps-updated
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Conditionally run the tests
|
||||||
|
# if source code updated OR dependencies updated
|
||||||
|
if: ${{ steps.check-diff.outputs.mnt6_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
cd mnt6_753/
|
cd mnt6_753/
|
||||||
cargo test --all-features
|
cargo test --all-features
|
||||||
|
|
||||||
|
test-cp6_782:
|
||||||
|
name: Test (cp6_782/)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check if source code updated
|
||||||
|
uses: dorny/paths-filter@v2.11.1
|
||||||
|
id: check-diff
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
cp6_782_is_updated:
|
||||||
|
- 'cp6_782/**'
|
||||||
|
|
||||||
|
- name: Generate lockfile
|
||||||
|
run: cargo generate-lockfile
|
||||||
|
|
||||||
|
- name: Check if deps updated
|
||||||
|
id: deps-updated
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Conditionally run the tests
|
||||||
|
# if source code updated OR dependencies updated
|
||||||
|
if: ${{ steps.check-diff.outputs.cp6_782_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
|
||||||
|
run: |
|
||||||
|
cd cp6_782/
|
||||||
|
cargo test --all-features
|
||||||
|
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
name: Check Documentation
|
name: Check Documentation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -164,14 +247,14 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Rust (${{ matrix.rust }})
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
target: aarch64-unknown-none
|
target: thumbv6m-none-eabi
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -183,10 +266,10 @@ jobs:
|
|||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: check
|
command: check
|
||||||
args: --examples --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none
|
args: --examples --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none
|
args: --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi
|
||||||
|
|||||||
@@ -6,10 +6,19 @@
|
|||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
- [\#156](https://github.com/arkworks-rs/curves/pull/156) Add the bw6-767 curve.
|
||||||
|
- [\#174](https://github.com/arkworks-rs/curves/pull/174) Add the "grumpkin" curve.
|
||||||
|
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
|
- [\#156](https://github.com/arkworks-rs/curves/pull/156) The hard part of the final exponentiation for bw6-761 relocated from arkworks/algebra.
|
||||||
|
- [\#158](https://github.com/arkworks-rs/curves/pull/158) Enabled GLV as the default scalar multiplication for BLS12-377, BLS12-381 and BN254.
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
- [\#176](https://github.com/arkworks-rs/curves/pull/176) Non-canonical infinity point and bad flags in BLS12-381 serialization should fail.
|
||||||
|
|
||||||
## v0.4.0
|
## v0.4.0
|
||||||
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
|
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
|
||||||
- Fixed curve benches
|
- Fixed curve benches
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ members = [
|
|||||||
"bw6_761",
|
"bw6_761",
|
||||||
"ed_on_bw6_761",
|
"ed_on_bw6_761",
|
||||||
|
|
||||||
|
"bw6_767",
|
||||||
|
|
||||||
"cp6_782",
|
"cp6_782",
|
||||||
"ed_on_cp6_782",
|
"ed_on_cp6_782",
|
||||||
|
|
||||||
@@ -18,6 +20,7 @@ members = [
|
|||||||
|
|
||||||
"bn254",
|
"bn254",
|
||||||
"ed_on_bn254",
|
"ed_on_bn254",
|
||||||
|
"grumpkin",
|
||||||
|
|
||||||
"mnt4_298",
|
"mnt4_298",
|
||||||
"mnt6_298",
|
"mnt6_298",
|
||||||
@@ -71,4 +74,5 @@ ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
|
|||||||
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
|
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
|
||||||
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }
|
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }
|
||||||
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra/" }
|
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra/" }
|
||||||
|
ark-algebra-bench-templates = { git = "https://github.com/arkworks-rs/algebra/" }
|
||||||
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }
|
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
# Curve implementations
|
# Notice
|
||||||
|
|
||||||
|
This repository is no longer maintained, and PRs to add or modify curves should instead be made against [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra); all the curves implemented here have moved to the [`curves` folder](https://github.com/arkworks-rs/algebra/tree/master/curves) of that repository.
|
||||||
|
|
||||||
|
## Curve implementations
|
||||||
|
|
||||||
This repository contains implementations of some popular elliptic curves. The curve API implemented here matches the curve traits defined [here](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) in the [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra) repository.
|
This repository contains implementations of some popular elliptic curves. The curve API implemented here matches the curve traits defined [here](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) in the [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra) repository.
|
||||||
|
|
||||||
@@ -20,6 +24,7 @@ This repository contains implementations of some popular elliptic curves. The cu
|
|||||||
### BN254 and related curves
|
### BN254 and related curves
|
||||||
* [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve
|
* [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve
|
||||||
* [`ark-ed-on-bn254`](ed_on_bn254): Implements a Twisted Edwards curve atop the scalar field of BN254
|
* [`ark-ed-on-bn254`](ed_on_bn254): Implements a Twisted Edwards curve atop the scalar field of BN254
|
||||||
|
* [`ark-grumpkin`](grumpkin): Implements the Grumpkin curve. A curve that forms a cycle with bn254.
|
||||||
|
|
||||||
### MNT-298 cycle of curves and related curves
|
### MNT-298 cycle of curves and related curves
|
||||||
* [`ark-mnt4-298`](mnt4_298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298
|
* [`ark-mnt4-298`](mnt4_298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ use ark_ec::{
|
|||||||
bls12::Bls12Config,
|
bls12::Bls12Config,
|
||||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||||
models::{
|
models::{
|
||||||
short_weierstrass::{Affine as SWAffine, SWCurveConfig},
|
short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig},
|
||||||
twisted_edwards::{
|
twisted_edwards::{
|
||||||
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
|
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
CurveConfig,
|
CurveConfig,
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, PrimeField, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
use ark_std::{ops::Neg, One};
|
use ark_std::{ops::Neg, One};
|
||||||
|
|
||||||
use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};
|
use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};
|
||||||
@@ -49,6 +50,12 @@ impl SWCurveConfig for Config {
|
|||||||
Self::BaseField::zero()
|
Self::BaseField::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
|
||||||
|
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
|
||||||
|
GLVConfig::glv_mul_projective(*p, s)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine {
|
fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine {
|
||||||
// Using the effective cofactor.
|
// Using the effective cofactor.
|
||||||
@@ -59,6 +66,34 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static[Self::BaseField] = &[
|
||||||
|
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231")
|
||||||
|
];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("8444461749428370424248824938781546531284005582649182570233710176290576793600");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(true, BigInt!("91893752504881257701523279626832445441")),
|
||||||
|
(true, BigInt!("1")),
|
||||||
|
(false, BigInt!("1")),
|
||||||
|
(true, BigInt!("91893752504881257701523279626832445440")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &SWProjective<Self>) -> SWProjective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &SWAffine<Self>) -> SWAffine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn x_minus_one() -> Fr {
|
fn x_minus_one() -> Fr {
|
||||||
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
||||||
X - Fr::one()
|
X - Fr::one()
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use ark_ec::{
|
|||||||
bls12,
|
bls12,
|
||||||
bls12::Bls12Config,
|
bls12::Bls12Config,
|
||||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||||
models::CurveConfig,
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
||||||
AffineRepr, CurveGroup, Group,
|
AffineRepr, CurveConfig, CurveGroup, PrimeGroup,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
use ark_std::ops::Neg;
|
use ark_std::ops::Neg;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
@@ -98,6 +98,36 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static[Self::BaseField] = &[
|
||||||
|
Fq2::new(
|
||||||
|
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
|
||||||
|
Fq::ZERO
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField = MontFp!("91893752504881257701523279626832445440");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("91893752504881257701523279626832445440")),
|
||||||
|
(true, BigInt!("1")),
|
||||||
|
(false, BigInt!("1")),
|
||||||
|
(false, BigInt!("91893752504881257701523279626832445441")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
||||||
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ test_group!(g1; G1Projective; sw);
|
|||||||
test_group!(g2; G2Projective; sw);
|
test_group!(g2; G2Projective; sw);
|
||||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
|
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
|
||||||
test_pairing!(pairing; crate::Bls12_377);
|
test_pairing!(pairing; crate::Bls12_377);
|
||||||
|
test_group!(g1_glv; G1Projective; glv);
|
||||||
|
test_group!(g2_glv; G2Projective; glv);
|
||||||
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
|
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
|
||||||
test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
|
test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use ark_algebra_bench_templates::*;
|
use ark_algebra_bench_templates::*;
|
||||||
|
|
||||||
use ark_bls12_381::{
|
use ark_bls12_381::{
|
||||||
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
|
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ use ark_ec::{
|
|||||||
bls12::Bls12Config,
|
bls12::Bls12Config,
|
||||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{Affine, SWCurveConfig},
|
short_weierstrass::{Affine, SWCurveConfig},
|
||||||
AffineRepr, Group,
|
AffineRepr, PrimeGroup,
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, PrimeField, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
|
||||||
use ark_serialize::{Compress, SerializationError};
|
use ark_serialize::{Compress, SerializationError};
|
||||||
use ark_std::{ops::Neg, One};
|
use ark_std::{ops::Neg, One};
|
||||||
|
|
||||||
@@ -52,6 +53,12 @@ impl SWCurveConfig for Config {
|
|||||||
Self::BaseField::zero()
|
Self::BaseField::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
|
||||||
|
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
|
||||||
|
GLVConfig::glv_mul_projective(*p, s)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
|
fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
|
||||||
// Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
|
// Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
|
||||||
@@ -142,6 +149,34 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static[Self::BaseField] = &[
|
||||||
|
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350")
|
||||||
|
];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("52435875175126190479447740508185965837461563690374988244538805122978187051009");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(true, BigInt!("228988810152649578064853576960394133504")),
|
||||||
|
(true, BigInt!("1")),
|
||||||
|
(false, BigInt!("1")),
|
||||||
|
(true, BigInt!("228988810152649578064853576960394133503")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &G1Projective) -> G1Projective {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn one_minus_x() -> Fr {
|
fn one_minus_x() -> Fr {
|
||||||
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
|
||||||
Fr::one() - X
|
Fr::one() - X
|
||||||
@@ -180,6 +215,7 @@ mod test {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::g1;
|
use crate::g1;
|
||||||
|
use ark_serialize::CanonicalDeserialize;
|
||||||
use ark_std::{rand::Rng, UniformRand};
|
use ark_std::{rand::Rng, UniformRand};
|
||||||
|
|
||||||
fn sample_unchecked() -> Affine<g1::Config> {
|
fn sample_unchecked() -> Affine<g1::Config> {
|
||||||
@@ -204,4 +240,55 @@ mod test {
|
|||||||
assert!(p.is_in_correct_subgroup_assuming_on_curve());
|
assert!(p.is_in_correct_subgroup_assuming_on_curve());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn non_canonical_identity_point() {
|
||||||
|
let non_canonical_hex = "c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
|
||||||
|
assert_eq!(non_canonical_bytes.len(), 48);
|
||||||
|
|
||||||
|
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
|
||||||
|
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
|
||||||
|
|
||||||
|
assert!(maybe_affine_point.is_err());
|
||||||
|
|
||||||
|
let non_canonical_hex_uncompressed = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
|
||||||
|
let non_canonical_bytes = hex::decode(non_canonical_hex_uncompressed).unwrap();
|
||||||
|
assert_eq!(non_canonical_bytes.len(), 96);
|
||||||
|
|
||||||
|
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
|
||||||
|
CanonicalDeserialize::deserialize_uncompressed(&non_canonical_bytes[..]);
|
||||||
|
|
||||||
|
assert!(maybe_affine_point.is_err())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bad_flag_combination() {
|
||||||
|
// See https://github.com/zkcrypto/pairing/tree/fa8103764a07bd273927447d434de18aace252d3/src/bls12_381#serialization
|
||||||
|
// - Bit 1 is compressed/uncompressed
|
||||||
|
// - Bit 2 is infinity
|
||||||
|
// - Bit 3 is lexicographical order for compressed point deserialization
|
||||||
|
// Hence `0b1110` ("e" in hex) or `0b0110` ("6" in hex") are both nonsensical.
|
||||||
|
|
||||||
|
// uncompressed, but lexicographically largest flag is set
|
||||||
|
let non_canonical_hex = "600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
|
||||||
|
assert_eq!(non_canonical_bytes.len(), 48);
|
||||||
|
|
||||||
|
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
|
||||||
|
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
|
||||||
|
|
||||||
|
assert!(maybe_affine_point.is_err());
|
||||||
|
|
||||||
|
// compressed, but infinity flag is set and lexicographically largest flag is
|
||||||
|
// set
|
||||||
|
let non_canonical_hex_2 = "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
|
||||||
|
let non_canonical_bytes = hex::decode(non_canonical_hex_2).unwrap();
|
||||||
|
assert_eq!(non_canonical_bytes.len(), 48);
|
||||||
|
|
||||||
|
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
|
||||||
|
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
|
||||||
|
assert!(maybe_affine_point.is_err());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ use ark_ec::{
|
|||||||
bls12::Bls12Config,
|
bls12::Bls12Config,
|
||||||
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
|
||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
||||||
AffineRepr, CurveGroup, Group,
|
AffineRepr, CurveGroup, PrimeGroup,
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
use ark_serialize::{Compress, SerializationError};
|
use ark_serialize::{Compress, SerializationError};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -185,6 +186,36 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static[Self::BaseField] = &[
|
||||||
|
Fq2::new(
|
||||||
|
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
|
||||||
|
Fq::ZERO
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField = MontFp!("228988810152649578064853576960394133503");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("228988810152649578064853576960394133503")),
|
||||||
|
(true, BigInt!("1")),
|
||||||
|
(false, BigInt!("1")),
|
||||||
|
(false, BigInt!("228988810152649578064853576960394133504")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
||||||
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use ark_algebra_test_templates::*;
|
use ark_algebra_test_templates::*;
|
||||||
use ark_ec::{AffineRepr, CurveGroup, Group};
|
use ark_ec::{AffineRepr, CurveGroup, PrimeGroup};
|
||||||
use ark_ff::{fields::Field, One, UniformRand, Zero};
|
use ark_ff::{fields::Field, One, UniformRand, Zero};
|
||||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
|
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
|
||||||
use ark_std::{rand::Rng, test_rng, vec};
|
use ark_std::{rand::Rng, test_rng, vec};
|
||||||
@@ -8,6 +8,8 @@ use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projecti
|
|||||||
|
|
||||||
test_group!(g1; G1Projective; sw);
|
test_group!(g1; G1Projective; sw);
|
||||||
test_group!(g2; G2Projective; sw);
|
test_group!(g2; G2Projective; sw);
|
||||||
|
test_group!(g1_glv; G1Projective; glv);
|
||||||
|
test_group!(g2_glv; G2Projective; glv);
|
||||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm);
|
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm);
|
||||||
test_pairing!(pairing; crate::Bls12_381);
|
test_pairing!(pairing; crate::Bls12_381);
|
||||||
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
|
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
|
||||||
|
|||||||
@@ -14,17 +14,28 @@ pub struct EncodingFlags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EncodingFlags {
|
impl EncodingFlags {
|
||||||
pub fn get_flags(bytes: &[u8]) -> Self {
|
/// Fetches the flags from the byte-string
|
||||||
|
pub fn get_flags(bytes: &[u8]) -> Result<Self, SerializationError> {
|
||||||
let compression_flag_set = (bytes[0] >> 7) & 1;
|
let compression_flag_set = (bytes[0] >> 7) & 1;
|
||||||
let infinity_flag_set = (bytes[0] >> 6) & 1;
|
let infinity_flag_set = (bytes[0] >> 6) & 1;
|
||||||
let sort_flag_set = (bytes[0] >> 5) & 1;
|
let sort_flag_set = (bytes[0] >> 5) & 1;
|
||||||
|
|
||||||
Self {
|
let is_compressed = compression_flag_set == 1;
|
||||||
is_compressed: compression_flag_set == 1,
|
let is_infinity = infinity_flag_set == 1;
|
||||||
is_infinity: infinity_flag_set == 1,
|
let is_lexographically_largest = sort_flag_set == 1;
|
||||||
is_lexographically_largest: sort_flag_set == 1,
|
|
||||||
|
if is_lexographically_largest && (!is_compressed || is_infinity) {
|
||||||
|
return Err(SerializationError::InvalidData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
is_compressed,
|
||||||
|
is_infinity,
|
||||||
|
is_lexographically_largest,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encodes the flags into the byte-string
|
||||||
pub fn encode_flags(&self, bytes: &mut [u8]) {
|
pub fn encode_flags(&self, bytes: &mut [u8]) {
|
||||||
if self.is_compressed {
|
if self.is_compressed {
|
||||||
bytes[0] |= 1 << 7;
|
bytes[0] |= 1 << 7;
|
||||||
@@ -38,6 +49,13 @@ impl EncodingFlags {
|
|||||||
bytes[0] |= 1 << 5;
|
bytes[0] |= 1 << 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the flags from the byte-string.
|
||||||
|
///
|
||||||
|
/// This reverses the effects of `encode_flags`.
|
||||||
|
pub fn remove_flags(bytes: &mut [u8]) {
|
||||||
|
bytes[0] &= 0b0001_1111;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> {
|
pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> {
|
||||||
@@ -71,20 +89,15 @@ pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_fq_with_offset(
|
fn read_bytes_with_offset(bytes: &[u8], offset: usize, mask: bool) -> [u8; G1_SERIALIZED_SIZE] {
|
||||||
bytes: &[u8],
|
|
||||||
offset: usize,
|
|
||||||
mask: bool,
|
|
||||||
) -> Result<Fq, ark_serialize::SerializationError> {
|
|
||||||
let mut tmp = [0; G1_SERIALIZED_SIZE];
|
let mut tmp = [0; G1_SERIALIZED_SIZE];
|
||||||
// read `G1_SERIALIZED_SIZE` bytes
|
// read `G1_SERIALIZED_SIZE` bytes
|
||||||
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
|
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
|
||||||
|
|
||||||
if mask {
|
if mask {
|
||||||
// Mask away the flag bits
|
EncodingFlags::remove_flags(&mut tmp);
|
||||||
tmp[0] &= 0b0001_1111;
|
|
||||||
}
|
}
|
||||||
deserialize_fq(tmp).ok_or(SerializationError::InvalidData)
|
tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
|
pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
|
||||||
@@ -97,20 +110,26 @@ pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
|
|||||||
.ok_or(SerializationError::InvalidData)?;
|
.ok_or(SerializationError::InvalidData)?;
|
||||||
|
|
||||||
// Obtain the three flags from the start of the byte sequence
|
// Obtain the three flags from the start of the byte sequence
|
||||||
let flags = EncodingFlags::get_flags(&bytes[..]);
|
let flags = EncodingFlags::get_flags(&bytes[..])?;
|
||||||
|
|
||||||
// we expect to be deserializing a compressed point
|
// We expect to be deserializing a compressed point
|
||||||
if !flags.is_compressed {
|
if !flags.is_compressed {
|
||||||
return Err(SerializationError::UnexpectedFlags);
|
return Err(SerializationError::UnexpectedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to obtain the x-coordinate
|
||||||
|
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
|
||||||
|
|
||||||
if flags.is_infinity {
|
if flags.is_infinity {
|
||||||
|
// Check that the `x` co-ordinate was `0`
|
||||||
|
if x_bytes != [0u8; 48] {
|
||||||
|
return Err(SerializationError::InvalidData);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(G1Affine::zero());
|
return Ok(G1Affine::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to obtain the x-coordinate
|
let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
let x = read_fq_with_offset(&bytes, 0, true)?;
|
|
||||||
|
|
||||||
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
|
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
|
||||||
.ok_or(SerializationError::InvalidData)?;
|
.ok_or(SerializationError::InvalidData)?;
|
||||||
|
|
||||||
@@ -126,22 +145,27 @@ pub(crate) fn read_g1_uncompressed<R: ark_serialize::Read>(
|
|||||||
.map_err(|_| SerializationError::InvalidData)?;
|
.map_err(|_| SerializationError::InvalidData)?;
|
||||||
|
|
||||||
// Obtain the three flags from the start of the byte sequence
|
// Obtain the three flags from the start of the byte sequence
|
||||||
let flags = EncodingFlags::get_flags(&bytes[..]);
|
let flags = EncodingFlags::get_flags(&bytes[..])?;
|
||||||
|
|
||||||
// we expect to be deserializing an uncompressed point
|
// we expect to be deserializing an uncompressed point
|
||||||
if flags.is_compressed {
|
if flags.is_compressed {
|
||||||
return Err(SerializationError::UnexpectedFlags);
|
return Err(SerializationError::UnexpectedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
|
||||||
|
let y_bytes = read_bytes_with_offset(&bytes, 1, false);
|
||||||
|
|
||||||
if flags.is_infinity {
|
if flags.is_infinity {
|
||||||
|
if x_bytes != [0u8; 48] || y_bytes != [0u8; 48] {
|
||||||
|
return Err(SerializationError::InvalidData);
|
||||||
|
}
|
||||||
return Ok(G1Affine::zero());
|
return Ok(G1Affine::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to obtain the x-coordinate
|
// Attempt to obtain the x-coordinate
|
||||||
let x = read_fq_with_offset(&bytes, 0, true)?;
|
let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
// Attempt to obtain the y-coordinate
|
// Attempt to obtain the y-coordinate
|
||||||
let y = read_fq_with_offset(&bytes, 1, false)?;
|
let y = deserialize_fq(y_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
|
||||||
let p = G1Affine::new_unchecked(x, y);
|
let p = G1Affine::new_unchecked(x, y);
|
||||||
|
|
||||||
Ok(p)
|
Ok(p)
|
||||||
@@ -156,21 +180,26 @@ pub(crate) fn read_g2_compressed<R: ark_serialize::Read>(
|
|||||||
.map_err(|_| SerializationError::InvalidData)?;
|
.map_err(|_| SerializationError::InvalidData)?;
|
||||||
|
|
||||||
// Obtain the three flags from the start of the byte sequence
|
// Obtain the three flags from the start of the byte sequence
|
||||||
let flags = EncodingFlags::get_flags(&bytes);
|
let flags = EncodingFlags::get_flags(&bytes)?;
|
||||||
|
|
||||||
// we expect to be deserializing a compressed point
|
// we expect to be deserializing a compressed point
|
||||||
if !flags.is_compressed {
|
if !flags.is_compressed {
|
||||||
return Err(SerializationError::UnexpectedFlags);
|
return Err(SerializationError::UnexpectedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
|
||||||
|
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
|
||||||
|
|
||||||
if flags.is_infinity {
|
if flags.is_infinity {
|
||||||
|
if xc1_bytes != [0u8; 48] || xc0_bytes != [0u8; 48] {
|
||||||
|
return Err(SerializationError::InvalidData);
|
||||||
|
}
|
||||||
return Ok(G2Affine::zero());
|
return Ok(G2Affine::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to obtain the x-coordinate
|
// Attempt to obtain the x-coordinate
|
||||||
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
|
let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
|
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
|
||||||
let x = Fq2::new(xc0, xc1);
|
let x = Fq2::new(xc0, xc1);
|
||||||
|
|
||||||
let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
|
let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
|
||||||
@@ -188,25 +217,39 @@ pub(crate) fn read_g2_uncompressed<R: ark_serialize::Read>(
|
|||||||
.map_err(|_| SerializationError::InvalidData)?;
|
.map_err(|_| SerializationError::InvalidData)?;
|
||||||
|
|
||||||
// Obtain the three flags from the start of the byte sequence
|
// Obtain the three flags from the start of the byte sequence
|
||||||
let flags = EncodingFlags::get_flags(&bytes);
|
let flags = EncodingFlags::get_flags(&bytes)?;
|
||||||
|
|
||||||
// we expect to be deserializing an uncompressed point
|
// we expect to be deserializing an uncompressed point
|
||||||
if flags.is_compressed {
|
if flags.is_compressed {
|
||||||
return Err(SerializationError::UnexpectedFlags);
|
return Err(SerializationError::UnexpectedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
|
||||||
|
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
|
||||||
|
|
||||||
|
let yc1_bytes = read_bytes_with_offset(&bytes, 2, false);
|
||||||
|
let yc0_bytes = read_bytes_with_offset(&bytes, 3, false);
|
||||||
|
|
||||||
if flags.is_infinity {
|
if flags.is_infinity {
|
||||||
|
if xc1_bytes != [0u8; 48]
|
||||||
|
|| xc0_bytes != [0u8; 48]
|
||||||
|
|| yc1_bytes != [0u8; 48]
|
||||||
|
|| yc0_bytes != [0u8; 48]
|
||||||
|
{
|
||||||
|
return Err(SerializationError::InvalidData);
|
||||||
|
}
|
||||||
return Ok(G2Affine::zero());
|
return Ok(G2Affine::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
let yc1 = deserialize_fq(yc1_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
let yc0 = deserialize_fq(yc0_bytes).ok_or(SerializationError::InvalidData)?;
|
||||||
|
|
||||||
// Attempt to obtain the x-coordinate
|
// Attempt to obtain the x-coordinate
|
||||||
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
|
|
||||||
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
|
|
||||||
let x = Fq2::new(xc0, xc1);
|
let x = Fq2::new(xc0, xc1);
|
||||||
|
|
||||||
// Attempt to obtain the y-coordinate
|
// Attempt to obtain the y-coordinate
|
||||||
let yc1 = read_fq_with_offset(&bytes, 2, false)?;
|
|
||||||
let yc0 = read_fq_with_offset(&bytes, 3, false)?;
|
|
||||||
let y = Fq2::new(yc0, yc1);
|
let y = Fq2::new(yc0, yc1);
|
||||||
|
|
||||||
let p = G2Affine::new_unchecked(x, y);
|
let p = G2Affine::new_unchecked(x, y);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
biginteger::{BigInt, BigInteger, BigInteger384},
|
biginteger::{BigInt, BigInteger, BigInteger384},
|
||||||
fields::{FftField, Field, Fp12Config, Fp2Config, Fp6Config, PrimeField},
|
fields::{FftField, Field, Fp12Config, Fp2Config, Fp6Config, PrimeField},
|
||||||
One, UniformRand, Zero,
|
AdditiveGroup, One, UniformRand, Zero,
|
||||||
};
|
};
|
||||||
use ark_std::{
|
use ark_std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
|
bn,
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
short_weierstrass::Affine,
|
scalar_mul::glv::GLVConfig,
|
||||||
|
short_weierstrass::{Affine, Projective},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
|
|
||||||
use crate::{Fq, Fr};
|
use crate::{Fq, Fr};
|
||||||
|
|
||||||
@@ -36,6 +38,42 @@ impl SWCurveConfig for Config {
|
|||||||
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
|
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
|
||||||
Self::BaseField::zero()
|
Self::BaseField::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_projective(
|
||||||
|
p: &bn::G1Projective<crate::Config>,
|
||||||
|
scalar: &[u64],
|
||||||
|
) -> bn::G1Projective<crate::Config> {
|
||||||
|
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
|
||||||
|
GLVConfig::glv_mul_projective(*p, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
|
||||||
|
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
|
||||||
|
)];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("21888242871839275217838484774961031246154997185409878258781734729429964517155");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("147946756881789319000765030803803410728")),
|
||||||
|
(true, BigInt!("9931322734385697763")),
|
||||||
|
(false, BigInt!("9931322734385697763")),
|
||||||
|
(false, BigInt!("147946756881789319010696353538189108491")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// G1_GENERATOR_X = 1
|
/// G1_GENERATOR_X = 1
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
short_weierstrass::Affine,
|
scalar_mul::glv::GLVConfig,
|
||||||
|
short_weierstrass::{Affine, Projective},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fr};
|
use crate::{Fq, Fq2, Fr};
|
||||||
|
|
||||||
@@ -50,6 +51,35 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[Fq2::new(
|
||||||
|
MontFp!("21888242871839275220042445260109153167277707414472061641714758635765020556616"),
|
||||||
|
Fq::ZERO,
|
||||||
|
)];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("4407920970296243842393367215006156084916469457145843978461");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("147946756881789319010696353538189108491")),
|
||||||
|
(false, BigInt!("9931322734385697763")),
|
||||||
|
(true, BigInt!("9931322734385697763")),
|
||||||
|
(false, BigInt!("147946756881789319000765030803803410728")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
|
||||||
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ test_group!(g1; G1Projective; sw);
|
|||||||
test_group!(g2; G2Projective; sw);
|
test_group!(g2; G2Projective; sw);
|
||||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
|
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
|
||||||
test_pairing!(pairing; crate::Bn254);
|
test_pairing!(pairing; crate::Bn254);
|
||||||
|
test_group!(g1_glv; G1Projective; glv);
|
||||||
|
test_group!(g2_glv; G2Projective; glv);
|
||||||
|
|||||||
@@ -3,5 +3,7 @@ use ark_ff::fields::{Fp256, MontBackend, MontConfig};
|
|||||||
#[derive(MontConfig)]
|
#[derive(MontConfig)]
|
||||||
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
|
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
|
||||||
#[generator = "5"]
|
#[generator = "5"]
|
||||||
|
#[small_subgroup_base = "3"]
|
||||||
|
#[small_subgroup_power = "2"]
|
||||||
pub struct FrConfig;
|
pub struct FrConfig;
|
||||||
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;
|
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{Affine, Projective},
|
short_weierstrass::{Affine, Projective},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
|
||||||
|
|
||||||
use crate::{Fq, Fr};
|
use crate::{Fq, Fr};
|
||||||
|
|
||||||
@@ -49,6 +50,46 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
|
||||||
|
"4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"
|
||||||
|
)];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("293634935485640680722085584138834120324914961969255022593"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
false,
|
||||||
|
BigInt!("293634935485640680722085584138834120315328839056164388863"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("293634935485640680722085584138834120315328839056164388863"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("587269870971281361444171168277668240640243801025419411456"),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// G1_GENERATOR_X =
|
/// G1_GENERATOR_X =
|
||||||
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
|
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
|
||||||
pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");
|
pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{Affine, Projective},
|
short_weierstrass::{Affine, Projective},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
|
||||||
|
|
||||||
use crate::{Fq, Fr};
|
use crate::{Fq, Fr};
|
||||||
|
|
||||||
@@ -50,6 +51,46 @@ impl SWCurveConfig for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for Config {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[
|
||||||
|
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("293634935485640680722085584138834120315328839056164388863"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
false,
|
||||||
|
BigInt!("293634935485640680722085584138834120324914961969255022593"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("293634935485640680722085584138834120324914961969255022593"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
true,
|
||||||
|
BigInt!("587269870971281361444171168277668240640243801025419411456"),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// G2_GENERATOR_X =
|
/// G2_GENERATOR_X =
|
||||||
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
|
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
|
||||||
pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");
|
pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ use ark_ec::{
|
|||||||
bw6,
|
bw6,
|
||||||
bw6::{BW6Config, TwistType, BW6},
|
bw6::{BW6Config, TwistType, BW6},
|
||||||
};
|
};
|
||||||
use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt};
|
use ark_ff::{
|
||||||
|
biginteger::BigInteger768 as BigInteger, fp6_2over3::Fp6, BigInt, CyclotomicMultSubgroup, Field,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@@ -16,42 +18,141 @@ mod tests;
|
|||||||
pub struct Config;
|
pub struct Config;
|
||||||
|
|
||||||
impl BW6Config for Config {
|
impl BW6Config for Config {
|
||||||
const X: BigInteger = BigInt::new([
|
const X: BigInteger = BigInt!("0x8508c00000000001");
|
||||||
0x8508c00000000001,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
]);
|
|
||||||
/// `x` is positive.
|
/// `x` is positive.
|
||||||
const X_IS_NEGATIVE: bool = false;
|
const X_IS_NEGATIVE: bool = false;
|
||||||
|
// X
|
||||||
|
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000001];
|
||||||
|
// (X-1)/3
|
||||||
|
const X_MINUS_1_DIV_3: BigInteger = BigInt!("0x2c58400000000000");
|
||||||
// X+1
|
// X+1
|
||||||
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002];
|
|
||||||
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false;
|
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false;
|
||||||
// X^3-X^2-X
|
// X^2-X-1
|
||||||
const ATE_LOOP_COUNT_2: &'static [i8] = &[
|
const ATE_LOOP_COUNT_2: &'static [i8] = &[
|
||||||
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
|
0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
|
||||||
0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0,
|
0, 1, 0, 1, 0, 0, 0, 1,
|
||||||
1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 1, 0, 0, 0, 1,
|
|
||||||
0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
|
|
||||||
];
|
];
|
||||||
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
|
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
|
||||||
const TWIST_TYPE: TwistType = TwistType::M;
|
const TWIST_TYPE: TwistType = TwistType::M;
|
||||||
|
const H_T: i64 = 13;
|
||||||
|
const H_Y: i64 = 9;
|
||||||
|
const T_MOD_R_IS_ZERO: bool = false;
|
||||||
type Fp = Fq;
|
type Fp = Fq;
|
||||||
type Fp3Config = Fq3Config;
|
type Fp3Config = Fq3Config;
|
||||||
type Fp6Config = Fq6Config;
|
type Fp6Config = Fq6Config;
|
||||||
type G1Config = g1::Config;
|
type G1Config = g1::Config;
|
||||||
type G2Config = g2::Config;
|
type G2Config = g2::Config;
|
||||||
|
|
||||||
|
fn final_exponentiation_hard_part(f: &Fp6<Self::Fp6Config>) -> Fp6<Self::Fp6Config> {
|
||||||
|
// hard_part
|
||||||
|
// From https://eprint.iacr.org/2020/351.pdf, Alg.6
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
// R0(x) := (-103*x^7 + 70*x^6 + 269*x^5 - 197*x^4 - 314*x^3 - 73*x^2 - 263*x - 220)
|
||||||
|
// R1(x) := (103*x^9 - 276*x^8 + 77*x^7 + 492*x^6 - 445*x^5 - 65*x^4 + 452*x^3 - 181*x^2 + 34*x + 229)
|
||||||
|
// f ^ R0(u) * (f ^ q) ^ R1(u) in a 2-NAF multi-exp fashion.
|
||||||
|
|
||||||
|
// steps 1,2,3
|
||||||
|
let f0 = *f;
|
||||||
|
let mut f0p = f0;
|
||||||
|
f0p.frobenius_map_in_place(1);
|
||||||
|
let f1 = Self::exp_by_x(&f0);
|
||||||
|
let mut f1p = f1;
|
||||||
|
f1p.frobenius_map_in_place(1);
|
||||||
|
let f2 = Self::exp_by_x(&f1);
|
||||||
|
let mut f2p = f2;
|
||||||
|
f2p.frobenius_map_in_place(1);
|
||||||
|
let f3 = Self::exp_by_x(&f2);
|
||||||
|
let mut f3p = f3;
|
||||||
|
f3p.frobenius_map_in_place(1);
|
||||||
|
let f4 = Self::exp_by_x(&f3);
|
||||||
|
let mut f4p = f4;
|
||||||
|
f4p.frobenius_map_in_place(1);
|
||||||
|
let f5 = Self::exp_by_x(&f4);
|
||||||
|
let mut f5p = f5;
|
||||||
|
f5p.frobenius_map_in_place(1);
|
||||||
|
let f6 = Self::exp_by_x(&f5);
|
||||||
|
let mut f6p = f6;
|
||||||
|
f6p.frobenius_map_in_place(1);
|
||||||
|
let f7 = Self::exp_by_x(&f6);
|
||||||
|
let mut f7p = f7;
|
||||||
|
f7p.frobenius_map_in_place(1);
|
||||||
|
|
||||||
|
// step 4
|
||||||
|
let f8p = Self::exp_by_x(&f7p);
|
||||||
|
let f9p = Self::exp_by_x(&f8p);
|
||||||
|
|
||||||
|
// step 5
|
||||||
|
let mut f5p_p3 = f5p;
|
||||||
|
f5p_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result1 = f3p * &f6p * &f5p_p3;
|
||||||
|
|
||||||
|
// step 6
|
||||||
|
let result2 = result1.square();
|
||||||
|
let f4_2p = f4 * &f2p;
|
||||||
|
let mut tmp1_p3 = f0 * &f1 * &f3 * &f4_2p * &f8p;
|
||||||
|
tmp1_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result3 = result2 * &f5 * &f0p * &tmp1_p3;
|
||||||
|
|
||||||
|
// step 7
|
||||||
|
let result4 = result3.square();
|
||||||
|
let mut f7_p3 = f7;
|
||||||
|
f7_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result5 = result4 * &f9p * &f7_p3;
|
||||||
|
|
||||||
|
// step 8
|
||||||
|
let result6 = result5.square();
|
||||||
|
let f2_4p = f2 * &f4p;
|
||||||
|
let f4_2p_5p = f4_2p * &f5p;
|
||||||
|
let mut tmp2_p3 = f2_4p * &f3 * &f3p;
|
||||||
|
tmp2_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result7 = result6 * &f4_2p_5p * &f6 * &f7p * &tmp2_p3;
|
||||||
|
|
||||||
|
// step 9
|
||||||
|
let result8 = result7.square();
|
||||||
|
let mut tmp3_p3 = f0p * &f9p;
|
||||||
|
tmp3_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result9 = result8 * &f0 * &f7 * &f1p * &tmp3_p3;
|
||||||
|
|
||||||
|
// step 10
|
||||||
|
let result10 = result9.square();
|
||||||
|
let f6p_8p = f6p * &f8p;
|
||||||
|
let f5_7p = f5 * &f7p;
|
||||||
|
let mut tmp4_p3 = f6p_8p;
|
||||||
|
tmp4_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result11 = result10 * &f5_7p * &f2p * &tmp4_p3;
|
||||||
|
|
||||||
|
// step 11
|
||||||
|
let result12 = result11.square();
|
||||||
|
let f3_6 = f3 * &f6;
|
||||||
|
let f1_7 = f1 * &f7;
|
||||||
|
let mut tmp5_p3 = f1_7 * &f2;
|
||||||
|
tmp5_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result13 = result12 * &f3_6 * &f9p * &tmp5_p3;
|
||||||
|
|
||||||
|
// step 12
|
||||||
|
let result14 = result13.square();
|
||||||
|
let mut tmp6_p3 = f4_2p * &f5_7p * &f6p_8p;
|
||||||
|
tmp6_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result15 = result14 * &f0 * &f0p * &f3p * &f5p * &tmp6_p3;
|
||||||
|
|
||||||
|
// step 13
|
||||||
|
let result16 = result15.square();
|
||||||
|
let mut tmp7_p3 = f3_6;
|
||||||
|
tmp7_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result17 = result16 * &f1p * &tmp7_p3;
|
||||||
|
|
||||||
|
// step 14
|
||||||
|
let result18 = result17.square();
|
||||||
|
let mut tmp8_p3 = f2_4p * &f4_2p_5p * &f9p;
|
||||||
|
tmp8_p3.cyclotomic_inverse_in_place();
|
||||||
|
let result19 = result18 * &f1_7 * &f5_7p * &f0p * &tmp8_p3;
|
||||||
|
|
||||||
|
result19
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BW6_761 = BW6<Config>;
|
pub type BW6_761 = BW6<Config>;
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ test_group!(g1; G1Projective; sw);
|
|||||||
test_group!(g2; G2Projective; sw);
|
test_group!(g2; G2Projective; sw);
|
||||||
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
|
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
|
||||||
test_pairing!(pairing; crate::BW6_761);
|
test_pairing!(pairing; crate::BW6_761);
|
||||||
|
test_group!(g1_glv; G1Projective; glv);
|
||||||
|
test_group!(g2_glv; G2Projective; glv);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp3::{Fp3, Fp3Config},
|
fields::fp3::{Fp3, Fp3Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Fq;
|
use crate::Fq;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq3, Fq3Config};
|
use crate::{Fq, Fq3, Fq3Config};
|
||||||
|
|||||||
33
bw6_767/Cargo.toml
Normal file
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},
|
short_weierstrass::{Affine, Projective, SWCurveConfig},
|
||||||
AffineRepr, CurveGroup,
|
AffineRepr, CurveGroup,
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||||
use ark_std::vec::Vec;
|
use ark_std::vec::Vec;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use ark_ec::{
|
|||||||
pairing::{MillerLoopOutput, Pairing, PairingOutput},
|
pairing::{MillerLoopOutput, Pairing, PairingOutput},
|
||||||
};
|
};
|
||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
biginteger::BigInteger832, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field, One,
|
biginteger::BigInteger832, AdditiveGroup, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field,
|
||||||
|
One,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
@@ -181,38 +182,6 @@ pub const ATE_LOOP_COUNT: [u64; 13] = [
|
|||||||
/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
|
/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
|
||||||
pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
||||||
|
|
||||||
/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 =
|
pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt!("7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033");
|
||||||
/// 7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033
|
|
||||||
pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt::new([
|
|
||||||
0xb62ef36af72855d1,
|
|
||||||
0x676b5cef49d290fa,
|
|
||||||
0xd17fcf3c60947427,
|
|
||||||
0x5b93d992bc1b2849,
|
|
||||||
0x2171887cecd072cb,
|
|
||||||
0x879a2873f1516f4a,
|
|
||||||
0x8cc6856bd2cdf24e,
|
|
||||||
0xbff4fb6644d01993,
|
|
||||||
0x5dcbeea3e31ea667,
|
|
||||||
0x5f256f47681649f3,
|
|
||||||
0x2355a2b0839967fe,
|
|
||||||
0x144ed,
|
|
||||||
0x0,
|
|
||||||
]);
|
|
||||||
|
|
||||||
/// FINAL_EXPONENT_LAST_CHUNK_W1 =
|
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt!("86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986");
|
||||||
/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
|
|
||||||
pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt::new([
|
|
||||||
0x5657b9b57b942aea,
|
|
||||||
0x84f9a65f3bd54eaf,
|
|
||||||
0x5ea4214e35cd127,
|
|
||||||
0xe3cbcbc14ec1501d,
|
|
||||||
0xf196cb845a3092ab,
|
|
||||||
0x7e14627ad0e19017,
|
|
||||||
0x217db4,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
]);
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp3::{Fp3, Fp3Config},
|
fields::fp3::{Fp3, Fp3Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Fq;
|
use crate::Fq;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq3, Fq3Config};
|
use crate::{Fq, Fq3, Fq3Config};
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ pub mod fields {
|
|||||||
pub mod curves {
|
pub mod curves {
|
||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective,
|
short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective,
|
||||||
CurveGroup, Group,
|
AdditiveGroup, CurveGroup,
|
||||||
};
|
};
|
||||||
use ark_ff::{BitIteratorLE, Field, One, PrimeField};
|
use ark_ff::{BitIteratorLE, Field, One, PrimeField};
|
||||||
use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
|
use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
|
||||||
@@ -315,12 +315,14 @@ pub mod curves {
|
|||||||
}
|
}
|
||||||
assert!(cs.is_satisfied().unwrap());
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
|
||||||
let modulus = <C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec();
|
let modulus = C::ScalarField::MODULUS.as_ref().to_vec();
|
||||||
let mut max = modulus.clone();
|
let mut max = modulus.clone();
|
||||||
for limb in &mut max {
|
for limb in &mut max {
|
||||||
*limb = u64::MAX;
|
*limb = u64::MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let num_limbs = max.len();
|
||||||
|
|
||||||
let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
|
let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
|
||||||
if modulus_num_bits_mod_64 != 0 {
|
if modulus_num_bits_mod_64 != 0 {
|
||||||
*max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
|
*max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
|
||||||
@@ -332,10 +334,10 @@ pub mod curves {
|
|||||||
.to_vec(),
|
.to_vec(),
|
||||||
vec![u64::rand(&mut rng)],
|
vec![u64::rand(&mut rng)],
|
||||||
(-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
|
(-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
|
||||||
<C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec(),
|
modulus,
|
||||||
max,
|
max,
|
||||||
vec![0; 50],
|
vec![0u64; num_limbs],
|
||||||
vec![1000012341233u64; 36],
|
vec![1000012341233u64; num_limbs],
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut input = vec![];
|
let mut input = vec![];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
biginteger::BigInteger256 as BigInteger,
|
biginteger::BigInteger256 as BigInteger,
|
||||||
fields::{Field, LegendreSymbol::*},
|
fields::{Field, LegendreSymbol::*},
|
||||||
One, Zero,
|
AdditiveGroup, One, Zero,
|
||||||
};
|
};
|
||||||
use ark_std::str::FromStr;
|
use ark_std::str::FromStr;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
|||||||
short_weierstrass::{self, SWCurveConfig},
|
short_weierstrass::{self, SWCurveConfig},
|
||||||
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
|
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
|
|
||||||
use crate::{Fq, Fr};
|
use crate::{Fq, Fr};
|
||||||
|
|
||||||
@@ -110,19 +110,19 @@ impl MontCurveConfig for BandersnatchConfig {
|
|||||||
// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
|
// <https://github.com/zhenfeizhang/bandersnatch/blob/main/bandersnatch/script/bandersnatch.sage>
|
||||||
|
|
||||||
/// x coordinate for TE curve generator
|
/// x coordinate for TE curve generator
|
||||||
const TE_GENERATOR_X: Fq =
|
pub const TE_GENERATOR_X: Fq =
|
||||||
MontFp!("18886178867200960497001835917649091219057080094937609519140440539760939937304");
|
MontFp!("18886178867200960497001835917649091219057080094937609519140440539760939937304");
|
||||||
|
|
||||||
/// y coordinate for TE curve generator
|
/// y coordinate for TE curve generator
|
||||||
const TE_GENERATOR_Y: Fq =
|
pub const TE_GENERATOR_Y: Fq =
|
||||||
MontFp!("19188667384257783945677642223292697773471335439753913231509108946878080696678");
|
MontFp!("19188667384257783945677642223292697773471335439753913231509108946878080696678");
|
||||||
|
|
||||||
/// x coordinate for SW curve generator
|
/// x coordinate for SW curve generator
|
||||||
const SW_GENERATOR_X: Fq =
|
pub const SW_GENERATOR_X: Fq =
|
||||||
MontFp!("30900340493481298850216505686589334086208278925799850409469406976849338430199");
|
MontFp!("30900340493481298850216505686589334086208278925799850409469406976849338430199");
|
||||||
|
|
||||||
/// y coordinate for SW curve generator
|
/// y coordinate for SW curve generator
|
||||||
const SW_GENERATOR_Y: Fq =
|
pub const SW_GENERATOR_Y: Fq =
|
||||||
MontFp!("12663882780877899054958035777720958383845500985908634476792678820121468453298");
|
MontFp!("12663882780877899054958035777720958383845500985908634476792678820121468453298");
|
||||||
|
|
||||||
impl SWCurveConfig for BandersnatchConfig {
|
impl SWCurveConfig for BandersnatchConfig {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_algebra_test_templates::*;
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
biginteger::BigInteger256 as BigInteger,
|
biginteger::BigInteger256 as BigInteger,
|
||||||
fields::{Field, LegendreSymbol::*},
|
fields::{Field, LegendreSymbol::*},
|
||||||
One, Zero,
|
AdditiveGroup, One, Zero,
|
||||||
};
|
};
|
||||||
use ark_std::str::FromStr;
|
use ark_std::str::FromStr;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_algebra_test_templates::*;
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
biginteger::BigInteger256 as BigInteger,
|
biginteger::BigInteger256 as BigInteger,
|
||||||
fields::{Field, LegendreSymbol::*},
|
fields::{Field, LegendreSymbol::*},
|
||||||
One, Zero,
|
AdditiveGroup, One, Zero,
|
||||||
};
|
};
|
||||||
use ark_std::str::FromStr;
|
use ark_std::str::FromStr;
|
||||||
|
|
||||||
|
|||||||
37
grumpkin/Cargo.toml
Normal file
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,
|
mnt4::MNT4Config,
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};
|
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use ark_ec::models::mnt4::{MNT4Config, MNT4};
|
use ark_ec::models::mnt4::{MNT4Config, MNT4};
|
||||||
use ark_ff::{biginteger::BigInteger320, BigInt, Field, MontFp};
|
use ark_ff::{biginteger::BigInteger320, AdditiveGroup, BigInt, Field, MontFp};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fq2Config, Fq4Config, Fr};
|
use crate::{Fq, Fq2, Fq2Config, Fq4Config, Fr};
|
||||||
|
|
||||||
@@ -38,10 +38,11 @@ impl MNT4Config for Config {
|
|||||||
0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0,
|
||||||
];
|
];
|
||||||
const ATE_IS_LOOP_COUNT_NEG: bool = false;
|
const ATE_IS_LOOP_COUNT_NEG: bool = false;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0]);
|
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt!("0x1");
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
|
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
|
||||||
|
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4_80.ml#L96
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
||||||
BigInt::new([993502997770534913, 5071219579242586943, 2027349, 0, 0]);
|
BigInt!("689871209842287392837045615510547309923794945");
|
||||||
type Fp = Fq;
|
type Fp = Fq;
|
||||||
type Fr = Fr;
|
type Fr = Fr;
|
||||||
type Fp2Config = Fq2Config;
|
type Fp2Config = Fq2Config;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp4::{Fp4, Fp4Config},
|
fields::fp4::{Fp4, Fp4Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fq2Config};
|
use crate::{Fq, Fq2, Fq2Config};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
|||||||
mnt4::MNT4Config,
|
mnt4::MNT4Config,
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};
|
use crate::{Fq, Fq2, Fr, G1_COEFF_A_NON_RESIDUE};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
use ark_ec::models::mnt4::{MNT4Config, MNT4};
|
use ark_ec::models::mnt4::{MNT4Config, MNT4};
|
||||||
use ark_ff::{
|
use ark_ff::{biginteger::BigInteger768, AdditiveGroup, BigInt, Field, Fp2, MontFp};
|
||||||
biginteger::{BigInt, BigInteger768},
|
|
||||||
Field, Fp2, MontFp,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{Fq, Fq2Config, Fq4Config, Fr};
|
use crate::{Fq, Fq2Config, Fq4Config, Fr};
|
||||||
|
|
||||||
@@ -48,23 +45,10 @@ impl MNT4Config for Config {
|
|||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
];
|
];
|
||||||
const ATE_IS_LOOP_COUNT_NEG: bool = true;
|
const ATE_IS_LOOP_COUNT_NEG: bool = true;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 =
|
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
|
||||||
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
|
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([
|
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4753.ml#L100
|
||||||
8824542903220142079,
|
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470399");
|
||||||
7711082599397206192,
|
|
||||||
8303354903384568230,
|
|
||||||
5874150271971943936,
|
|
||||||
9717849827920685054,
|
|
||||||
95829799234282493,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
]);
|
|
||||||
type Fp = Fq;
|
type Fp = Fq;
|
||||||
type Fr = Fr;
|
type Fr = Fr;
|
||||||
type Fp2Config = Fq2Config;
|
type Fp2Config = Fq2Config;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp4::{Fp4, Fp4Config},
|
fields::fp4::{Fp4, Fp4Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq2, Fq2Config};
|
use crate::{Fq, Fq2, Fq2Config};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
|||||||
mnt6::MNT6Config,
|
mnt6::MNT6Config,
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
|
|
||||||
use crate::{g1, Fq, Fq3, Fr};
|
use crate::{g1, Fq, Fq3, Fr};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
|||||||
models::mnt6::{MNT6Config, MNT6},
|
models::mnt6::{MNT6Config, MNT6},
|
||||||
short_weierstrass::SWCurveConfig,
|
short_weierstrass::SWCurveConfig,
|
||||||
};
|
};
|
||||||
use ark_ff::{biginteger::BigInteger320, BigInt, Field, Fp3};
|
use ark_ff::{biginteger::BigInteger320, AdditiveGroup, BigInt, Field, Fp3};
|
||||||
|
|
||||||
use crate::{Fq, Fq3Config, Fq6Config, Fr};
|
use crate::{Fq, Fq3Config, Fq6Config, Fr};
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ impl MNT6Config for Config {
|
|||||||
const TWIST_COEFF_A: Fp3<Self::Fp3Config> =
|
const TWIST_COEFF_A: Fp3<Self::Fp3Config> =
|
||||||
Fp3::<Self::Fp3Config>::new(Fq::ZERO, Fq::ZERO, g1::Config::COEFF_A);
|
Fp3::<Self::Fp3Config>::new(Fq::ZERO, Fq::ZERO, g1::Config::COEFF_A);
|
||||||
|
|
||||||
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt4_80.ml#L88
|
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6_80.ml#L118
|
||||||
const ATE_LOOP_COUNT: &'static [i8] = &[
|
const ATE_LOOP_COUNT: &'static [i8] = &[
|
||||||
1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -1,
|
1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -1,
|
||||||
0, 1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0,
|
0, 1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0,
|
||||||
@@ -36,10 +36,11 @@ impl MNT6Config for Config {
|
|||||||
0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0,
|
||||||
];
|
];
|
||||||
const ATE_IS_LOOP_COUNT_NEG: bool = true;
|
const ATE_IS_LOOP_COUNT_NEG: bool = true;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0]);
|
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger320 = BigInt!("0x1");
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
|
||||||
|
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6_80.ml#L126
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger320 =
|
||||||
BigInt::new([0xdc9a1b671660000, 0x46609756bec2a33f, 0x1eef55, 0x0, 0x0]);
|
BigInt!("689871209842287392837045615510547309923794944");
|
||||||
type Fp = Fq;
|
type Fp = Fq;
|
||||||
type Fr = Fr;
|
type Fr = Fr;
|
||||||
type Fp3Config = Fq3Config;
|
type Fp3Config = Fq3Config;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp3::{Fp3, Fp3Config},
|
fields::fp3::{Fp3, Fp3Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::fq::Fq;
|
use crate::fq::Fq;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq3, Fq3Config};
|
use crate::{Fq, Fq3, Fq3Config};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use ark_ec::{
|
|||||||
mnt6::MNT6Config,
|
mnt6::MNT6Config,
|
||||||
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
models::{short_weierstrass::SWCurveConfig, CurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp};
|
use ark_ff::{AdditiveGroup, MontFp};
|
||||||
|
|
||||||
use crate::{g1, Fq, Fq3, Fr};
|
use crate::{g1, Fq, Fq3, Fr};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_ec::models::{
|
|||||||
mnt6::{MNT6Config, MNT6},
|
mnt6::{MNT6Config, MNT6},
|
||||||
short_weierstrass::SWCurveConfig,
|
short_weierstrass::SWCurveConfig,
|
||||||
};
|
};
|
||||||
use ark_ff::{biginteger::BigInteger768, BigInt, Field, Fp3};
|
use ark_ff::{biginteger::BigInteger768, AdditiveGroup, BigInt, Field, Fp3};
|
||||||
|
|
||||||
use crate::{Fq, Fq3Config, Fq6Config, Fr};
|
use crate::{Fq, Fq3Config, Fq6Config, Fr};
|
||||||
|
|
||||||
@@ -49,23 +49,10 @@ impl MNT6Config for Config {
|
|||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
];
|
];
|
||||||
const ATE_IS_LOOP_COUNT_NEG: bool = false;
|
const ATE_IS_LOOP_COUNT_NEG: bool = false;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 =
|
const FINAL_EXPONENT_LAST_CHUNK_1: BigInteger768 = BigInt!("0x1");
|
||||||
BigInt::new([0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
|
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
|
const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = false;
|
||||||
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt::new([
|
// https://github.com/o1-labs/snarky/blob/9c21ab2bb23874604640740d646a932e813432c3/snarkette/mnt6753.ml#L130C1-L130C1
|
||||||
8824542903220142080,
|
const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger768 = BigInt!("204691208819330962009469868104636132783269696790011977400223898462431810102935615891307667367766898917669754470400");
|
||||||
7711082599397206192,
|
|
||||||
8303354903384568230,
|
|
||||||
5874150271971943936,
|
|
||||||
9717849827920685054,
|
|
||||||
95829799234282493,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
]);
|
|
||||||
type Fp = Fq;
|
type Fp = Fq;
|
||||||
type Fr = Fr;
|
type Fr = Fr;
|
||||||
type Fp3Config = Fq3Config;
|
type Fp3Config = Fq3Config;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp3::{Fp3, Fp3Config},
|
fields::fp3::{Fp3, Fp3Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::fq::Fq;
|
use crate::fq::Fq;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ark_ff::{
|
use ark_ff::{
|
||||||
fields::fp6_2over3::{Fp6, Fp6Config},
|
fields::fp6_2over3::{Fp6, Fp6Config},
|
||||||
Field, MontFp,
|
AdditiveGroup, Field, MontFp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Fq, Fq3, Fq3Config};
|
use crate::{Fq, Fq3, Fq3Config};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{self as sw, SWCurveConfig},
|
short_weierstrass::{self as sw, SWCurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
|
|
||||||
use crate::{fq::Fq, fr::Fr};
|
use crate::{fq::Fq, fr::Fr};
|
||||||
|
|
||||||
@@ -42,6 +43,40 @@ impl SWCurveConfig for PallasConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for PallasConfig {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
|
||||||
|
"20444556541222657078399132219657928148671392403212669005631716460534733845831"
|
||||||
|
)];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("26005156700822196841419187675678338661165322343552424574062261873906994770353");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("98231058071100081932162823354453065728")),
|
||||||
|
(true, BigInt!("98231058071186745657228807397848383489")),
|
||||||
|
(false, BigInt!("196462116142286827589391630752301449217")),
|
||||||
|
(false, BigInt!("98231058071100081932162823354453065728")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective) -> Projective {
|
||||||
|
// Endomorphism of the points on the curve.
|
||||||
|
// endomorphism_p(x,y) = (BETA * x, y)
|
||||||
|
// where BETA is a non-trivial cubic root of unity in Fq.
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine) -> Affine {
|
||||||
|
// Endomorphism of the points on the curve.
|
||||||
|
// endomorphism_p(x,y) = (BETA * x, y)
|
||||||
|
// where BETA is a non-trivial cubic root of unity in Fq.
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// G_GENERATOR_X = -1
|
/// G_GENERATOR_X = -1
|
||||||
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ use crate::Projective;
|
|||||||
use ark_algebra_test_templates::*;
|
use ark_algebra_test_templates::*;
|
||||||
|
|
||||||
test_group!(g1; Projective; sw);
|
test_group!(g1; Projective; sw);
|
||||||
|
test_group!(g1_glv; Projective; glv);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
|||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
short_weierstrass::{self as sw, SWCurveConfig},
|
short_weierstrass::{self as sw, SWCurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, Field, MontFp, Zero};
|
||||||
|
|
||||||
use crate::{fq::Fq, fr::Fr};
|
use crate::{fq::Fq, fr::Fr};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use ark_ec::{
|
|||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
short_weierstrass::{self as sw, SWCurveConfig},
|
short_weierstrass::{self as sw, SWCurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, Field, MontFp, Zero};
|
||||||
|
|
||||||
use crate::{fq::Fq, fr::Fr};
|
use crate::{fq::Fq, fr::Fr};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::{fq::Fq, fr::Fr};
|
use crate::{fq::Fq, fr::Fr};
|
||||||
use ark_ec::{
|
use ark_ec::{
|
||||||
models::CurveConfig,
|
models::CurveConfig,
|
||||||
|
scalar_mul::glv::GLVConfig,
|
||||||
short_weierstrass::{self as sw, SWCurveConfig},
|
short_weierstrass::{self as sw, SWCurveConfig},
|
||||||
};
|
};
|
||||||
use ark_ff::{Field, MontFp, Zero};
|
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@@ -41,6 +42,40 @@ impl SWCurveConfig for VestaConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GLVConfig for VestaConfig {
|
||||||
|
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
|
||||||
|
"26005156700822196841419187675678338661165322343552424574062261873906994770353"
|
||||||
|
)];
|
||||||
|
|
||||||
|
const LAMBDA: Self::ScalarField =
|
||||||
|
MontFp!("20444556541222657078399132219657928148671392403212669005631716460534733845831");
|
||||||
|
|
||||||
|
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
|
||||||
|
(false, BigInt!("98231058071100081932162823354453065729")),
|
||||||
|
(true, BigInt!("98231058071186745657228807397848383488")),
|
||||||
|
(false, BigInt!("196462116142286827589391630752301449217")),
|
||||||
|
(false, BigInt!("98231058071100081932162823354453065729")),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn endomorphism(p: &Projective) -> Projective {
|
||||||
|
// Endomorphism of the points on the curve.
|
||||||
|
// endomorphism_p(x,y) = (BETA * x, y)
|
||||||
|
// where BETA is a non-trivial cubic root of unity in Fq.
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn endomorphism_affine(p: &Affine) -> Affine {
|
||||||
|
// Endomorphism of the points on the curve.
|
||||||
|
// endomorphism_p(x,y) = (BETA * x, y)
|
||||||
|
// where BETA is a non-trivial cubic root of unity in Fq.
|
||||||
|
let mut res = (*p).clone();
|
||||||
|
res.x *= Self::ENDO_COEFFS[0];
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// G_GENERATOR_X = -1
|
/// G_GENERATOR_X = -1
|
||||||
/// Encoded in Montgomery form, so the value here is -R mod p.
|
/// Encoded in Montgomery form, so the value here is -R mod p.
|
||||||
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
pub const G_GENERATOR_X: Fq = MontFp!("-1");
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ use crate::Projective;
|
|||||||
use ark_algebra_test_templates::*;
|
use ark_algebra_test_templates::*;
|
||||||
|
|
||||||
test_group!(g1; Projective; sw);
|
test_group!(g1; Projective; sw);
|
||||||
|
test_group!(g1_glv; Projective; glv);
|
||||||
|
|||||||
Reference in New Issue
Block a user