30 Commits

Author SHA1 Message Date
mmagician
5a0b8eca0b chore: Release 2022-12-28 12:33:05 +01:00
mmagician
a986e08ce4 explicitly specify a dependency version 2022-12-28 12:23:43 +01:00
mmagician
5831ddbfe7 remove patches from release branch 2022-12-28 12:20:40 +01:00
Pratyush Mishra
cba0c7ef0d Add frobenius_map_in_place (#140) 2022-12-28 12:19:38 +01:00
Weikeng Chen
a82486db1d Add supplementary small group bases for some common fields (#137)
* update

* use r1cs std

* fix

* rem

* Apply suggestions from code review

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-12-21 18:06:24 -08:00
Pratyush Mishra
febd7635fb Rename all *Parameters to *Config (#136)
* Rename all `*Parameters` to `*Config`

* Tweak
2022-12-16 19:35:32 -08:00
Weikeng Chen
f8a6a4050e Add the secp256k1 and secq256k1 curves (#122)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-12-09 10:41:40 -08:00
mmagician
cdf4d182a6 Prepare release 0.4 (#133) 2022-11-29 08:22:09 -08:00
Weikeng Chen
99831650f8 Prepared G2 consistency test (#70)
* add the g2 check

* fmt

* fix

* fix

* fix

* fix

* changelog

* test macos for curve tests

* use macos only for mnt6-753

* fix

* fix name consistency

* adjust the order

* mnt4 753

* fix

Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-31 17:12:52 -07:00
Weikeng Chen
db03d405b5 Add the curve25519 curve (#124)
* add ed25519 curve

* changelog

* curve info

* fix

* edit

* update

* add more explanation

* Update curve25519/src/curves/mod.rs

* Update curve25519/src/curves/mod.rs

* fixed the comment

* Update curve25519/src/curves/mod.rs

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 19:55:35 -07:00
Weikeng Chen
a7d266f73d Add the ed25519 curve (#121)
* add ed25519 curve

* changelog

* curve info

* fix

* cleanup the script

* Update ed25519/src/curves/mod.rs

* Update ed25519/src/curves/mod.rs

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 19:33:55 -07:00
Weikeng Chen
5d6d31d213 Fix the location of BitIteratorBE (#132)
* fix

* fix

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 11:29:45 -07:00
mmagician
df39c78a5b Update changelog (#131) 2022-10-19 10:06:42 -07:00
mmagician
138b23f2fa Zcash-style serialization for BLS12-381 (#129)
Co-authored-by: kevaundray <37423678+kevaundray@users.noreply.github.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-10-18 22:44:43 -07:00
mmagician
4bcf87de22 Faster cofactor clearing for G1 & G2 of bls12-381 + benchmarking (#103) 2022-10-16 10:13:57 -07:00
Pratyush Mishra
efefa209d6 Fix mul-by-non-residue for bw6::fq3 2022-10-02 09:15:25 -07:00
Pratyush Mishra
1833cbfb29 Tweaks 2022-10-02 09:15:25 -07:00
Pratyush Mishra
f43d59c958 Rename 2022-10-02 09:15:25 -07:00
Pratyush Mishra
68f500da01 Optimizations to field and curve arithmetic 2022-10-02 09:15:25 -07:00
Pratyush Mishra
363426c1d4 Update to new benchmarking framework (#126) 2022-09-09 19:24:33 -07:00
Pratyush Mishra
55a092a6c7 is_identity -> is_zero (#125) 2022-09-09 11:07:42 -07:00
Weikeng Chen
f74378c017 Add serialization for CP6-782 (#120)
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 22:55:16 -07:00
Weikeng Chen
3af6ec17d6 Fix Bandersnatch parameters and the constraint tests (#119)
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 12:32:28 -07:00
Weikeng Chen
dc555882cd Fix the remaining curve and field tests (#118)
* push

* push

* cargo ready

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 00:34:13 -07:00
Weikeng Chen
3c4c67f114 Sync with the recent changes in ark-algebra on pairing and testing (#116)
* Fix another typo in the Jubjub curve comment

* fix

* progress

* get_point_from_x_unchecked

* fix

* soft link

* Fix Bandersnatch

* Fix Edwards form of Bandersnatch

* Actually fix ed_on_bls12_381_bandersnatch/src/curves/mod.rs

* fix

* fix

* curve-benches

* fix the last mul_by_a; fmt

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-09-02 16:31:58 -07:00
mmagician
42289245a6 Replace ATE_LOOP_COUNT with its 2-NAF for MNT curves (#107)
* Replace ATE_LOOP_COUNT by its 2-NAF

* Add constant references

* Apply suggestions from code review

Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
2022-09-02 08:19:51 -07:00
Weikeng Chen
b433045f4d Fix a typo in the Jubjub curve comment (#114) 2022-08-27 14:17:37 -07:00
Weikeng Chen
52577f93ba Last PR to get the curve tests to work (#113) 2022-08-21 21:08:38 -07:00
Weikeng Chen
6d94362894 Let ark-curve-constraint-tests work with latest arkworks-rs algebra (#112) 2022-08-21 19:58:41 -07:00
Weikeng Chen
435de9fc36 Let cargo build work again for the new arkworks-rs algebra (#111) 2022-08-21 18:22:43 -07:00
254 changed files with 3320 additions and 2698 deletions

View File

@@ -14,7 +14,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v3
- name: Install Rust - name: Install Rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -41,7 +41,7 @@ jobs:
- nightly - nightly
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Install Rust (${{ matrix.rust }}) - name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -79,14 +79,13 @@ jobs:
if: matrix.rust == 'nightly' if: matrix.rust == 'nightly'
directories: # Job that list subdirectories directories: # Job that list subdirectories
name: List directories for parallelizing tests name: List directories for parallelizing tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
dir: ${{ steps.set-dirs.outputs.dir }} # generate output name dir by using inner step output dir: ${{ steps.set-dirs.outputs.dir }} # generate output name dir by using inner step output
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- id: set-dirs # Give it an id to handle to get step outputs in the outputs key above - id: set-dirs # Give it an id to handle to get step outputs in the outputs key above
run: echo "::set-output name=dir::$(ls -d */ | jq -R -s -c 'split("\n")[:-1]')" run: echo "::set-output name=dir::$(ls -d */ | jq -R -s -c 'split("\n")[:-1]')"
# Define step output named dir base on ls command transformed to JSON thanks to jq # Define step output named dir base on ls command transformed to JSON thanks to jq
@@ -103,22 +102,47 @@ jobs:
exclude: exclude:
- dir: scripts/ - dir: scripts/
- dir: curve-constraint-tests/ - dir: curve-constraint-tests/
- dir: curve-benches/ - dir: mnt4_753/
- dir: mnt6_753/
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Run tests - name: Run tests
run: | run: |
cd ${{matrix.dir}} cd ${{matrix.dir}}
cargo test --all-features cargo test --all-features
test-mnt4-753:
name: Test (mnt4_753/)
runs-on: macos-latest
needs: [directories] # Waits for the directory listing job
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run tests
run: |
cd mnt4_753/
cargo test --all-features
test-mnt6-753:
name: Test (mnt6_753/)
runs-on: macos-latest
needs: [directories] # Waits for the directory listing job
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run tests
run: |
cd mnt6_753/
cargo test --all-features
docs: docs:
name: Check Documentation name: Check Documentation
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v3
- name: Install Rust - name: Install Rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
@@ -138,7 +162,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Install Rust (${{ matrix.rust }}) - name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
@@ -159,10 +183,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 --exclude ark-curve-benches --target aarch64-unknown-none args: --examples --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none
- 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 --exclude ark-curve-benches --target aarch64-unknown-none args: --workspace --exclude ark-curve-constraint-tests --target aarch64-unknown-none

View File

@@ -8,12 +8,21 @@
### Breaking changes ### Breaking changes
- [\#104](https://github.com/arkworks-rs/curves/pull/104) Remove `QUADRATIC_NONRESIDUE` parameter from implementors of `Fp2Config`. - [\#104](https://github.com/arkworks-rs/curves/pull/104) Remove `QUADRATIC_NONRESIDUE` parameter from implementors of `Fp2Config`.
- [\#129](https://github.com/arkworks-rs/curves/pull/129) Implement custom serialization for BLS12-381 for compatibility with the [Zcash lib](https://github.com/zkcrypto/bls12_381).
### Features ### Features
- [\#121](https://github.com/arkworks-rs/curves/pull/121) Add the ed25519 curve.
- [\#122](https://github.com/arkworks-rs/curves/pull/122) Add the secp256k1 and secq256k1 curves.
- [\#124](https://github.com/arkworks-rs/curves/pull/124) Add the curve25519 curve.
### Improvements ### Improvements
- [\#70](https://github.com/arkworks-rs/curves/pull/70) Add prepared G2 pairing consistency test.
- [\#74](https://github.com/arkworks-rs/curves/pull/74) Use Scott's subgroup membership tests for `G1` and `G2` of BLS12-381. - [\#74](https://github.com/arkworks-rs/curves/pull/74) Use Scott's subgroup membership tests for `G1` and `G2` of BLS12-381.
- [\#103](https://github.com/arkworks-rs/curves/pull/103) Faster cofactor clearing for BLS12-381.
- [\#107](https://github.com/arkworks-rs/curves/pull/107/) Use 2-NAF of `ATE_LOOP_COUNT` to speed up the Miller loop in MNT curves.
### Bug fixes ### Bug fixes

View File

@@ -1,7 +1,6 @@
[workspace] [workspace]
members = [ members = [
"curve-benches",
"curve-constraint-tests", "curve-constraint-tests",
"bls12_377", "bls12_377",
@@ -30,7 +29,14 @@ members = [
"pallas", "pallas",
"vesta", "vesta",
"secp256k1",
"secq256k1",
"curve25519",
"ed25519",
] ]
resolver = "2"
[profile.release] [profile.release]
opt-level = 3 opt-level = 3
@@ -56,12 +62,3 @@ lto = "thin"
incremental = true incremental = true
debug-assertions = true debug-assertions = true
debug = true debug = true
# To be removed in the new release.
[patch.crates-io]
ark-ec = { git = "https://github.com/arkworks-rs/algebra" }
ark-ff = { 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-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std" }
ark-std = { git = "https://github.com/arkworks-rs/std" }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-bls12-377" name = "ark-bls12-377"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "The BLS12-377 pairing-friendly elliptic curve" description = "The BLS12-377 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,18 +10,19 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-ff = { version="^0.3.0", default-features = false } ark-ff = { version="0.4.0-alpha", default-features = false }
ark-ec = { version="^0.3.0", default-features = false } ark-ec = { version="0.4.0-alpha", default-features = false }
ark-r1cs-std = { version="^0.3.0", default-features = false, optional = true } ark-r1cs-std = { version="0.4.0-alpha", default-features = false, optional = true }
ark-std = { version="^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
[dev-dependencies] [dev-dependencies]
ark-relations = { version="^0.3.0", default-features = false } ark-relations = { version="0.4.0-alpha", default-features = false }
ark-serialize = { version="^0.3.0", default-features = false } ark-serialize = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version="^0.3.0", default-features = false } ark-algebra-test-templates = { version = "0.4.0-alpha", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0-alpha", default-features = false }
ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false }
[features] [features]
@@ -32,3 +33,8 @@ curve = [ "scalar_field", "base_field" ]
scalar_field = [] scalar_field = []
base_field = [] base_field = []
r1cs = [ "base_field", "ark-r1cs-std" ] r1cs = [ "base_field", "ark-r1cs-std" ]
[[bench]]
name = "bls12_377"
path = "benches/bls12_377.rs"
harness = false

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bls12_377::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_377, Fq12, G1Projective as G1, G2Projective as G2,
};
bench!(
Name = "Bls12_377",
Pairing = Bls12_377,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -1,45 +1,39 @@
use ark_ec::{bls12::Bls12Parameters, CurveConfig}; use ark_ec::{bls12::Bls12Config, CurveConfig};
use ark_r1cs_std::{ use ark_r1cs_std::{
fields::fp::FpVar, fields::fp::FpVar,
groups::{bls12, curves::twisted_edwards::AffineVar as TEAffineVar}, groups::{bls12, curves::twisted_edwards::AffineVar as TEAffineVar},
}; };
use crate::Parameters; use crate::Config;
/// An element of G1 in the BLS12-377 bilinear group. /// An element of G1 in the BLS12-377 bilinear group.
pub type G1Var = bls12::G1Var<Parameters>; pub type G1Var = bls12::G1Var<Config>;
/// An element of G2 in the BLS12-377 bilinear group. /// An element of G2 in the BLS12-377 bilinear group.
pub type G2Var = bls12::G2Var<Parameters>; pub type G2Var = bls12::G2Var<Config>;
/// An element of G1 (in TE Affine form) in the BLS12-377 bilinear group. /// An element of G1 (in TE Affine form) in the BLS12-377 bilinear group.
pub type G1TEAffineVar = TEAffineVar< pub type G1TEAffineVar = TEAffineVar<
<Parameters as Bls12Parameters>::G1Parameters, <Config as Bls12Config>::G1Config,
FpVar<<<Parameters as Bls12Parameters>::G1Parameters as CurveConfig>::BaseField>, FpVar<<<Config as Bls12Config>::G1Config as CurveConfig>::BaseField>,
>; >;
/// Represents the cached precomputation that can be performed on a G1 element /// Represents the cached precomputation that can be performed on a G1 element
/// which enables speeding up pairing computation. /// which enables speeding up pairing computation.
pub type G1PreparedVar = bls12::G1PreparedVar<Parameters>; pub type G1PreparedVar = bls12::G1PreparedVar<Config>;
/// Represents the cached precomputation that can be performed on a G2 element /// Represents the cached precomputation that can be performed on a G2 element
/// which enables speeding up pairing computation. /// which enables speeding up pairing computation.
pub type G2PreparedVar = bls12::G2PreparedVar<Parameters>; pub type G2PreparedVar = bls12::G2PreparedVar<Config>;
#[test] #[test]
fn test() { fn test() {
use ark_ec::models::bls12::Bls12Parameters; use ark_ec::models::bls12::Bls12Config;
ark_curve_constraint_tests::curves::sw_test::< ark_curve_constraint_tests::curves::sw_test::<<Config as Bls12Config>::G1Config, G1Var>()
<Parameters as Bls12Parameters>::G1Parameters,
G1Var,
>()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::te_test::< ark_curve_constraint_tests::curves::te_test::<
<Parameters as Bls12Parameters>::G1Parameters, <Config as Bls12Config>::G1Config,
G1TEAffineVar, G1TEAffineVar,
>() >()
.unwrap(); .unwrap();
ark_curve_constraint_tests::curves::sw_test::< ark_curve_constraint_tests::curves::sw_test::<<Config as Bls12Config>::G2Config, G2Var>()
<Parameters as Bls12Parameters>::G2Parameters,
G2Var,
>()
.unwrap(); .unwrap();
} }

View File

@@ -106,7 +106,7 @@
//! ``` //! ```
//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { //! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
//! # use ark_std::UniformRand; //! # use ark_std::UniformRand;
//! # use ark_ec::PairingEngine; //! # use ark_ec::pairing::Pairing;
//! # use ark_relations::r1cs::*; //! # use ark_relations::r1cs::*;
//! # use ark_r1cs_std::prelude::*; //! # use ark_r1cs_std::prelude::*;
//! # use ark_bls12_377::{*, constraints::*}; //! # use ark_bls12_377::{*, constraints::*};
@@ -135,7 +135,7 @@
//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; //! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//! //!
//! // Check that the value of &a + &b is correct. //! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native); //! assert_eq!(pairing_result.value()?, pairing_result_native.0);
//! //!
//! // Check that operations on variables and constants are equivalent. //! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; //! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;

View File

@@ -1,11 +1,13 @@
use crate::Parameters; use crate::Config;
/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear /// Specifies the constraints for computing a pairing in the BLS12-377 bilinear
/// group. /// group.
pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar<Parameters>; pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar<Config>;
#[test] #[test]
fn test() { fn test() {
use crate::Bls12_377; use crate::Bls12_377;
ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377, PairingVar>().unwrap() ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377, PairingVar>().unwrap();
ark_curve_constraint_tests::pairing::g2_prepare_consistency_test::<Bls12_377, PairingVar>()
.unwrap();
} }

View File

@@ -11,9 +11,9 @@ use core::ops::Neg;
use crate::{Fq, Fr}; use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -25,7 +25,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = MontFp!("5285428838741532253824584287042945485047145357130994810877"); const COFACTOR_INV: Fr = MontFp!("5285428838741532253824584287042945485047145357130994810877");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 0 /// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO; const COEFF_A: Fq = Fq::ZERO;
@@ -36,14 +36,14 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G1SWAffine = G1SWAffine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); const GENERATOR: G1SWAffine = G1SWAffine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
} }
pub type G1SWAffine = SWAffine<Parameters>; pub type G1SWAffine = SWAffine<Config>;
pub type G1TEAffine = TEAffine<Parameters>; pub type G1TEAffine = TEAffine<Config>;
pub type G1TEProjective = TEProjective<Parameters>; pub type G1TEProjective = TEProjective<Config>;
/// Bls12_377::G1 also has a twisted Edwards form. /// Bls12_377::G1 also has a twisted Edwards form.
/// It can be obtained via the following script, implementing /// It can be obtained via the following script, implementing
@@ -92,7 +92,7 @@ pub type G1TEProjective = TEProjective<Parameters>;
/// # b = -TE1d/TE1a /// # b = -TE1d/TE1a
/// TE2d = Fp(122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179) /// TE2d = Fp(122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179)
/// ``` /// ```
impl TECurveConfig for Parameters { impl TECurveConfig for Config {
/// COEFF_A = -1 /// COEFF_A = -1
const COEFF_A: Fq = MontFp!("-1"); const COEFF_A: Fq = MontFp!("-1");
@@ -102,11 +102,11 @@ impl TECurveConfig for Parameters {
/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y) /// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
const GENERATOR: G1TEAffine = G1TEAffine::new_unchecked(TE_GENERATOR_X, TE_GENERATOR_Y); const GENERATOR: G1TEAffine = G1TEAffine::new_unchecked(TE_GENERATOR_X, TE_GENERATOR_Y);
type MontCurveConfig = Parameters; type MontCurveConfig = Config;
/// Multiplication by `a` is multiply by `-1`. /// Multiplication by `a` is multiply by `-1`.
#[inline(always)] #[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField { fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
elem.neg() elem.neg()
} }
} }
@@ -140,14 +140,14 @@ impl TECurveConfig for Parameters {
// # MB = s // # MB = s
// MB=Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931) // MB=Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931)
// ``` // ```
impl MontCurveConfig for Parameters { impl MontCurveConfig for Config {
/// COEFF_A = 228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384 /// COEFF_A = 228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384
const COEFF_A: Fq = MontFp!("228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384"); const COEFF_A: Fq = MontFp!("228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384");
/// COEFF_B = 10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931 /// COEFF_B = 10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931
const COEFF_B: Fq = MontFp!("10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931"); const COEFF_B: Fq = MontFp!("10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931");
type TECurveConfig = Parameters; type TECurveConfig = Config;
} }
/// G1_GENERATOR_X = /// G1_GENERATOR_X =

View File

@@ -6,11 +6,11 @@ use ark_ff::{Field, MontFp, Zero};
use crate::{g1, Fq, Fq2, Fr}; use crate::{g1, Fq, Fq2, Fr};
pub type G2Affine = Affine<Parameters>; pub type G2Affine = Affine<Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq2; type BaseField = Fq2;
type ScalarField = Fr; type ScalarField = Fr;
@@ -34,9 +34,9 @@ impl CurveConfig for Parameters {
MontFp!("6764900296503390671038341982857278410319949526107311149686707033187604810669"); MontFp!("6764900296503390671038341982857278410319949526107311149686707033187604810669");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = [0, 0] /// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::new(g1::Parameters::COEFF_A, g1::Parameters::COEFF_A); const COEFF_A: Fq2 = Fq2::new(g1::Config::COEFF_A, g1::Config::COEFF_A);
// As per https://eprint.iacr.org/2012/072.pdf, // As per https://eprint.iacr.org/2012/072.pdf,
// this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is // this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is
@@ -53,7 +53,7 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
} }

View File

@@ -1,6 +1,6 @@
use ark_ec::{ use ark_ec::{
bls12, bls12,
bls12::{Bls12, Bls12Parameters, TwistType}, bls12::{Bls12, Bls12Config, TwistType},
}; };
use crate::*; use crate::*;
@@ -11,9 +11,9 @@ pub mod g2;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub struct Parameters; pub struct Config;
impl Bls12Parameters for Parameters { impl Bls12Config for Config {
const X: &'static [u64] = &[0x8508c00000000001]; const X: &'static [u64] = &[0x8508c00000000001];
/// `x` is positive. /// `x` is positive.
const X_IS_NEGATIVE: bool = false; const X_IS_NEGATIVE: bool = false;
@@ -22,15 +22,15 @@ impl Bls12Parameters for Parameters {
type Fp2Config = Fq2Config; type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config; type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config; type Fp12Config = Fq12Config;
type G1Parameters = g1::Parameters; type G1Config = g1::Config;
type G2Parameters = g2::Parameters; type G2Config = g2::Config;
} }
pub type Bls12_377 = Bls12<Parameters>; pub type Bls12_377 = Bls12<Config>;
pub type G1Affine = bls12::G1Affine<Parameters>; pub type G1Affine = bls12::G1Affine<Config>;
pub type G1Projective = bls12::G1Projective<Parameters>; pub type G1Projective = bls12::G1Projective<Config>;
pub type G2Affine = bls12::G2Affine<Parameters>; pub type G2Affine = bls12::G2Affine<Config>;
pub type G2Projective = bls12::G2Projective<Parameters>; pub type G2Projective = bls12::G2Projective<Config>;
pub use g1::{G1TEAffine, G1TEProjective}; pub use g1::{G1TEAffine, G1TEProjective};

View File

@@ -1,19 +1,7 @@
use ark_algebra_test_templates::{ use crate::{Bls12_377, G1Projective, G2Projective};
curves::{curve_tests, edwards_tests, sw_tests}, use ark_algebra_test_templates::*;
generate_bilinearity_test, generate_g1_generator_raw_test, generate_g1_test, generate_g2_test,
msm::test_var_base_msm,
};
use ark_ec::{models::short_weierstrass::SWCurveConfig, AffineCurve, PairingEngine};
use ark_ff::{
fields::{Field, PrimeField},
One, Zero,
};
use ark_std::{rand::Rng, test_rng};
use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_377, Fq, Fq12, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
generate_g1_test!(bls12_377; curve_tests; sw_tests; edwards_tests;); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
generate_g2_test!(bls12_377; curve_tests; sw_tests;); test_pairing!(pairing; crate::Bls12_377);
generate_bilinearity_test!(Bls12_377, Fq12);
generate_g1_generator_raw_test!(bls12_377, 1);

View File

@@ -21,10 +21,31 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp { fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
let original = fe; fe.neg_in_place();
let mut fe = -fe.double(); *fe = *fe + fe.double_in_place().double_in_place();
fe.double_in_place(); fe
fe - original }
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original += x;
y.double_in_place().double_in_place();
*y += original;
}
#[inline(always)]
fn mul_fp_by_nonresidue_plus_one_and_add(y: &mut Self::Fp, x: &Self::Fp) {
y.double_in_place().double_in_place().neg_in_place();
*y += x;
}
fn mul_fp_by_nonresidue_and_add(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original.double_in_place().double_in_place();
original += &*y;
*y = *x;
*y -= original;
} }
} }

View File

@@ -68,10 +68,12 @@ impl Fp6Config for Fq6Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 { fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// Karatsuba multiplication with constant other = u. // Karatsuba multiplication with constant other = u.
let c0 = Fq2Config::mul_fp_by_nonresidue(&fe.c1); let old_c0 = fe.c0;
let c1 = fe.c0; fe.c0 = fe.c1;
Fq2::new(c0, c1) Fq2Config::mul_fp_by_nonresidue_in_place(&mut fe.c0);
fe.c1 = old_c0;
fe
} }
} }

View File

@@ -1,22 +1,22 @@
use ark_algebra_test_templates::{ use ark_algebra_test_templates::*;
fields::*, generate_field_serialization_test, generate_field_test,
};
use ark_ff::{ use ark_ff::{
biginteger::{BigInt, BigInteger, BigInteger384}, biginteger::{BigInt, BigInteger, BigInteger384},
fields::{FftField, Field, Fp6Config, PrimeField}, fields::{FftField, Field, Fp6Config, PrimeField},
One, UniformRand, Zero, Fp384, One, UniformRand, Zero,
}; };
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize}; use ark_std::{
use ark_std::{rand::Rng, test_rng};
use core::{
cmp::Ordering, cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign}, ops::{AddAssign, MulAssign},
test_rng,
}; };
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, FqConfig, Fr, FrConfig}; use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, Fr};
generate_field_test!(bls12_377; fq2; fq6; fq12; mont(6, 4); ); test_field!(fr; Fr; mont_prime_field);
generate_field_serialization_test!(bls12_377; fq2; fq6; fq12;); test_field!(fq; Fq; mont_prime_field);
test_field!(fq2; Fq2);
test_field!(fq6; Fq6);
test_field!(fq12; Fq12);
#[test] #[test]
fn test_fq_repr_from() { fn test_fq_repr_from() {
@@ -85,7 +85,7 @@ fn test_fq_ordering() {
// BigInteger384's ordering is well-tested, but we still need to make sure the // BigInteger384's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form. // Fq elements aren't being compared in Montgomery form.
for i in 0..100u64 { for i in 0..100u64 {
assert!(Fq::from(BigInteger384::from(i + 1)) > Fq::from(BigInteger384::from(i))); assert!(Fq::from(Fp384::from(i + 1)) > Fq::from(Fp384::from(i)));
} }
} }
@@ -95,14 +95,8 @@ fn test_fq_legendre() {
assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre()); assert_eq!(Zero, Fq::zero().legendre());
assert_eq!( assert_eq!(QuadraticResidue, Fq::from(Fp384::from(4u64)).legendre());
QuadraticResidue, assert_eq!(QuadraticNonResidue, Fq::from(Fp384::from(5u64)).legendre());
Fq::from(BigInteger384::from(4u64)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger384::from(5u64)).legendre()
);
} }
#[test] #[test]
@@ -142,7 +136,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1); Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-bls12-381" name = "ark-bls12-381"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "The BLS12-381 pairing-friendly elliptic curve" description = "The BLS12-381 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,16 +10,18 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-ff = { version="^0.3.0", default-features = false } ark-ff = { version="0.4.0-alpha", default-features = false }
ark-ec = { version="^0.3.0", default-features = false } ark-ec = { version="0.4.0-alpha", default-features = false }
ark-std = { version="^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
ark-serialize = { version = "0.4.0-alpha", default-features = false }
[dev-dependencies] [dev-dependencies]
ark-serialize = { version="^0.3.0", default-features = false } ark-algebra-test-templates = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version="^0.3.0", default-features = false } ark-algebra-bench-templates = { version = "0.4.0-alpha", default-features = false }
hex = "^0.4.0"
[features] [features]
default = [ "curve" ] default = [ "curve" ]
@@ -27,3 +29,8 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ] curve = [ "scalar_field" ]
scalar_field = [] scalar_field = []
[[bench]]
name = "bls12_381"
path = "benches/bls12_381.rs"
harness = false

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bls12_381::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
};
bench!(
Name = "Bls12_381",
Pairing = Bls12_381,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -1,22 +1,26 @@
use crate::*;
use ark_ec::{ use ark_ec::{
bls12, bls12,
bls12::Bls12Parameters, bls12::Bls12Config,
models::CurveConfig, models::CurveConfig,
short_weierstrass::{Affine, SWCurveConfig}, short_weierstrass::{Affine, SWCurveConfig},
AffineCurve, ProjectiveCurve, AffineRepr, Group,
}; };
use ark_ff::{biginteger::BigInteger256, Field, MontFp, Zero}; use ark_ff::{Field, MontFp, PrimeField, Zero};
use ark_std::ops::Neg; use ark_serialize::{Compress, SerializationError};
use ark_std::{ops::Neg, One};
use crate::*; use crate::util::{
read_g1_compressed, read_g1_uncompressed, serialize_fq, EncodingFlags, G1_SERIALIZED_SIZE,
};
pub type G1Affine = bls12::G1Affine<crate::Parameters>; pub type G1Affine = bls12::G1Affine<crate::Config>;
pub type G1Projective = bls12::G1Projective<crate::Parameters>; pub type G1Projective = bls12::G1Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -29,7 +33,7 @@ impl CurveConfig for Parameters {
MontFp!("52435875175126190458656871551744051925719901746859129887267498875565241663483"); MontFp!("52435875175126190458656871551744051925719901746859129887267498875565241663483");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 0 /// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO; const COEFF_A: Fq = Fq::ZERO;
@@ -40,7 +44,7 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
@@ -50,20 +54,93 @@ impl SWCurveConfig for Parameters {
// //
// Check that endomorphism_p(P) == -[X^2]P // Check that endomorphism_p(P) == -[X^2]P
let x = BigInteger256::new([crate::Parameters::X[0], 0, 0, 0]);
// An early-out optimization described in Section 6. // An early-out optimization described in Section 6.
// If uP == P but P != point of infinity, then the point is not in the right // If uP == P but P != point of infinity, then the point is not in the right
// subgroup. // subgroup.
let x_times_p = p.mul(x); let x_times_p = p.mul_bigint(crate::Config::X);
if x_times_p.eq(p) && !p.infinity { if x_times_p.eq(p) && !p.infinity {
return false; return false;
} }
let minus_x_squared_times_p = x_times_p.mul(x).neg(); let minus_x_squared_times_p = x_times_p.mul_bigint(crate::Config::X).neg();
let endomorphism_p = endomorphism(p); let endomorphism_p = endomorphism(p);
minus_x_squared_times_p.eq(&endomorphism_p) minus_x_squared_times_p.eq(&endomorphism_p)
} }
#[inline]
fn clear_cofactor(p: &G1Affine) -> G1Affine {
// Using the effective cofactor, as explained in
// Section 5 of https://eprint.iacr.org/2019/403.pdf.
//
// It is enough to multiply by (1 - x), instead of (x - 1)^2 / 3
let h_eff = one_minus_x().into_bigint();
Config::mul_affine(&p, h_eff.as_ref()).into()
}
fn deserialize_with_mode<R: ark_serialize::Read>(
mut reader: R,
compress: ark_serialize::Compress,
validate: ark_serialize::Validate,
) -> Result<Affine<Self>, ark_serialize::SerializationError> {
let p = if compress == ark_serialize::Compress::Yes {
read_g1_compressed(&mut reader)?
} else {
read_g1_uncompressed(&mut reader)?
};
if validate == ark_serialize::Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve()
{
return Err(SerializationError::InvalidData);
}
Ok(p)
}
fn serialize_with_mode<W: ark_serialize::Write>(
item: &Affine<Self>,
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let encoding = EncodingFlags {
is_compressed: compress == ark_serialize::Compress::Yes,
is_infinity: item.is_zero(),
is_lexographically_largest: item.y > -item.y,
};
let mut p = *item;
if encoding.is_infinity {
p = G1Affine::zero();
}
// need to access the field struct `x` directly, otherwise we get None from xy()
// method
let x_bytes = serialize_fq(p.x);
if encoding.is_compressed {
let mut bytes: [u8; G1_SERIALIZED_SIZE] = x_bytes;
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
} else {
let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE];
bytes[0..G1_SERIALIZED_SIZE].copy_from_slice(&x_bytes[..]);
bytes[G1_SERIALIZED_SIZE..].copy_from_slice(&serialize_fq(p.y)[..]);
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
};
Ok(())
}
fn serialized_size(compress: Compress) -> usize {
if compress == Compress::Yes {
G1_SERIALIZED_SIZE
} else {
G1_SERIALIZED_SIZE * 2
}
}
}
fn one_minus_x() -> Fr {
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
Fr::one() - X
} }
/// G1_GENERATOR_X = /// G1_GENERATOR_X =
@@ -77,7 +154,7 @@ pub const G1_GENERATOR_Y: Fq = MontFp!("1339506544944476473020471379941921221584
/// BETA is a non-trivial cubic root of unity in Fq. /// BETA is a non-trivial cubic root of unity in Fq.
pub const BETA: Fq = MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"); pub const BETA: Fq = MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350");
pub fn endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> { pub fn endomorphism(p: &Affine<Config>) -> Affine<Config> {
// Endomorphism of the points on the curve. // Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y) // endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq. // where BETA is a non-trivial cubic root of unity in Fq.
@@ -85,3 +162,33 @@ pub fn endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> {
res.x *= BETA; res.x *= BETA;
res res
} }
#[cfg(test)]
mod test {
use super::*;
use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> Affine<g1::Config> {
let mut rng = ark_std::test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
return p;
}
}
}
#[test]
fn test_cofactor_clearing() {
const SAMPLES: usize = 100;
for _ in 0..SAMPLES {
let p: Affine<g1::Config> = sample_unchecked();
let p = p.clear_cofactor();
assert!(p.is_on_curve());
assert!(p.is_in_correct_subgroup_assuming_on_curve());
}
}
}

View File

@@ -1,21 +1,28 @@
use ark_std::ops::Neg;
use ark_ec::{ use ark_ec::{
bls12, bls12,
bls12::Bls12Parameters, bls12::Bls12Config,
models::CurveConfig, models::CurveConfig,
short_weierstrass::{Affine, SWCurveConfig}, short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineCurve, AffineRepr, CurveGroup, Group,
}; };
use ark_ff::{BigInt, Field, MontFp, Zero}; use ark_ff::{Field, MontFp, Zero};
use ark_serialize::{Compress, SerializationError};
use crate::*; use super::util::{serialize_fq, EncodingFlags, G2_SERIALIZED_SIZE};
use crate::{
util::{read_g2_compressed, read_g2_uncompressed},
*,
};
pub type G2Affine = bls12::G2Affine<crate::Parameters>; pub type G2Affine = bls12::G2Affine<crate::Config>;
pub type G2Projective = bls12::G2Projective<crate::Parameters>; pub type G2Projective = bls12::G2Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq2; type BaseField = Fq2;
type ScalarField = Fr; type ScalarField = Fr;
@@ -40,18 +47,18 @@ impl CurveConfig for Parameters {
MontFp!("26652489039290660355457965112010883481355318854675681319708643586776743290055"); MontFp!("26652489039290660355457965112010883481355318854675681319708643586776743290055");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = [0, 0] /// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::new(g1::Parameters::COEFF_A, g1::Parameters::COEFF_A); const COEFF_A: Fq2 = Fq2::new(g1::Config::COEFF_A, g1::Config::COEFF_A);
/// COEFF_B = [4, 4] /// COEFF_B = [4, 4]
const COEFF_B: Fq2 = Fq2::new(g1::Parameters::COEFF_B, g1::Parameters::COEFF_B); const COEFF_B: Fq2 = Fq2::new(g1::Config::COEFF_B, g1::Config::COEFF_B);
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
@@ -60,8 +67,8 @@ impl SWCurveConfig for Parameters {
// //
// Checks that [p]P = [X]P // Checks that [p]P = [X]P
let mut x_times_point = point.mul(BigInt::new([crate::Parameters::X[0], 0, 0, 0])); let mut x_times_point = point.mul_bigint(crate::Config::X);
if crate::Parameters::X_IS_NEGATIVE { if crate::Config::X_IS_NEGATIVE {
x_times_point = -x_times_point; x_times_point = -x_times_point;
} }
@@ -69,6 +76,109 @@ impl SWCurveConfig for Parameters {
x_times_point.eq(&p_times_point) x_times_point.eq(&p_times_point)
} }
#[inline]
fn clear_cofactor(p: &G2Affine) -> G2Affine {
// Based on Section 4.1 of https://eprint.iacr.org/2017/419.pdf
// [h(ψ)]P = [x^2 x 1]P + [x 1]ψ(P) + (ψ^2)(2P)
// x = -15132376222941642752
// When multiplying, use -c1 instead, and then negate the result. That's much
// more efficient, since the scalar -c1 has less limbs and a much lower Hamming
// weight.
let x: &'static [u64] = crate::Config::X;
let p_projective = p.into_group();
// [x]P
let x_p = Config::mul_affine(p, &x).neg();
// ψ(P)
let psi_p = p_power_endomorphism(&p);
// (ψ^2)(2P)
let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double());
// tmp = [x]P + ψ(P)
let mut tmp = x_p.clone();
tmp += &psi_p;
// tmp2 = [x^2]P + [x]ψ(P)
let mut tmp2: Projective<Config> = tmp;
tmp2 = tmp2.mul_bigint(x).neg();
// add up all the terms
psi2_p2 += tmp2;
psi2_p2 -= x_p;
psi2_p2 += &-psi_p;
(psi2_p2 - p_projective).into_affine()
}
fn deserialize_with_mode<R: ark_serialize::Read>(
mut reader: R,
compress: ark_serialize::Compress,
validate: ark_serialize::Validate,
) -> Result<Affine<Self>, ark_serialize::SerializationError> {
let p = if compress == ark_serialize::Compress::Yes {
read_g2_compressed(&mut reader)?
} else {
read_g2_uncompressed(&mut reader)?
};
if validate == ark_serialize::Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve()
{
return Err(SerializationError::InvalidData);
}
Ok(p)
}
fn serialize_with_mode<W: ark_serialize::Write>(
item: &Affine<Self>,
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let encoding = EncodingFlags {
is_compressed: compress == ark_serialize::Compress::Yes,
is_infinity: item.is_zero(),
is_lexographically_largest: item.y > -item.y,
};
let mut p = *item;
if encoding.is_infinity {
p = G2Affine::zero();
}
let mut x_bytes = [0u8; G2_SERIALIZED_SIZE];
let c1_bytes = serialize_fq(p.x.c1);
let c0_bytes = serialize_fq(p.x.c0);
x_bytes[0..48].copy_from_slice(&c1_bytes[..]);
x_bytes[48..96].copy_from_slice(&c0_bytes[..]);
if encoding.is_compressed {
let mut bytes: [u8; G2_SERIALIZED_SIZE] = x_bytes;
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
} else {
let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE];
let mut y_bytes = [0u8; G2_SERIALIZED_SIZE];
let c1_bytes = serialize_fq(p.y.c1);
let c0_bytes = serialize_fq(p.y.c0);
y_bytes[0..48].copy_from_slice(&c1_bytes[..]);
y_bytes[48..96].copy_from_slice(&c0_bytes[..]);
bytes[0..G2_SERIALIZED_SIZE].copy_from_slice(&x_bytes);
bytes[G2_SERIALIZED_SIZE..].copy_from_slice(&y_bytes);
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
};
Ok(())
}
fn serialized_size(compress: ark_serialize::Compress) -> usize {
if compress == Compress::Yes {
G2_SERIALIZED_SIZE
} else {
2 * G2_SERIALIZED_SIZE
}
}
} }
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);
@@ -109,7 +219,12 @@ pub const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new(
"1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257")
); );
pub fn p_power_endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> { pub const DOUBLE_P_POWER_ENDOMORPHISM: Fq2 = Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq::ZERO
);
pub fn p_power_endomorphism(p: &Affine<Config>) -> Affine<Config> {
// The p-power endomorphism for G2 is defined as follows: // The p-power endomorphism for G2 is defined as follows:
// 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1). // 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1).
// To map a point (x, y) in E' to (s, t) in E, // To map a point (x, y) in E' to (s, t) in E,
@@ -125,8 +240,8 @@ pub fn p_power_endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> {
// as implemented in the code as follows. // as implemented in the code as follows.
let mut res = *p; let mut res = *p;
res.x.frobenius_map(1); res.x.frobenius_map_in_place(1);
res.y.frobenius_map(1); res.y.frobenius_map_in_place(1);
let tmp_x = res.x.clone(); let tmp_x = res.x.clone();
res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c1; res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c1;
@@ -135,3 +250,47 @@ pub fn p_power_endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> {
res res
} }
/// For a p-power endomorphism psi(P), compute psi(psi(P))
pub fn double_p_power_endomorphism(p: &Projective<Config>) -> Projective<Config> {
let mut res = *p;
res.x *= DOUBLE_P_POWER_ENDOMORPHISM;
res.y = res.y.neg();
res
}
#[cfg(test)]
mod test {
use super::*;
use ark_std::UniformRand;
#[test]
fn test_cofactor_clearing() {
// multiplying by h_eff and clearing the cofactor by the efficient
// endomorphism-based method should yield the same result.
let h_eff: &'static [u64] = &[
0xe8020005aaa95551,
0x59894c0adebbf6b4,
0xe954cbc06689f6a3,
0x2ec0ec69d7477c1a,
0x6d82bf015d1212b0,
0x329c2f178731db95,
0x9986ff031508ffe1,
0x88e2a8e9145ad768,
0x584c6a0ea91b3528,
0xbc69f08f2ee75b3,
];
let mut rng = ark_std::test_rng();
const SAMPLES: usize = 10;
for _ in 0..SAMPLES {
let p = Affine::<g2::Config>::rand(&mut rng);
let optimised = p.clear_cofactor().into_group();
let naive = g2::Config::mul_affine(&p, h_eff);
assert_eq!(optimised, naive);
}
}
}

View File

@@ -1,9 +1,10 @@
use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType}; use ark_ec::bls12::{Bls12, Bls12Config, TwistType};
use crate::{Fq, Fq12Config, Fq2Config, Fq6Config}; use crate::{Fq, Fq12Config, Fq2Config, Fq6Config};
pub mod g1; pub mod g1;
pub mod g2; pub mod g2;
pub(crate) mod util;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -13,11 +14,11 @@ pub use self::{
g2::{G2Affine, G2Projective}, g2::{G2Affine, G2Projective},
}; };
pub type Bls12_381 = Bls12<Parameters>; pub type Bls12_381 = Bls12<Config>;
pub struct Parameters; pub struct Config;
impl Bls12Parameters for Parameters { impl Bls12Config for Config {
const X: &'static [u64] = &[0xd201000000010000]; const X: &'static [u64] = &[0xd201000000010000];
const X_IS_NEGATIVE: bool = true; const X_IS_NEGATIVE: bool = true;
const TWIST_TYPE: TwistType = TwistType::M; const TWIST_TYPE: TwistType = TwistType::M;
@@ -25,6 +26,6 @@ impl Bls12Parameters for Parameters {
type Fp2Config = Fq2Config; type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config; type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config; type Fp12Config = Fq12Config;
type G1Parameters = self::g1::Parameters; type G1Config = self::g1::Config;
type G2Parameters = self::g2::Parameters; type G2Config = self::g2::Config;
} }

View File

@@ -1,71 +0,0 @@
use ark_algebra_test_templates::{
curves::*, generate_bilinearity_test, generate_g1_generator_raw_test, generate_g1_test,
generate_g2_test, msm::*,
};
use ark_ec::{
models::short_weierstrass::SWCurveConfig, AffineCurve, PairingEngine, ProjectiveCurve,
};
use ark_ff::{
fields::{Field, PrimeField},
One, UniformRand, Zero,
};
use ark_std::{rand::Rng, test_rng};
use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
generate_g1_test!(bls12_381; curve_tests; sw_tests;);
generate_g2_test!(bls12_381; curve_tests; sw_tests;);
generate_bilinearity_test!(Bls12_381, Fq12);
generate_g1_generator_raw_test!(bls12_381, 4);
#[test]
fn test_g1_endomorphism_beta() {
assert!(g1::BETA.pow(&[3u64]).is_one());
}
#[test]
fn test_g1_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G1Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g1_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x(x, greatest) {
if !p.into_projective().mul(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
#[test]
fn test_g2_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G2Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq2::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G2Affine::get_point_from_x(x, greatest) {
if !p.into_projective().mul(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}

119
bls12_381/src/curves/tests/mod.rs Executable file
View File

@@ -0,0 +1,119 @@
use ark_algebra_test_templates::*;
use ark_ec::{AffineRepr, CurveGroup, Group};
use ark_ff::{fields::Field, One, UniformRand, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
use ark_std::{rand::Rng, test_rng, vec};
use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm);
test_pairing!(pairing; crate::Bls12_381);
#[test]
fn test_g1_endomorphism_beta() {
assert!(crate::g1::BETA.pow(&[3u64]).is_one());
}
#[test]
fn test_g1_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G1Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g1_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x_unchecked(x, greatest) {
if !p.mul_bigint(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
#[test]
fn test_g2_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G2Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq2::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G2Affine::get_point_from_x_unchecked(x, greatest) {
if !p.mul_bigint(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
// Test vectors and macro adapted from https://github.com/zkcrypto/bls12_381/blob/e224ad4ea1babfc582ccd751c2bf128611d10936/src/tests/mod.rs
macro_rules! test_vectors {
($projective:ident, $affine:ident, $compress:expr, $expected:ident) => {
let mut e = $projective::zero();
let mut v = vec![];
{
let mut expected = $expected;
for _ in 0..1000 {
let e_affine = $affine::from(e);
let mut serialized = vec![0u8; e.serialized_size($compress)];
e_affine
.serialize_with_mode(serialized.as_mut_slice(), $compress)
.unwrap();
v.extend_from_slice(&serialized[..]);
let mut decoded = serialized;
let len_of_encoding = decoded.len();
(&mut decoded[..]).copy_from_slice(&expected[0..len_of_encoding]);
expected = &expected[len_of_encoding..];
let decoded =
$affine::deserialize_with_mode(&decoded[..], $compress, Validate::Yes).unwrap();
assert_eq!(e_affine, decoded);
e += &$projective::generator();
}
}
assert_eq!(&v[..], $expected);
};
}
#[test]
fn g1_compressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g1_compressed_valid_test_vectors.dat");
test_vectors!(G1Projective, G1Affine, Compress::Yes, bytes);
}
#[test]
fn g1_uncompressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g1_uncompressed_valid_test_vectors.dat");
test_vectors!(G1Projective, G1Affine, Compress::No, bytes);
}
#[test]
fn g2_compressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g2_compressed_valid_test_vectors.dat");
test_vectors!(G2Projective, G2Affine, Compress::Yes, bytes);
}
#[test]
fn g2_uncompressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g2_uncompressed_valid_test_vectors.dat");
test_vectors!(G2Projective, G2Affine, Compress::No, bytes);
}

View File

@@ -0,0 +1,215 @@
use ark_ec::{short_weierstrass::Affine, AffineRepr};
use ark_ff::{BigInteger384, PrimeField};
use ark_serialize::SerializationError;
use crate::{g1::Config as G1Config, g2::Config as G2Config, Fq, Fq2, G1Affine, G2Affine};
pub const G1_SERIALIZED_SIZE: usize = 48;
pub const G2_SERIALIZED_SIZE: usize = 96;
pub struct EncodingFlags {
pub is_compressed: bool,
pub is_infinity: bool,
pub is_lexographically_largest: bool,
}
impl EncodingFlags {
pub fn get_flags(bytes: &[u8]) -> Self {
let compression_flag_set = (bytes[0] >> 7) & 1;
let infinity_flag_set = (bytes[0] >> 6) & 1;
let sort_flag_set = (bytes[0] >> 5) & 1;
Self {
is_compressed: compression_flag_set == 1,
is_infinity: infinity_flag_set == 1,
is_lexographically_largest: sort_flag_set == 1,
}
}
pub fn encode_flags(&self, bytes: &mut [u8]) {
if self.is_compressed {
bytes[0] |= 1 << 7;
}
if self.is_infinity {
bytes[0] |= 1 << 6;
}
if self.is_compressed && !self.is_infinity && self.is_lexographically_largest {
bytes[0] |= 1 << 5;
}
}
}
pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> {
let mut tmp = BigInteger384::new([0, 0, 0, 0, 0, 0]);
// Note: The following unwraps are if the compiler cannot convert
// the byte slice into [u8;8], we know this is infallible since we
// are providing the indices at compile time and bytes has a fixed size
tmp.0[5] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap());
tmp.0[4] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
tmp.0[3] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap());
tmp.0[2] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap());
tmp.0[1] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap());
tmp.0[0] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap());
Fq::from_bigint(tmp)
}
pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] {
let mut result = [0u8; 48];
let rep = field.into_bigint();
result[0..8].copy_from_slice(&rep.0[5].to_be_bytes());
result[8..16].copy_from_slice(&rep.0[4].to_be_bytes());
result[16..24].copy_from_slice(&rep.0[3].to_be_bytes());
result[24..32].copy_from_slice(&rep.0[2].to_be_bytes());
result[32..40].copy_from_slice(&rep.0[1].to_be_bytes());
result[40..48].copy_from_slice(&rep.0[0].to_be_bytes());
result
}
pub(crate) fn read_fq_with_offset(
bytes: &[u8],
offset: usize,
mask: bool,
) -> Result<Fq, ark_serialize::SerializationError> {
let mut tmp = [0; G1_SERIALIZED_SIZE];
// read `G1_SERIALIZED_SIZE` bytes
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
if mask {
// Mask away the flag bits
tmp[0] &= 0b0001_1111;
}
deserialize_fq(tmp).ok_or(SerializationError::InvalidData)
}
pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G1Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; G1_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.ok()
.ok_or(SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..]);
// we expect to be deserializing a compressed point
if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
if flags.is_infinity {
return Ok(G1Affine::zero());
}
// Attempt to obtain the x-coordinate
let x = read_fq_with_offset(&bytes, 0, true)?;
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
.ok_or(SerializationError::InvalidData)?;
Ok(p)
}
pub(crate) fn read_g1_uncompressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G1Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..]);
// we expect to be deserializing an uncompressed point
if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
if flags.is_infinity {
return Ok(G1Affine::zero());
}
// Attempt to obtain the x-coordinate
let x = read_fq_with_offset(&bytes, 0, true)?;
// Attempt to obtain the y-coordinate
let y = read_fq_with_offset(&bytes, 1, false)?;
let p = G1Affine::new_unchecked(x, y);
Ok(p)
}
pub(crate) fn read_g2_compressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G2Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; G2_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes);
// we expect to be deserializing a compressed point
if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
if flags.is_infinity {
return Ok(G2Affine::zero());
}
// Attempt to obtain the x-coordinate
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
let x = Fq2::new(xc0, xc1);
let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
.ok_or(SerializationError::InvalidData)?;
Ok(p)
}
pub(crate) fn read_g2_uncompressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G2Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes);
// we expect to be deserializing an uncompressed point
if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
if flags.is_infinity {
return Ok(G2Affine::zero());
}
// Attempt to obtain the x-coordinate
let xc1 = read_fq_with_offset(&bytes, 0, true)?;
let xc0 = read_fq_with_offset(&bytes, 1, false)?;
let x = Fq2::new(xc0, xc1);
// Attempt to obtain the y-coordinate
let yc1 = read_fq_with_offset(&bytes, 2, false)?;
let yc0 = read_fq_with_offset(&bytes, 3, false)?;
let y = Fq2::new(yc0, yc1);
let p = G2Affine::new_unchecked(x, y);
Ok(p)
}

View File

@@ -3,5 +3,7 @@ use ark_ff::fields::{Fp384, MontBackend, MontConfig};
#[derive(MontConfig)] #[derive(MontConfig)]
#[modulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"] #[modulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"]
#[generator = "2"] #[generator = "2"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "2"]
pub struct FqConfig; pub struct FqConfig;
pub type Fq = Fp384<MontBackend<FqConfig, 6>>; pub type Fq = Fp384<MontBackend<FqConfig, 6>>;

View File

@@ -21,7 +21,22 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fp: &Self::Fp) -> Self::Fp { fn mul_fp_by_nonresidue_in_place(fp: &mut Self::Fp) -> &mut Self::Fp {
-(*fp) fp.neg_in_place()
}
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
*y += x;
}
#[inline(always)]
fn mul_fp_by_nonresidue_plus_one_and_add(y: &mut Self::Fp, x: &Self::Fp) {
*y = *x;
}
fn mul_fp_by_nonresidue_and_add(y: &mut Self::Fp, x: &Self::Fp) {
y.neg_in_place();
*y += x;
} }
} }

View File

@@ -82,11 +82,10 @@ impl Fp6Config for Fq6Config {
/// Multiply this element by the quadratic nonresidue 1 + u. /// Multiply this element by the quadratic nonresidue 1 + u.
/// Make this generic. /// Make this generic.
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 { fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
let mut copy = *fe; let t0 = fe.c0;
let t0 = copy.c0; fe.c0 -= &fe.c1;
copy.c0 -= &fe.c1; fe.c1 += &t0;
copy.c1 += &t0; fe
copy
} }
} }

View File

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

View File

@@ -1,23 +1,22 @@
use ark_algebra_test_templates::{ use ark_algebra_test_templates::*;
fields::*, generate_field_serialization_test, generate_field_test,
};
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, One, UniformRand, Zero,
}; };
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::{ use ark_std::{
cmp::Ordering, cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign}, ops::{AddAssign, MulAssign, SubAssign},
rand::Rng, vec,
test_rng, vec,
}; };
use crate::{Fq, Fq12, Fq12Config, Fq2, Fq2Config, Fq6, Fq6Config, FqConfig, Fr, FrConfig}; use crate::{Fq, Fq12, Fq12Config, Fq2, Fq2Config, Fq6, Fq6Config, Fr};
generate_field_test!(bls12_381; fq2; fq6; fq12; mont(6, 4); ); test_field!(fr; Fr; mont_prime_field);
generate_field_serialization_test!(bls12_381; fq2; fq6; fq12;); test_field!(fq; Fq; mont_prime_field);
test_field!(fq2; Fq2);
test_field!(fq6; Fq6);
test_field!(fq12; Fq12);
#[test] #[test]
fn test_negative_one() { fn test_negative_one() {
@@ -1602,7 +1601,7 @@ fn test_fq2_doubling() {
} }
#[test] #[test]
fn test_fq2_frobenius_map() { fn test_fq2_frobenius_map_in_place() {
let mut a = Fq2::new( let mut a = Fq2::new(
Fq::from(BigInt::new([ Fq::from(BigInt::new([
0x2d0078036923ffc7, 0x2d0078036923ffc7,
@@ -1621,7 +1620,7 @@ fn test_fq2_frobenius_map() {
0x12d1137b8a6a837, 0x12d1137b8a6a837,
])), ])),
); );
a.frobenius_map(0); a.frobenius_map_in_place(0);
assert_eq!( assert_eq!(
a, a,
Fq2::new( Fq2::new(
@@ -1643,7 +1642,7 @@ fn test_fq2_frobenius_map() {
])), ])),
) )
); );
a.frobenius_map(1); a.frobenius_map_in_place(1);
assert_eq!( assert_eq!(
a, a,
Fq2::new( Fq2::new(
@@ -1665,7 +1664,7 @@ fn test_fq2_frobenius_map() {
])), ])),
) )
); );
a.frobenius_map(1); a.frobenius_map_in_place(1);
assert_eq!( assert_eq!(
a, a,
Fq2::new( Fq2::new(
@@ -1687,7 +1686,7 @@ fn test_fq2_frobenius_map() {
])), ])),
) )
); );
a.frobenius_map(2); a.frobenius_map_in_place(2);
assert_eq!( assert_eq!(
a, a,
Fq2::new( Fq2::new(
@@ -1719,7 +1718,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1); Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }
@@ -1732,7 +1731,7 @@ fn test_fq2_mul_nonresidue() {
for _ in 0..1000 { for _ in 0..1000 {
let mut a = Fq2::rand(&mut rng); let mut a = Fq2::rand(&mut rng);
let mut b = a; let mut b = a;
a = Fq6Config::mul_fp2_by_nonresidue(&a); Fq6Config::mul_fp2_by_nonresidue_in_place(&mut a);
b.mul_assign(&nqr); b.mul_assign(&nqr);
assert_eq!(a, b); assert_eq!(a, b);
@@ -1748,7 +1747,7 @@ fn test_fq6_mul_nonresidue() {
for _ in 0..1000 { for _ in 0..1000 {
let mut a = Fq6::rand(&mut rng); let mut a = Fq6::rand(&mut rng);
let mut b = a; let mut b = a;
a = Fq12Config::mul_fp6_by_nonresidue(&a); Fq12Config::mul_fp6_by_nonresidue_in_place(&mut a);
b.mul_assign(&nqr); b.mul_assign(&nqr);
assert_eq!(a, b); assert_eq!(a, b);

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-bn254" name = "ark-bn254"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "The BN254 pairing-friendly elliptic curve" description = "The BN254 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,16 +10,17 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-ff = { version="^0.3.0", default-features = false } ark-ff = { version="0.4.0-alpha", default-features = false }
ark-ec = { version="^0.3.0", default-features = false } ark-ec = { version="0.4.0-alpha", default-features = false }
ark-std = { version="^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
[dev-dependencies] [dev-dependencies]
ark-serialize = { version="^0.3.0", default-features = false } ark-serialize = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version="^0.3.0", default-features = false } ark-algebra-test-templates = { version = "0.4.0-alpha", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0-alpha", default-features = false }
[features] [features]
default = [ "curve" ] default = [ "curve" ]
@@ -27,3 +28,8 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ] curve = [ "scalar_field" ]
scalar_field = [] scalar_field = []
[[bench]]
name = "bn254"
path = "benches/bn254.rs"
harness = false

13
bn254/benches/bn254.rs Normal file
View File

@@ -0,0 +1,13 @@
use ark_algebra_bench_templates::*;
use ark_bn254::{fq::Fq, fq2::Fq2, fr::Fr, Bn254, Fq12, G1Projective as G1, G2Projective as G2};
bench!(
Name = "BN254",
Pairing = Bn254,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -7,11 +7,11 @@ use ark_ff::{Field, MontFp, Zero};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
pub type G1Affine = Affine<Parameters>; pub type G1Affine = Affine<Config>;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -22,7 +22,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = Fr::ONE; const COFACTOR_INV: Fr = Fr::ONE;
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 0 /// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO; const COEFF_A: Fq = Fq::ZERO;
@@ -33,7 +33,7 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
} }

View File

@@ -6,12 +6,12 @@ use ark_ff::{Field, MontFp, Zero};
use crate::{Fq, Fq2, Fr}; use crate::{Fq, Fq2, Fr};
pub type G2Affine = Affine<Parameters>; pub type G2Affine = Affine<Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq2; type BaseField = Fq2;
type ScalarField = Fr; type ScalarField = Fr;
@@ -30,7 +30,7 @@ impl CurveConfig for Parameters {
MontFp!("10944121435919637613327163357776759465618812564592884533313067514031822496649"); MontFp!("10944121435919637613327163357776759465618812564592884533313067514031822496649");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = [0, 0] /// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::ZERO; const COEFF_A: Fq2 = Fq2::ZERO;
@@ -45,7 +45,7 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero() Self::BaseField::zero()
} }
} }

View File

@@ -1,6 +1,6 @@
use ark_ec::{ use ark_ec::{
bn, bn,
bn::{Bn, BnParameters, TwistType}, bn::{Bn, BnConfig, TwistType},
}; };
use ark_ff::MontFp; use ark_ff::MontFp;
@@ -12,9 +12,9 @@ pub mod g2;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub struct Parameters; pub struct Config;
impl BnParameters for Parameters { impl BnConfig for Config {
const X: &'static [u64] = &[4965661367192848881]; const X: &'static [u64] = &[4965661367192848881];
/// `x` is positive. /// `x` is positive.
const X_IS_NEGATIVE: bool = false; const X_IS_NEGATIVE: bool = false;
@@ -37,13 +37,13 @@ impl BnParameters for Parameters {
type Fp2Config = Fq2Config; type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config; type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config; type Fp12Config = Fq12Config;
type G1Parameters = g1::Parameters; type G1Config = g1::Config;
type G2Parameters = g2::Parameters; type G2Config = g2::Config;
} }
pub type Bn254 = Bn<Parameters>; pub type Bn254 = Bn<Config>;
pub type G1Affine = bn::G1Affine<Parameters>; pub type G1Affine = bn::G1Affine<Config>;
pub type G1Projective = bn::G1Projective<Parameters>; pub type G1Projective = bn::G1Projective<Config>;
pub type G2Affine = bn::G2Affine<Parameters>; pub type G2Affine = bn::G2Affine<Config>;
pub type G2Projective = bn::G2Projective<Parameters>; pub type G2Projective = bn::G2Projective<Config>;

View File

@@ -1,16 +1,9 @@
use ark_algebra_test_templates::{ use ark_algebra_test_templates::*;
curves::*, generate_bilinearity_test, generate_g1_test, generate_g2_test, msm::*, use ark_ff::fields::Field;
};
use ark_ec::{AffineCurve, PairingEngine};
use ark_ff::{
fields::{Field, PrimeField},
One,
};
use ark_std::{rand::Rng, test_rng};
use core::ops::MulAssign;
use crate::{g1, g2, Bn254, Fq12, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; use crate::{Bn254, G1Projective, G2Projective};
generate_g1_test!(bn254; curve_tests; sw_tests;); test_group!(g1; G1Projective; sw);
generate_g2_test!(bn254; curve_tests; sw_tests;); test_group!(g2; G2Projective; sw);
generate_bilinearity_test!(Bn254, Fq12); test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
test_pairing!(pairing; crate::Bn254);

View File

@@ -21,7 +21,7 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp { fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
-(*fe) fe.neg_in_place()
} }
} }

View File

@@ -90,12 +90,16 @@ impl Fp6Config for Fq6Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 { fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0) // (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0)
let mut f = *fe; let mut f = *fe;
f.double_in_place().double_in_place().double_in_place(); f.double_in_place().double_in_place().double_in_place();
let c0 = f.c0 + fe.c0 + Fq2Config::mul_fp_by_nonresidue(&fe.c1); let mut c0 = fe.c1;
Fq2Config::mul_fp_by_nonresidue_in_place(&mut c0);
c0 += &f.c0;
c0 += &fe.c0;
let c1 = f.c1 + fe.c1 + fe.c0; let c1 = f.c1 + fe.c1 + fe.c0;
Fq2::new(c0, c1) *fe = Fq2::new(c0, c1);
fe
} }
} }

View File

@@ -1,22 +1,21 @@
use ark_algebra_test_templates::{ use ark_algebra_test_templates::*;
fields::*, generate_field_serialization_test, generate_field_test,
};
use ark_ff::{ use ark_ff::{
biginteger::{BigInt, BigInteger, BigInteger256}, biginteger::{BigInt, BigInteger, BigInteger256},
fields::{FftField, Field, Fp6Config, PrimeField}, fields::{FftField, Field, Fp6Config, PrimeField},
One, UniformRand, Zero, One, UniformRand, Zero,
}; };
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize}; use ark_std::{
use ark_std::{rand::Rng, test_rng};
use core::{
cmp::Ordering, cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign}, ops::{AddAssign, MulAssign},
}; };
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, FqConfig, Fr, FrConfig}; use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, Fr};
generate_field_test!(bn254; fq2; fq6; fq12; mont(4, 4); ); test_field!(fr; Fr; mont_prime_field);
generate_field_serialization_test!(bn254; fq2; fq6; fq12;); test_field!(fq; Fq; mont_prime_field);
test_field!(fq2; Fq2);
test_field!(fq6; Fq6);
test_field!(fq12; Fq12);
#[test] #[test]
fn test_fq_repr_from() { fn test_fq_repr_from() {
@@ -140,7 +139,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1); Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-bw6-761" name = "ark-bw6-761"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "The BW6-761 pairing-friendly elliptic curve" description = "The BW6-761 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,18 +10,24 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-ff = { version="^0.3.0", default-features = false } ark-ff = { version="0.4.0-alpha", default-features = false }
ark-ec = { version="^0.3.0", default-features = false } ark-ec = { version="0.4.0-alpha", default-features = false }
ark-std = { version="^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
ark-bls12-377 = { version="^0.3.0", path = "../bls12_377", default-features = false, features = [ "base_field" ] } ark-bls12-377 = { version = "0.4.0-alpha", path = "../bls12_377", default-features = false, features = [ "base_field" ] }
[dev-dependencies] [dev-dependencies]
ark-serialize = { version="^0.3.0", default-features = false } ark-serialize = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version="^0.3.0", default-features = false } ark-algebra-test-templates = { version = "0.4.0-alpha", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0-alpha", default-features = false }
[features] [features]
default = [] default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ]
[[bench]]
name = "bw6_761"
path = "benches/bw6_761.rs"
harness = false

View File

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

View File

@@ -6,13 +6,13 @@ use ark_ff::{Field, MontFp};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
pub type G1Affine = Affine<Parameters>; pub type G1Affine = Affine<Config>;
pub type G1Projective = Projective<Parameters>; pub type G1Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -33,7 +33,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = MontFp!("91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804"); const COFACTOR_INV: Fr = MontFp!("91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 0 /// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO; const COEFF_A: Fq = Fq::ZERO;
@@ -43,7 +43,7 @@ impl SWCurveConfig for Parameters {
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero; use ark_ff::Zero;
Self::BaseField::zero() Self::BaseField::zero()
} }

View File

@@ -6,13 +6,13 @@ use ark_ff::{Field, MontFp};
use crate::{Fq, Fr}; use crate::{Fq, Fr};
pub type G2Affine = Affine<Parameters>; pub type G2Affine = Affine<Config>;
pub type G2Projective = Projective<Parameters>; pub type G2Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -33,7 +33,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = MontFp!("214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124"); const COFACTOR_INV: Fr = MontFp!("214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 0 /// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO; const COEFF_A: Fq = Fq::ZERO;
@@ -44,7 +44,7 @@ impl SWCurveConfig for Parameters {
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)] #[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField { fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero; use ark_ff::Zero;
Self::BaseField::zero() Self::BaseField::zero()
} }

View File

@@ -1,6 +1,6 @@
use ark_ec::{ use ark_ec::{
bw6, bw6,
bw6::{BW6Parameters, TwistType, BW6}, bw6::{BW6Config, TwistType, BW6},
}; };
use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt}; use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt};
@@ -13,9 +13,9 @@ pub mod g2;
mod tests; mod tests;
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl BW6Parameters for Parameters { impl BW6Config for Config {
const X: BigInteger = BigInt::new([ const X: BigInteger = BigInt::new([
0x8508c00000000001, 0x8508c00000000001,
0x0, 0x0,
@@ -50,13 +50,13 @@ impl BW6Parameters for Parameters {
type Fp = Fq; type Fp = Fq;
type Fp3Config = Fq3Config; type Fp3Config = Fq3Config;
type Fp6Config = Fq6Config; type Fp6Config = Fq6Config;
type G1Parameters = g1::Parameters; type G1Config = g1::Config;
type G2Parameters = g2::Parameters; type G2Config = g2::Config;
} }
pub type BW6_761 = BW6<Parameters>; pub type BW6_761 = BW6<Config>;
pub type G1Affine = bw6::G1Affine<Parameters>; pub type G1Affine = bw6::G1Affine<Config>;
pub type G1Projective = bw6::G1Projective<Parameters>; pub type G1Projective = bw6::G1Projective<Config>;
pub type G2Affine = bw6::G2Affine<Parameters>; pub type G2Affine = bw6::G2Affine<Config>;
pub type G2Projective = bw6::G2Projective<Parameters>; pub type G2Projective = bw6::G2Projective<Config>;

View File

@@ -1,13 +1,8 @@
use ark_algebra_test_templates::{
curves::*, generate_bilinearity_test, generate_g1_test, generate_g2_test, msm::*,
};
use ark_ec::{AffineCurve, PairingEngine};
use ark_ff::{Field, One, PrimeField};
use ark_std::{rand::Rng, test_rng};
use core::ops::MulAssign;
use crate::*; use crate::*;
use ark_algebra_test_templates::*;
use ark_ff::Field;
generate_g1_test!(bw6_761; curve_tests; sw_tests;); test_group!(g1; G1Projective; sw);
generate_g2_test!(bw6_761; curve_tests; sw_tests;); test_group!(g2; G2Projective; sw);
generate_bilinearity_test!(BW6_761, Fq6); test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
test_pairing!(pairing; crate::BW6_761);

View File

@@ -82,9 +82,7 @@ impl Fp3Config for Fq3Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp { fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
let original = -(*fe); fe.double_in_place().double_in_place().neg_in_place()
let double = original + &original;
double + &double
} }
} }

View File

@@ -1,12 +1,7 @@
use ark_algebra_test_templates::{
fields::*, generate_field_serialization_test, generate_field_test,
};
use ark_ff::{Field, One, PrimeField, UniformRand, Zero};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::{rand::Rng, test_rng};
use core::ops::{AddAssign, MulAssign, SubAssign};
use crate::*; use crate::*;
use ark_algebra_test_templates::*;
generate_field_test!(bw6_761; fq3; fq6_2_on_3; false; mont(12, 6); ); test_field!(fr; Fr; mont_prime_field);
generate_field_serialization_test!(bw6_761;); test_field!(fq; Fq; mont_prime_field);
test_field!(fq3; Fq3);
test_field!(fq6; Fq6);

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-cp6-782" name = "ark-cp6-782"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "The CP6-782 pairing-friendly elliptic curve" description = "The CP6-782 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,18 +10,25 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-ff = { version = "^0.3.0", default-features = false } ark-ff = { version = "0.4.0-alpha", default-features = false }
ark-ec = { version = "^0.3.0", default-features = false } ark-ec = { version = "0.4.0-alpha", default-features = false }
ark-std = { version = "^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
ark-bls12-377 = { version = "^0.3.0", path = "../bls12_377", default-features = false, features = [ "base_field" ] } ark-bls12-377 = { version = "0.4.0-alpha", path = "../bls12_377", default-features = false, features = [ "base_field" ] }
itertools = { version = "0.10", default-features = false }
ark-serialize = { version = "0.4.0-alpha", default-features = false }
[dev-dependencies] [dev-dependencies]
ark-serialize = { version = "^0.3.0", default-features = false } ark-algebra-test-templates = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version = "^0.3.0", default-features = false } ark-algebra-bench-templates = { version = "0.4.0-alpha", default-features = false }
[features] [features]
default = [] default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ]
[[bench]]
name = "cp6_782"
path = "benches/cp6_782.rs"
harness = false

1
cp6_782/LICENSE-APACHE Symbolic link
View File

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

1
cp6_782/LICENSE-MIT Symbolic link
View File

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

View File

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

View File

@@ -1,18 +1,60 @@
use ark_ec::{ use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig}, models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::{Affine, Projective}, short_weierstrass::{Affine, Projective},
AffineRepr, CurveGroup,
}; };
use ark_ff::MontFp; use ark_ff::MontFp;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::vec::Vec;
use crate::{Fq, Fr}; use crate::{Fq, Fr};
pub type G1Affine = Affine<Parameters>; pub type G1Affine = Affine<Config>;
pub type G1Projective = Projective<Parameters>; pub type G1Projective = Projective<Config>;
#[derive(Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)]
pub struct G1Prepared(pub G1Affine);
impl From<G1Affine> for G1Prepared {
fn from(other: G1Affine) -> Self {
G1Prepared(other)
}
}
impl From<G1Projective> for G1Prepared {
fn from(q: G1Projective) -> Self {
q.into_affine().into()
}
}
impl<'a> From<&'a G1Affine> for G1Prepared {
fn from(other: &'a G1Affine) -> Self {
G1Prepared(*other)
}
}
impl<'a> From<&'a G1Projective> for G1Prepared {
fn from(q: &'a G1Projective) -> Self {
q.into_affine().into()
}
}
impl G1Prepared {
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
}
impl Default for G1Prepared {
fn default() -> Self {
G1Prepared(G1Affine::generator())
}
}
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq; type BaseField = Fq;
type ScalarField = Fr; type ScalarField = Fr;
@@ -34,7 +76,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = MontFp!("163276846538158998893990986356139314746223949404500031940624325017036397274793417940375498603127780919653358641788"); const COFACTOR_INV: Fr = MontFp!("163276846538158998893990986356139314746223949404500031940624325017036397274793417940375498603127780919653358641788");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = 5 /// COEFF_A = 5
const COEFF_A: Fq = MontFp!("5"); const COEFF_A: Fq = MontFp!("5");

View File

@@ -1,18 +1,60 @@
use ark_ec::{ use ark_ec::{
models::CurveConfig, models::CurveConfig,
short_weierstrass::{Affine, Projective, SWCurveConfig}, short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveGroup,
}; };
use ark_ff::{Field, MontFp}; use ark_ff::{Field, MontFp};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::vec::Vec;
use crate::{Fq, Fq3, Fr}; use crate::{Fq, Fq3, Fr};
pub type G2Affine = Affine<Parameters>; pub type G2Affine = Affine<Config>;
pub type G2Projective = Projective<Parameters>; pub type G2Projective = Projective<Config>;
#[derive(Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)]
pub struct G2Prepared(pub G2Affine);
impl From<G2Affine> for G2Prepared {
fn from(other: G2Affine) -> Self {
G2Prepared(other)
}
}
impl From<G2Projective> for G2Prepared {
fn from(q: G2Projective) -> Self {
q.into_affine().into()
}
}
impl<'a> From<&'a G2Affine> for G2Prepared {
fn from(other: &'a G2Affine) -> Self {
G2Prepared(*other)
}
}
impl<'a> From<&'a G2Projective> for G2Prepared {
fn from(q: &'a G2Projective) -> Self {
q.into_affine().into()
}
}
impl G2Prepared {
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
}
impl Default for G2Prepared {
fn default() -> Self {
G2Prepared(G2Affine::generator())
}
}
#[derive(Clone, Default, PartialEq, Eq)] #[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters; pub struct Config;
impl CurveConfig for Parameters { impl CurveConfig for Config {
type BaseField = Fq3; type BaseField = Fq3;
type ScalarField = Fr; type ScalarField = Fr;
@@ -58,7 +100,7 @@ impl CurveConfig for Parameters {
const COFACTOR_INV: Fr = MontFp!("45586359457219724873147353901735745013467692594291916855200979604570630929674383405372210802279573887880950375598"); const COFACTOR_INV: Fr = MontFp!("45586359457219724873147353901735745013467692594291916855200979604570630929674383405372210802279573887880950375598");
} }
impl SWCurveConfig for Parameters { impl SWCurveConfig for Config {
/// COEFF_A = (0, 0, COEFF_A * TWIST^2) = (0, 0, 5) /// COEFF_A = (0, 0, COEFF_A * TWIST^2) = (0, 0, 5)
const COEFF_A: Fq3 = Fq3::new(Fq::ZERO, Fq::ZERO, MontFp!("5")); const COEFF_A: Fq3 = Fq3::new(Fq::ZERO, Fq::ZERO, MontFp!("5"));

View File

@@ -1,17 +1,19 @@
use ark_ec::{models::short_weierstrass::SWCurveConfig, PairingEngine}; use ark_ec::{
use ark_ff::{ models::short_weierstrass::SWCurveConfig,
biginteger::BigInteger832, pairing::{MillerLoopOutput, Pairing, PairingOutput},
fields::{BitIteratorBE, Field},
BigInt, One,
}; };
use ark_ff::{
biginteger::BigInteger832, BigInt, BitIteratorBE, CyclotomicMultSubgroup, Field, One,
};
use itertools::Itertools;
use crate::{Fq, Fq3, Fq6, Fr}; use crate::{Fq, Fq3, Fq6, Fr};
pub mod g1; pub mod g1;
pub use self::g1::{G1Affine, G1Projective}; pub use self::g1::{G1Affine, G1Prepared, G1Projective};
pub mod g2; pub mod g2;
pub use self::g2::{G2Affine, G2Projective}; pub use self::g2::{G2Affine, G2Prepared, G2Projective};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -21,40 +23,40 @@ pub type GT = Fq6;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CP6_782; pub struct CP6_782;
impl PairingEngine for CP6_782 { impl Pairing for CP6_782 {
type Fr = Fr; type ScalarField = Fr;
type G1Projective = G1Projective; type BaseField = Fq;
type G1 = G1Projective;
type G1Affine = G1Affine; type G1Affine = G1Affine;
type G1Prepared = G1Affine; type G1Prepared = G1Prepared;
type G2Projective = G2Projective; type G2 = G2Projective;
type G2Affine = G2Affine; type G2Affine = G2Affine;
type G2Prepared = G2Affine; type G2Prepared = G2Prepared;
type Fq = Fq; type TargetField = Fq6;
type Fqe = Fq3;
type Fqk = Fq6;
fn miller_loop<'a, I>(i: I) -> Self::Fqk fn multi_miller_loop(
where a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
I: IntoIterator<Item = &'a (Self::G1Prepared, Self::G2Prepared)>, b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
{ ) -> MillerLoopOutput<Self> {
let mut result = Self::Fqk::one(); let mut result = Self::TargetField::one();
for &(ref p, ref q) in i { a.into_iter().zip_eq(b).for_each(|(p, q)| {
result *= &CP6_782::ate_miller_loop(p, q); let (p, q) = (p.into(), q.into());
} result *= &CP6_782::ate_miller_loop(&p, &q);
result });
MillerLoopOutput(result)
} }
fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk> { fn final_exponentiation(r: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>> {
Some(CP6_782::final_exponentiation(r)) Some(PairingOutput(CP6_782::final_exponentiation(&r.0)))
} }
} }
impl CP6_782 { impl CP6_782 {
pub fn ate_pairing(p: &G1Affine, q: &G2Affine) -> GT { fn ate_miller_loop(p: &G1Prepared, q: &G2Prepared) -> Fq6 {
CP6_782::final_exponentiation(&CP6_782::ate_miller_loop(p, q)) let p = p.0;
} let q = q.0;
fn ate_miller_loop(p: &G1Affine, q: &G2Affine) -> Fq6 {
let px = p.x; let px = p.x;
let py = p.y; let py = p.y;
let qx = q.x; let qx = q.x;
@@ -76,7 +78,7 @@ impl CP6_782 {
let old_rx_square = old_rx.square(); let old_rx_square = old_rx.square();
let old_rx_square_3 = old_rx_square.double() + &old_rx_square; let old_rx_square_3 = old_rx_square.double() + &old_rx_square;
let old_rx_square_3_a = old_rx_square_3 + &g2::Parameters::COEFF_A; let old_rx_square_3_a = old_rx_square_3 + &g2::Config::COEFF_A;
let old_ry_double_inverse = old_ry.double().inverse().unwrap(); let old_ry_double_inverse = old_ry.double().inverse().unwrap();
let gamma = old_rx_square_3_a * &old_ry_double_inverse; let gamma = old_rx_square_3_a * &old_ry_double_inverse;
@@ -127,19 +129,19 @@ impl CP6_782 {
// elt_q3 = elt^(q^3) // elt_q3 = elt^(q^3)
let mut elt_q3 = elt.clone(); let mut elt_q3 = elt.clone();
elt_q3.frobenius_map(3); elt_q3.frobenius_map_in_place(3);
// elt_q3_over_elt = elt^(q^3-1) // elt_q3_over_elt = elt^(q^3-1)
let elt_q3_over_elt = elt_q3 * elt_inv; let elt_q3_over_elt = elt_q3 * elt_inv;
// alpha = elt^((q^3-1) * q) // alpha = elt^((q^3-1) * q)
let mut alpha = elt_q3_over_elt.clone(); let mut alpha = elt_q3_over_elt.clone();
alpha.frobenius_map(1); alpha.frobenius_map_in_place(1);
// beta = elt^((q^3-1)*(q+1) // beta = elt^((q^3-1)*(q+1)
alpha * &elt_q3_over_elt alpha * &elt_q3_over_elt
} }
fn final_exponentiation_last(elt: &Fq6, elt_inv: &Fq6) -> Fq6 { fn final_exponentiation_last(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
let mut elt_q = elt.clone(); let mut elt_q = elt.clone();
elt_q.frobenius_map(1); elt_q.frobenius_map_in_place(1);
let w1_part = elt_q.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_W1); let w1_part = elt_q.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_W1);
let w0_part = if FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG { let w0_part = if FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {

View File

@@ -1,13 +1,9 @@
use ark_algebra_test_templates::{ use ark_algebra_test_templates::*;
curves::*, generate_bilinearity_test, generate_g1_test, generate_g2_test, msm::*, use ark_ff::Field;
};
use ark_ec::{AffineCurve, PairingEngine};
use ark_ff::{Field, One, PrimeField};
use ark_std::{rand::Rng, test_rng};
use core::ops::MulAssign;
use crate::*; use crate::*;
generate_g1_test!(cp6_782; curve_tests; sw_tests;); test_group!(g1; G1Projective; sw);
generate_g2_test!(cp6_782; curve_tests; sw_tests;); test_group!(g2; G2Projective; sw);
generate_bilinearity_test!(CP6_782, Fq6); test_group!(pairing_output; ark_ec::pairing::PairingOutput<CP6_782>; msm);
test_pairing!(pairing; crate::CP6_782);

View File

@@ -77,11 +77,12 @@ impl Fp3Config for Fq3Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp { fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
let original = *fe; let original = *fe;
let mut four_fe = fe.double(); fe.double_in_place();
four_fe.double_in_place(); *fe += original;
let eight_fe = four_fe.double(); fe.double_in_place().double_in_place();
eight_fe + &four_fe + &original *fe += original;
fe
} }
} }

View File

@@ -1,12 +1,7 @@
use ark_algebra_test_templates::{
fields::*, generate_field_serialization_test, generate_field_test,
};
use ark_ff::{Field, One, PrimeField, UniformRand, Zero};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::{rand::Rng, test_rng};
use core::ops::{AddAssign, MulAssign, SubAssign};
use crate::*; use crate::*;
use ark_algebra_test_templates::*;
generate_field_test!(cp6_782; fq3; fq6_2_on_3; mont(13, 6); ); test_field!(fr; Fr; mont_prime_field);
generate_field_serialization_test!(cp6_782;); test_field!(fq; Fq; mont_prime_field);
test_field!(fq3; Fq3);
test_field!(fq6; Fq6);

View File

@@ -1,115 +0,0 @@
[package]
name = "ark-curve-benches"
version = "0.3.0"
authors = [
"Sean Bowe",
"Alessandro Chiesa",
"Matthew Green",
"Ian Miers",
"Pratyush Mishra",
"Howard Wu",
"Daira Hopwood"
]
description = "A benchmark library for finite fields and elliptic curves"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/algebra/"
keywords = ["cryptography", "finite-fields", "elliptic-curves", "pairing"]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
publish = false
build = "build.rs"
################################# Dependencies ################################
[dependencies]
bencher = { version = "0.1.5" }
[dev-dependencies]
ark-std = { version = "^0.3.0", default-features = false }
ark-ec = { version = "^0.3.0", default-features = false }
ark-ff = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false }
ark-mnt4-298 = { path = "../mnt4_298" }
ark-mnt6-298 = { path = "../mnt6_298" }
ark-mnt4-753 = { path = "../mnt4_753" }
ark-mnt6-753 = { path = "../mnt6_753" }
ark-bn254 = { path = "../bn254" }
ark-bls12-377 = { path = "../bls12_377" }
ark-bls12-381 = { path = "../bls12_381" }
ark-ed-on-bls12-381 = { path = "../ed_on_bls12_381" }
ark-bw6-761 = { path = "../bw6_761" }
ark-cp6-782 = { path = "../cp6_782" }
ark-pallas = { path = "../pallas" }
ark-vesta = { path = "../vesta" }
[features]
asm = [ "ark-ff/asm"]
parallel = [ "ark-ff/parallel", "ark-ec/parallel", ]
n_fold = []
[build-dependencies]
rustc_version = "0.2"
[[bench]]
name = "bls12_377"
path = "benches/bls12_377.rs"
harness = false
[[bench]]
name = "bls12_381"
path = "benches/bls12_381.rs"
harness = false
[[bench]]
name = "bn254"
path = "benches/bn254.rs"
harness = false
[[bench]]
name = "bw6_761"
path = "benches/bw6_761.rs"
harness = false
[[bench]]
name = "cp6_782"
path = "benches/cp6_782.rs"
harness = false
[[bench]]
name = "ed_on_bls12_381"
path = "benches/ed_on_bls12_381.rs"
harness = false
[[bench]]
name = "mnt4_298"
path = "benches/mnt4_298.rs"
harness = false
[[bench]]
name = "mnt6_298"
path = "benches/mnt6_298.rs"
harness = false
[[bench]]
name = "mnt4_753"
path = "benches/mnt4_753.rs"
harness = false
[[bench]]
name = "mnt6_753"
path = "benches/mnt6_753.rs"
harness = false
[[bench]]
name = "pallas"
path = "benches/pallas.rs"
harness = false
[[bench]]
name = "vesta"
path = "benches/vesta.rs"
harness = false

View File

@@ -1,30 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_377::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_377, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{
biginteger::{BigInteger256 as FrRepr, BigInteger384 as FqRepr},
BigInteger, Field, PrimeField, UniformRand,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
f_bench!(extension, Fq2, Fq2, fq2);
f_bench!(target, Fq12, Fq12, fq12);
pairing_bench!(Bls12_377, Fq12);
bencher::benchmark_main!(fq, fr, fq2, fq12, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,30 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bls12_381::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{
biginteger::{BigInteger256 as FrRepr, BigInteger384 as FqRepr},
BigInteger, Field, PrimeField, UniformRand,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
f_bench!(extension, Fq2, Fq2, fq2);
f_bench!(target, Fq12, Fq12, fq12);
pairing_bench!(Bls12_381, Fq12);
bencher::benchmark_main!(fq, fr, fq2, fq12, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,27 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bn254::{
fq::Fq, fq2::Fq2, fr::Fr, Bn254, Fq12, G1Affine, G1Projective as G1, G2Affine,
G2Projective as G2,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{biginteger::BigInteger256 as Repr, BigInteger, Field, PrimeField, UniformRand};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(Fq, Fq, Repr, Repr, fq);
f_bench!(Fr, Fr, Repr, Repr, fr);
f_bench!(extension, Fq2, Fq2, fq2);
f_bench!(target, Fq12, Fq12, fq12);
pairing_bench!(Bn254, Fq12);
bencher::benchmark_main!(fq, fr, fq2, fq12, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,29 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_bw6_761::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
BW6_761,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{
biginteger::{BigInteger384 as FrRepr, BigInteger768 as FqRepr},
BigInteger, Field, PrimeField, UniformRand,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq3, Fq3, fq3);
f_bench!(target, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(BW6_761, Fq6);
bencher::benchmark_main!(fq, fr, fq3, fq6, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,29 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_cp6_782::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
CP6_782,
};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{
biginteger::{BigInteger384 as FrRepr, BigInteger832 as FqRepr},
BigInteger, Field, PrimeField, UniformRand,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq3, Fq3, fq3);
f_bench!(target, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FrRepr, FrRepr, fr);
pairing_bench!(CP6_782, Fq6);
bencher::benchmark_main!(fq, fr, fq3, fq6, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,16 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::ProjectiveCurve;
use ark_ed_on_bls12_381::{fq::Fq, fr::Fr, EdwardsAffine as GAffine, EdwardsProjective as G};
use ark_ff::{biginteger::BigInteger256 as Repr, BigInteger, Field, PrimeField, UniformRand};
mod g {
use super::*;
ec_bench!(G, GAffine);
}
f_bench!(Fq, Fq, Repr, Repr, fq);
f_bench!(Fr, Fr, Repr, Repr, fr);
bencher::benchmark_main!(fq, fr, g::group_ops);

View File

@@ -1,26 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{biginteger::BigInteger320 as FqRepr, BigInteger, Field, PrimeField, UniformRand};
use ark_mnt4_298::{
fq::Fq, fq2::Fq2, fr::Fr, Fq4, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
MNT4_298,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq2, Fq2, fq2);
f_bench!(target, Fq4, Fq4, fq4);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FqRepr, FqRepr, fr);
pairing_bench!(MNT4_298, Fq4);
bencher::benchmark_main!(fq, fr, fq2, fq4, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,26 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{biginteger::BigInteger768 as FqRepr, BigInteger, Field, PrimeField, UniformRand};
use ark_mnt4_753::{
fq::Fq, fq2::Fq2, fr::Fr, Fq4, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
MNT4_753,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq2, Fq2, fq2);
f_bench!(target, Fq4, Fq4, fq4);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FqRepr, FqRepr, fr);
pairing_bench!(MNT4_753, Fq4);
bencher::benchmark_main!(fq, fr, fq2, fq4, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,26 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{biginteger::BigInteger320 as FqRepr, BigInteger, Field, PrimeField, UniformRand};
use ark_mnt6_298::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
MNT6_298,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq3, Fq3, fq3);
f_bench!(target, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FqRepr, FqRepr, fr);
pairing_bench!(MNT6_298, Fq6);
bencher::benchmark_main!(fq, fr, fq3, fq6, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,26 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::{PairingEngine, ProjectiveCurve};
use ark_ff::{biginteger::BigInteger768 as FqRepr, BigInteger, Field, PrimeField, UniformRand};
use ark_mnt6_753::{
fq::Fq, fq3::Fq3, fr::Fr, Fq6, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2,
MNT6_753,
};
mod g1 {
use super::*;
ec_bench!(G1, G1Affine);
}
mod g2 {
use super::*;
ec_bench!(G2, G2Affine);
}
f_bench!(extension, Fq3, Fq3, fq3);
f_bench!(target, Fq6, Fq6, fq6);
f_bench!(Fq, Fq, FqRepr, FqRepr, fq);
f_bench!(Fr, Fr, FqRepr, FqRepr, fr);
pairing_bench!(MNT6_753, Fq6);
bencher::benchmark_main!(fq, fr, fq3, fq6, g1::group_ops, g2::group_ops, pairing);

View File

@@ -1,16 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::ProjectiveCurve;
use ark_ff::{biginteger::BigInteger256 as Repr, BigInteger, Field, PrimeField, UniformRand};
use ark_pallas::{fq::Fq, fr::Fr, Affine as GAffine, Projective as G};
mod g {
use super::*;
ec_bench!(G, GAffine);
}
f_bench!(Fq, Fq, Repr, Repr, fq);
f_bench!(Fr, Fr, Repr, Repr, fr);
bencher::benchmark_main!(fq, fr, g::group_ops);

View File

@@ -1,16 +0,0 @@
use ark_curve_benches::*;
use ark_std::ops::{AddAssign, MulAssign, SubAssign};
use ark_ec::ProjectiveCurve;
use ark_ff::{biginteger::BigInteger256 as Repr, BigInteger, Field, PrimeField, UniformRand};
use ark_vesta::{fq::Fq, fr::Fr, Affine as GAffine, Projective as G};
mod g {
use super::*;
ec_bench!(G, GAffine);
}
f_bench!(Fq, Fq, Repr, Repr, fq);
f_bench!(Fr, Fr, Repr, Repr, fr);
bencher::benchmark_main!(fq, fr, g::group_ops);

View File

@@ -1,9 +0,0 @@
extern crate rustc_version;
use rustc_version::{version_meta, Channel};
fn main() {
if version_meta().expect("nightly check failed").channel == Channel::Nightly {
println!("cargo:rustc-cfg=nightly");
}
}

View File

@@ -1,8 +0,0 @@
#![allow(unused_macros, unused_imports)]
#[macro_use]
pub mod macros;
pub use macros::*;
#[macro_use]
pub extern crate bencher;
pub use bencher::*;

View File

@@ -1,258 +0,0 @@
#[macro_export]
macro_rules! ec_bench {
($projective:ty, $affine:ty) => {
fn rand(b: &mut $crate::bencher::Bencher) {
let mut rng = ark_std::test_rng();
b.iter(|| <$projective>::rand(&mut rng));
}
fn mul_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<($projective, Fr)> = (0..SAMPLES)
.map(|_| (<$projective>::rand(&mut rng), Fr::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
tmp *= v[count].1;
count = (count + 1) % SAMPLES;
tmp
});
}
fn add_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<($projective, $projective)> = (0..SAMPLES)
.map(|_| (<$projective>::rand(&mut rng), <$projective>::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn sub_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<($projective, $projective)> = (0..SAMPLES)
.map(|_| (<$projective>::rand(&mut rng), <$projective>::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, sub_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn double(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$projective> = (0..SAMPLES)
.map(|_| <$projective>::rand(&mut rng))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, double_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
fn add_assign_mixed(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<($projective, $affine)> = (0..SAMPLES)
.map(|_| {
(
<$projective>::rand(&mut rng),
<$projective>::rand(&mut rng).into(),
)
})
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign_mixed, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn deser(b: &mut $crate::bencher::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let tmp = <$projective>::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$affine>::deserialize(&v[index..(index + num_bytes)]).unwrap()
});
}
fn ser(b: &mut $crate::bencher::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut v: Vec<_> = (0..SAMPLES)
.map(|_| <$projective>::rand(&mut rng))
.collect();
let v = <$projective>::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize(&mut bytes)
});
}
fn deser_unchecked(b: &mut $crate::bencher::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let tmp = <$projective>::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize_unchecked(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$affine>::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
});
}
fn ser_unchecked(b: &mut $crate::bencher::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut v: Vec<_> = (0..SAMPLES)
.map(|_| <$projective>::rand(&mut rng))
.collect();
let v = <$projective>::batch_normalization_into_affine(v.as_mut_slice());
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize_unchecked(&mut bytes)
});
}
fn deser_uncompressed(b: &mut $crate::bencher::Bencher) {
use ark_ec::ProjectiveCurve;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let tmp = <$projective>::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
tmp.serialize_uncompressed(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$affine>::deserialize_uncompressed(&v[index..(index + num_bytes)]).unwrap()
});
}
fn msm_131072(b: &mut $crate::bencher::Bencher) {
use ark_ec::msm::VariableBaseMSM;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 131072;
let mut rng = ark_std::test_rng();
let g = <$projective>::rand(&mut rng).into_affine();
let v: Vec<_> = (0..SAMPLES).map(|_| g).collect();
let scalars: Vec<_> = (0..SAMPLES)
.map(|_| Fr::rand(&mut rng).into_bigint())
.collect();
b.bench_n(1, |b| {
b.iter(|| <$projective as VariableBaseMSM>::msm_bigint(&v, &scalars));
})
}
$crate::benchmark_group!(
group_ops,
rand,
mul_assign,
add_assign,
sub_assign,
add_assign_mixed,
double,
ser,
deser,
ser_unchecked,
deser_unchecked,
deser_uncompressed,
msm_131072,
);
};
}

View File

@@ -1,455 +0,0 @@
#[macro_export]
macro_rules! f_bench {
// Use this for base fields
($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty, $modname:ident) => {
pub mod $modname {
use super::*;
field_common!($f, $f_type);
sqrt!($f, $f_type);
prime_field!($f, $f_type, $f_repr, $f_repr_type);
$crate::benchmark_group!(
$modname,
// common stuff
add_assign,
sub_assign,
double,
negate,
mul_assign,
square,
inverse,
ser,
deser,
ser_unchecked,
deser_unchecked,
// sqrt field stuff
sqrt,
// prime field stuff
repr_add_nocarry,
repr_sub_noborrow,
repr_num_bits,
repr_mul2,
repr_div2,
into_repr,
from_repr,
);
}
use $modname::$modname;
};
// use this for intermediate fields
(extension, $f:ident, $f_type:ty, $modname:ident) => {
mod $modname {
use super::*;
field_common!($f, $f_type);
sqrt!($f, $f_type);
$crate::benchmark_group!(
$modname,
// common stuff
add_assign,
sub_assign,
double,
negate,
mul_assign,
square,
inverse,
ser,
deser,
ser_unchecked,
deser_unchecked,
// sqrt field stuff
sqrt,
);
}
use $modname::$modname;
};
// Use this for the full extension field Fqk
(target, $f:ident, $f_type:ty, $modname:ident) => {
mod $modname {
use super::*;
field_common!($f, $f_type);
$crate::benchmark_group!(
$modname,
// common stuff
add_assign,
sub_assign,
double,
negate,
mul_assign,
square,
inverse,
ser,
deser,
ser_unchecked,
deser_unchecked,
);
}
use $modname::$modname;
};
}
#[macro_export]
macro_rules! field_common {
($f:ident, $f_type:ty) => {
fn add_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn sub_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, sub_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn double(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, double_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
fn negate(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
tmp = -tmp;
count = (count + 1) % SAMPLES;
tmp
});
}
fn mul_assign(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, mul_assign, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn square(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, square_in_place);
count = (count + 1) % SAMPLES;
tmp
});
}
fn inverse(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let tmp = v[count].inverse();
count = (count + 1) % SAMPLES;
tmp
});
}
fn deser(b: &mut $crate::bencher::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
let tmp = $f::rand(&mut rng);
tmp.serialize(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$f_type>::deserialize(&v[index..(index + num_bytes)]).unwrap()
});
}
fn ser(b: &mut $crate::bencher::Bencher) {
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize(&mut bytes)
});
}
fn deser_unchecked(b: &mut $crate::bencher::Bencher) {
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut num_bytes = 0;
let v: Vec<_> = (0..SAMPLES)
.flat_map(|_| {
let mut bytes = Vec::with_capacity(1000);
let tmp = $f::rand(&mut rng);
tmp.serialize_unchecked(&mut bytes).unwrap();
num_bytes = bytes.len();
bytes
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let index = count * num_bytes;
<$f_type>::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
});
}
fn ser_unchecked(b: &mut $crate::bencher::Bencher) {
use ark_serialize::CanonicalSerialize;
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut bytes = Vec::with_capacity(1000);
let mut count = 0;
b.iter(|| {
let tmp = v[count];
count = (count + 1) % SAMPLES;
bytes.clear();
tmp.serialize_unchecked(&mut bytes)
});
}
};
}
#[macro_export]
macro_rules! sqrt {
($f:ident, $f_type:ty) => {
pub fn sqrt(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES)
.map(|_| {
let mut tmp = $f::rand(&mut rng);
tmp.square_in_place();
tmp
})
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
v[count].sqrt()
});
}
};
}
#[macro_export]
macro_rules! prime_field {
($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty) => {
fn repr_add_nocarry(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| {
let mut tmp1 = $f_repr::rand(&mut rng);
let mut tmp2 = $f_repr::rand(&mut rng);
// Shave a few bits off to avoid overflow.
for _ in 0..3 {
tmp1.div2();
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, add_with_carry, count);
count = (count + 1) % SAMPLES;
tmp
});
}
fn repr_sub_noborrow(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| {
let tmp1 = $f_repr::rand(&mut rng);
let mut tmp2 = tmp1;
// Ensure tmp2 is smaller than tmp1.
for _ in 0..10 {
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count].0;
n_fold!(tmp, v, sub_with_borrow, count);
count = (count + 1) % SAMPLES;
tmp;
});
}
fn repr_num_bits(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let tmp = v[count].num_bits();
count = (count + 1) % SAMPLES;
tmp;
});
}
fn repr_mul2(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, mul2);
count = (count + 1) % SAMPLES;
tmp;
});
}
fn repr_div2(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
let mut tmp = v[count];
n_fold!(tmp, div2);
count = (count + 1) % SAMPLES;
tmp;
});
}
fn into_repr(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
v[count].into_bigint();
});
}
fn from_repr(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<$f_repr_type> = (0..SAMPLES)
.map(|_| $f::rand(&mut rng).into_bigint())
.collect();
let mut count = 0;
b.iter(|| {
count = (count + 1) % SAMPLES;
let _ = $f::from(v[count]);
});
}
};
}

View File

@@ -1,11 +0,0 @@
#[macro_use]
mod utils;
#[macro_use]
mod ec;
#[macro_use]
mod field;
#[macro_use]
mod pairing;

View File

@@ -1,72 +0,0 @@
#[macro_export]
macro_rules! pairing_bench {
($curve:ident, $pairing_field:ident) => {
fn miller_loop(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let g1s = (0..SAMPLES).map(|_| G1::rand(&mut rng)).collect::<Vec<_>>();
let g2s = (0..SAMPLES).map(|_| G2::rand(&mut rng)).collect::<Vec<_>>();
let g1s = G1::batch_normalization_into_affine(&g1s);
let g2s = G2::batch_normalization_into_affine(&g2s);
let prepared = g1s
.into_iter()
.zip(g2s)
.map(|(g1, g2)| (g1.into(), g2.into()))
.collect::<Vec<(
<$curve as PairingEngine>::G1Prepared,
<$curve as PairingEngine>::G2Prepared,
)>>();
let mut count = 0;
b.iter(|| {
let tmp =
$curve::miller_loop(&[(prepared[count].0.clone(), prepared[count].1.clone())]);
count = (count + 1) % SAMPLES;
tmp
});
}
fn final_exponentiation(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<_> = (0..SAMPLES)
.map(|_| {
(
G1Affine::from(G1::rand(&mut rng)).into(),
G2Affine::from(G2::rand(&mut rng)).into(),
)
})
.map(|(p, q)| $curve::miller_loop(&[(p, q)]))
.collect();
let mut count = 0;
b.iter(|| {
let tmp = $curve::final_exponentiation(&v[count]);
count = (count + 1) % SAMPLES;
tmp
});
}
fn full_pairing(b: &mut $crate::bencher::Bencher) {
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let v: Vec<(G1, G2)> = (0..SAMPLES)
.map(|_| (G1::rand(&mut rng), G2::rand(&mut rng)))
.collect();
let mut count = 0;
b.iter(|| {
let tmp = $curve::pairing(v[count].0, v[count].1);
count = (count + 1) % SAMPLES;
tmp
});
}
$crate::benchmark_group!(pairing, miller_loop, final_exponentiation, full_pairing,);
};
}

View File

@@ -1,36 +0,0 @@
#[macro_export]
macro_rules! n_fold {
($tmp:ident, $v:ident, $func:ident, $count:ident) => {
$tmp.$func(&$v[$count].1);
};
($tmp:ident, $func:ident) => {
$tmp.$func();
};
}
/// Defines a function called `$group_name` that returns the test description
/// values for the listed functions `$function`.
#[macro_export]
macro_rules! benchmark_group {
($group_name:ident, $($function:path),+) => {
pub fn $group_name() -> ::std::vec::Vec<$crate::TestDescAndFn> {
use $crate::{TestDescAndFn, TestFn, TestDesc};
use std::borrow::Cow;
let mut benches = ::std::vec::Vec::new();
$(
benches.push(TestDescAndFn {
desc: TestDesc {
name: Cow::from(module_path!().to_string() + "::" + stringify!($function)),
ignore: false,
},
testfn: TestFn::StaticBenchFn($function),
});
)+
benches
}
};
($group_name:ident, $($function:path,)+) => {
benchmark_group!($group_name, $($function),+);
};
}

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ark-curve-constraint-tests" name = "ark-curve-constraint-tests"
version = "0.3.0" version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ] authors = [ "arkworks contributors" ]
description = "A library for testing constraints for finite fields, elliptic curves, and pairings" description = "A library for testing constraints for finite fields, elliptic curves, and pairings"
homepage = "https://arkworks.rs" homepage = "https://arkworks.rs"
@@ -10,15 +10,15 @@ keywords = ["cryptography", "finite-fields", "elliptic-curves", "r1cs" ]
categories = ["cryptography"] categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018" edition = "2021"
[dependencies] [dependencies]
ark-std = { version = "^0.3.0", default-features = false } ark-std = { version = "0.4.0-alpha", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false } ark-serialize = { version = "0.4.0-alpha", default-features = false }
ark-ff = { version = "^0.3.0", default-features = false } ark-ff = { version = "0.4.0-alpha", default-features = false }
ark-relations = { version = "^0.3.0", default-features = false } ark-relations = { version = "0.4.0-alpha", default-features = false }
ark-r1cs-std = { version = "^0.3.0", default-features = false } ark-r1cs-std = { version = "0.4.0-alpha", default-features = false }
ark-ec = { version = "^0.3.0", default-features = false } ark-ec = { version = "0.4.0-alpha", default-features = false }
[features] [features]
default = [] default = []

View File

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

View File

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

81
curve-constraint-tests/src/lib.rs Executable file → Normal file
View File

@@ -211,7 +211,7 @@ pub mod fields {
let mut a = F::rand(&mut rng); let mut a = F::rand(&mut rng);
let mut a_gadget = AF::new_variable(ark_relations::ns!(cs, "a"), || Ok(a), mode)?; let mut a_gadget = AF::new_variable(ark_relations::ns!(cs, "a"), || Ok(a), mode)?;
a_gadget.frobenius_map_in_place(i)?; a_gadget.frobenius_map_in_place(i)?;
a.frobenius_map(i); a.frobenius_map_in_place(i);
assert_eq!(a_gadget.value()?, a); assert_eq!(a_gadget.value()?, a);
} }
@@ -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,
ProjectiveCurve, CurveGroup, Group,
}; };
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};
@@ -235,7 +235,7 @@ pub mod curves {
pub fn group_test<C, ConstraintF, GG>() -> Result<(), SynthesisError> pub fn group_test<C, ConstraintF, GG>() -> Result<(), SynthesisError>
where where
C: ProjectiveCurve, C: CurveGroup,
ConstraintF: Field, ConstraintF: Field,
GG: CurveVar<C, ConstraintF>, GG: CurveVar<C, ConstraintF>,
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
@@ -321,8 +321,10 @@ pub mod curves {
*limb = u64::MAX; *limb = u64::MAX;
} }
let modulus_last_limb_bits = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64; let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
*max.last_mut().unwrap() >>= 64 - modulus_last_limb_bits; if modulus_num_bits_mod_64 != 0 {
*max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
}
let scalars = [ let scalars = [
C::ScalarField::rand(&mut rng) C::ScalarField::rand(&mut rng)
.into_bigint() .into_bigint()
@@ -340,7 +342,7 @@ pub mod curves {
// Check scalar mul with edge cases // Check scalar mul with edge cases
for scalar in scalars.iter() { for scalar in scalars.iter() {
let native_result = a_native.mul(scalar); let native_result = a_native.mul_bigint(scalar);
let native_result = native_result.into_affine(); let native_result = native_result.into_affine();
let scalar_bits: Vec<bool> = BitIteratorLE::new(&scalar).collect(); let scalar_bits: Vec<bool> = BitIteratorLE::new(&scalar).collect();
@@ -512,18 +514,21 @@ pub mod curves {
} }
pub mod pairing { pub mod pairing {
use ark_ec::{PairingEngine, ProjectiveCurve}; use ark_ec::{
pairing::{Pairing, PairingOutput},
AffineRepr, CurveGroup,
};
use ark_ff::{BitIteratorLE, Field, PrimeField}; use ark_ff::{BitIteratorLE, Field, PrimeField};
use ark_r1cs_std::prelude::*; use ark_r1cs_std::prelude::*;
use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
use ark_std::{test_rng, vec::Vec, UniformRand}; use ark_std::{test_rng, vec::Vec, UniformRand};
#[allow(dead_code)] #[allow(dead_code)]
pub fn bilinearity_test<E: PairingEngine, P: PairingVar<E>>() -> Result<(), SynthesisError> pub fn bilinearity_test<E: Pairing, P: PairingVar<E>>() -> Result<(), SynthesisError>
where where
for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1Projective, P::G1Var>, for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1, P::G1Var>,
for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>, for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2, P::G2Var>,
for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>, for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::TargetField, P::GTVar>,
{ {
let modes = [ let modes = [
AllocationMode::Input, AllocationMode::Input,
@@ -531,12 +536,12 @@ pub mod pairing {
AllocationMode::Constant, AllocationMode::Constant,
]; ];
for &mode in &modes { for &mode in &modes {
let cs = ConstraintSystem::<E::Fq>::new_ref(); let cs = ConstraintSystem::<<E::G1 as CurveGroup>::BaseField>::new_ref();
let mut rng = test_rng(); let mut rng = test_rng();
let a = E::G1Projective::rand(&mut rng); let a = E::G1::rand(&mut rng);
let b = E::G2Projective::rand(&mut rng); let b = E::G2::rand(&mut rng);
let s = E::Fr::rand(&mut rng); let s = E::ScalarField::rand(&mut rng);
let mut sa = a; let mut sa = a;
sa *= s; sa *= s;
@@ -578,7 +583,7 @@ pub mod pairing {
let mut ans_g = P::pairing(a_prep_g, b_prep_g)?; let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
let mut ans_n = E::pairing(a, b); let mut ans_n = E::pairing(a, b);
ans_n = ans_n.pow(s.into_bigint()); ans_n = PairingOutput(ans_n.0.pow(s.into_bigint()));
ans_g = ans_g.pow_le(&s_iter)?; ans_g = ans_g.pow_le(&s_iter)?;
(ans_g, ans_n) (ans_g, ans_n)
@@ -587,12 +592,12 @@ pub mod pairing {
ans1_g.enforce_equal(&ans2_g)?; ans1_g.enforce_equal(&ans2_g)?;
ans2_g.enforce_equal(&ans3_g)?; ans2_g.enforce_equal(&ans3_g)?;
assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1"); assert_eq!(ans1_g.value()?, ans1_n.0, "Failed native test 1");
assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2"); assert_eq!(ans2_g.value()?, ans2_n.0, "Failed native test 2");
assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3"); assert_eq!(ans3_g.value()?, ans3_n.0, "Failed native test 3");
assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native"); assert_eq!(ans1_n.0, ans2_n.0, "Failed ans1_native == ans2_native");
assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native"); assert_eq!(ans2_n.0, ans3_n.0, "Failed ans2_native == ans3_native");
assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3"); assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3");
assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2"); assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2");
assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3"); assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3");
@@ -609,4 +614,38 @@ pub mod pairing {
} }
Ok(()) Ok(())
} }
#[allow(dead_code)]
pub fn g2_prepare_consistency_test<E: Pairing, P: PairingVar<E>>() -> Result<(), SynthesisError>
{
let test_g2_elem = E::G2Affine::generator();
let test_g2_prepared = E::G2Prepared::from(test_g2_elem.clone());
let modes = [
AllocationMode::Input,
AllocationMode::Witness,
AllocationMode::Constant,
];
for &mode in &modes {
let cs = ConstraintSystem::new_ref();
let test_g2_gadget =
P::G2Var::new_witness(cs.clone(), || Ok(test_g2_elem.clone())).unwrap();
let prepared_test_g2_gadget = P::prepare_g2(&test_g2_gadget).unwrap();
let allocated_test_g2_gadget =
P::G2PreparedVar::new_variable(cs.clone(), || Ok(test_g2_prepared.clone()), mode)
.unwrap();
let prepared_test_g2_gadget_bytes = prepared_test_g2_gadget.to_bytes().unwrap();
let allocated_test_g2_gadget_bytes = allocated_test_g2_gadget.to_bytes().unwrap();
prepared_test_g2_gadget_bytes
.enforce_equal(&allocated_test_g2_gadget_bytes)
.unwrap();
assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
}
Ok(())
}
} }

30
curve25519/Cargo.toml Normal file
View File

@@ -0,0 +1,30 @@
[package]
name = "ark-curve25519"
version = "0.4.0-alpha.2"
authors = [ "arkworks contributors" ]
description = "The curve25519 Montgomery curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-curve25519/"
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-alpha", default-features = false }
ark-ec = { version = "0.4.0-alpha", default-features = false }
ark-std = { version = "0.4.0-alpha", default-features = false }
ark-r1cs-std = { version = "0.4.0-alpha", default-features = false, optional = true }
[dev-dependencies]
ark-relations = { version = "0.4.0-alpha", default-features = false }
ark-serialize = { version = "0.4.0-alpha", default-features = false }
ark-algebra-test-templates = { version = "0.4.0-alpha", 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" ]

1
curve25519/LICENSE-APACHE Symbolic link
View File

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

1
curve25519/LICENSE-MIT Symbolic link
View File

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

View File

@@ -0,0 +1,91 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "04264893",
"metadata": {},
"outputs": [],
"source": [
"r = 7237005577332262213973186563042994240857116359379907606001950938285454250989"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1603b293",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2^2 * 3 * 11 * 198211423230930754013084525763697 * 276602624281642239937218680557139826668747"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"factor(r - 1)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "425ceac7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7237005577332262213973186563042994240857116359379907606001950938285454250988\n",
"1570463851528226261927580272323658009530148727742783848239914322803198255651\n",
"4908983020090465803374304318106080751443647916949975825112097080460587568629\n",
"7119675135705137915307919240607293966034195415655343409829245710729128040338\n",
"2975531125133123119648879457563281269120703404158613135195788908093573672641\n"
]
}
],
"source": [
"gen = 2\n",
"print(pow(gen, (r - 1) / 2, r))\n",
"print(pow(gen, (r - 1) / 3, r))\n",
"print(pow(gen, (r - 1) / 11, r))\n",
"print(pow(gen, (r - 1) / 198211423230930754013084525763697, r))\n",
"print(pow(gen, (r - 1) / 276602624281642239937218680557139826668747, r))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4c58ca4",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.2",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

162
curve25519/scripts/g1.ipynb Normal file
View File

@@ -0,0 +1,162 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "f890e69f",
"metadata": {},
"outputs": [],
"source": [
"q = pow(2,255) - 19"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d90a7f0b",
"metadata": {},
"outputs": [],
"source": [
"A = 486662\n",
"B = 1"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1b2aebc5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"486664\n",
"486660\n"
]
}
],
"source": [
"a = (A + 2) * 1\n",
"d = (A - 2) * 1\n",
"print(a)\n",
"print(d)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "aae2f8bf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"9"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u = 9\n",
"u"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ea9a4d90",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"14781619447589544791020593568409986887264606134616475288964881837755586237401"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v = mod(u^3 + A * u^2 + u, q).sqrt()\n",
"v"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "95895004",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"38213832894368730265794714087330135568483813637251082400757400312561599933396"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u * pow(v, -1, q) % q"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "1134cf74",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"46316835694926478169428394003475163141307993866256225615783033603165251855960"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(u - 1) * pow(u + 1, -1, q) % q"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec089e21",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.2",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,14 @@
use ark_r1cs_std::groups::curves::twisted_edwards::{AffineVar, MontgomeryAffineVar};
use crate::{constraints::FqVar, *};
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<Curve25519Config, FqVar>;
/// A variable that is the R1CS equivalent of `crate::NonZeroMontgomeryAffine`.
pub type NonZeroMontgomeryVar = MontgomeryAffineVar<Curve25519Config, FqVar>;
#[test]
fn test() {
ark_curve_constraint_tests::curves::te_test::<Curve25519Config, EdwardsVar>().unwrap();
}

View File

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

View File

@@ -0,0 +1,8 @@
//! This module implements the R1CS equivalent of `ark_curve25519`.
//! It requires a curve that embeds curve25519.
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

View File

@@ -0,0 +1,71 @@
use crate::{Fq, Fr};
use ark_ec::{
models::CurveConfig,
twisted_edwards::{Affine, MontCurveConfig, MontgomeryAffine, Projective, TECurveConfig},
};
use ark_ff::MontFp;
#[cfg(test)]
mod tests;
pub type EdwardsAffine = Affine<Curve25519Config>;
pub type EdwardsProjective = Projective<Curve25519Config>;
pub type NonZeroMontgomeryAffine = MontgomeryAffine<Curve25519Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Curve25519Config;
impl CurveConfig for Curve25519Config {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR = 8
const COFACTOR: &'static [u64] = &[8];
/// COFACTOR_INV (mod r) =
/// 2713877091499598330239944961141122840321418634767465352250731601857045344121
const COFACTOR_INV: Fr =
MontFp!("2713877091499598330239944961141122840321418634767465352250731601857045344121");
}
// We want to emphasize that this twisted Edwards curve is not ed25519.
// Ed25519 has COEFF_A = -1 and COEFF_D = -121665 / 121666.
impl TECurveConfig for Curve25519Config {
/// COEFF_A = 486664
const COEFF_A: Fq = MontFp!("486664");
/// COEFF_D = 486660
const COEFF_D: Fq = MontFp!("486660");
/// Standard generators from <https://neuromancer.sk/std/other/Curve25519>.
/// The Montgomery form is
/// x = 0x09,
/// y = 0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9
/// The twisted Edwards form is
/// x = 0x547c4350219f5e19dd26a3d6668b74346a8eb726eb2396e1228cfa397ffe6bd4
/// y = 0x6666666666666666666666666666666666666666666666666666666666666658
const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y);
type MontCurveConfig = Curve25519Config;
}
impl MontCurveConfig for Curve25519Config {
/// COEFF_A = 486662
const COEFF_A: Fq = MontFp!("486662");
/// COEFF_B = 1
const COEFF_B: Fq = MontFp!("1");
type TECurveConfig = Curve25519Config;
}
/// GENERATOR_X =
/// 38213832894368730265794714087330135568483813637251082400757400312561599933396
const GENERATOR_X: Fq =
MontFp!("38213832894368730265794714087330135568483813637251082400757400312561599933396");
/// GENERATOR_Y =
/// (4/5)
/// 46316835694926478169428394003475163141307993866256225615783033603165251855960
const GENERATOR_Y: Fq =
MontFp!("46316835694926478169428394003475163141307993866256225615783033603165251855960");

View File

@@ -0,0 +1,4 @@
use crate::*;
use ark_algebra_test_templates::*;
test_group!(te; EdwardsProjective; te);

View File

@@ -0,0 +1,9 @@
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
#[derive(MontConfig)]
#[modulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"]
#[generator = "2"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "1"]
pub struct FqConfig;
pub type Fq = Fp256<MontBackend<FqConfig, 4>>;

View File

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

View File

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

View File

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

28
curve25519/src/lib.rs Executable file
View File

@@ -0,0 +1,28 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the curve25519 Montgomery curve.
//!
//! Curve information:
//! * Base field: q =
//! 57896044618658097711785492504343953926634992332820282019728792003956564819949
//! * Scalar field: r =
//! 7237005577332262213973186563042994240857116359379907606001950938285454250989
//! * Curve equation: B * y^2 = x^3 + A * x^2 + x, where
//! * A = 486662
//! * B = 1
#[cfg(feature = "r1cs")]
pub mod constraints;
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

Some files were not shown because too many files have changed in this diff Show More