├── models ├── .gitignore ├── src │ ├── models │ │ ├── mod.rs │ │ ├── bw6 │ │ │ ├── g1.rs │ │ │ ├── g2.rs │ │ │ └── mod.rs │ │ └── bls12 │ │ │ ├── g1.rs │ │ │ ├── g2.rs │ │ │ └── mod.rs │ └── lib.rs └── Cargo.toml ├── curves ├── .gitignore ├── bls12_381 │ ├── src │ │ ├── curves │ │ │ ├── tests │ │ │ │ ├── g1_compressed_valid_test_vectors.bin │ │ │ │ ├── g2_compressed_valid_test_vectors.bin │ │ │ │ ├── g1_uncompressed_valid_test_vectors.bin │ │ │ │ ├── g2_uncompressed_valid_test_vectors.bin │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ ├── g1.rs │ │ │ ├── util.rs │ │ │ └── g2.rs │ │ └── lib.rs │ └── Cargo.toml ├── secp256k1 │ ├── src │ │ ├── lib.rs │ │ └── curves │ │ │ ├── tests.rs │ │ │ └── mod.rs │ └── Cargo.toml ├── vesta │ ├── src │ │ ├── curves │ │ │ ├── tests.rs │ │ │ └── mod.rs │ │ └── lib.rs │ └── Cargo.toml ├── pallas │ ├── src │ │ ├── curves │ │ │ ├── tests.rs │ │ │ └── mod.rs │ │ └── lib.rs │ └── Cargo.toml ├── ed_on_bls12_377 │ ├── src │ │ ├── curves │ │ │ ├── tests.rs │ │ │ └── mod.rs │ │ └── lib.rs │ └── Cargo.toml ├── bw6_761 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── curves │ │ ├── g2.rs │ │ ├── tests.rs │ │ ├── g1.rs │ │ └── mod.rs ├── bls12_377 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── curves │ │ ├── tests.rs │ │ ├── g2.rs │ │ ├── mod.rs │ │ └── g1.rs └── ed_on_bls12_381_bandersnatch │ ├── Cargo.toml │ └── src │ ├── curves │ ├── tests.rs │ └── mod.rs │ └── lib.rs ├── .gitignore ├── test-utils ├── Cargo.toml └── src │ └── lib.rs ├── scripts └── publish.sh ├── .github ├── CODEOWNERS └── workflows │ └── check.yml ├── LICENSE-MIT ├── Cargo.toml ├── README.md ├── LICENSE-APACHE └── Cargo.lock /models/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /curves/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | target/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | models/target/* 2 | target 3 | target/* 4 | -------------------------------------------------------------------------------- /models/src/models/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bls12; 2 | pub mod bw6; 3 | pub use ark_ec::{pairing, short_weierstrass, twisted_edwards, CurveConfig}; 4 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/tests/g1_compressed_valid_test_vectors.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paritytech/arkworks-extensions/HEAD/curves/bls12_381/src/curves/tests/g1_compressed_valid_test_vectors.bin -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/tests/g2_compressed_valid_test_vectors.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paritytech/arkworks-extensions/HEAD/curves/bls12_381/src/curves/tests/g2_compressed_valid_test_vectors.bin -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/tests/g1_uncompressed_valid_test_vectors.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paritytech/arkworks-extensions/HEAD/curves/bls12_381/src/curves/tests/g1_uncompressed_valid_test_vectors.bin -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/tests/g2_uncompressed_valid_test_vectors.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paritytech/arkworks-extensions/HEAD/curves/bls12_381/src/curves/tests/g2_uncompressed_valid_test_vectors.bin -------------------------------------------------------------------------------- /test-utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-utils" 3 | description = "Testing support crate" 4 | version.workspace = true 5 | edition.workspace = true 6 | publish = false 7 | 8 | [dependencies] 9 | ark-ec.workspace = true 10 | ark-std.workspace = true 11 | ark-serialize.workspace = true 12 | 13 | [features] 14 | default = [ "std" ] 15 | std = [ "ark-ec/std", "ark-std/std" ] 16 | -------------------------------------------------------------------------------- /models/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | // Temporary fix to make clippy happy with implementation of clone on copy types 3 | // provided by "derivative" crate. 4 | #![allow(clippy::non_canonical_clone_impl)] 5 | 6 | pub use ark_ec::{ 7 | scalar_mul, scalar_mul::*, twisted_edwards, twisted_edwards::*, AffineRepr, CurveGroup, 8 | PrimeGroup, VariableBaseMSM, 9 | }; 10 | pub mod models; 11 | pub use models::*; 12 | -------------------------------------------------------------------------------- /curves/secp256k1/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the secp256k1 curve. 2 | //! Source: 3 | //! 4 | //! Curve information: 5 | //! * Base field: q = 6 | //! 115792089237316195423570985008687907853269984665640564039457584007908834671663 7 | //! * Scalar field: r = 8 | //! 115792089237316195423570985008687907852837564279074904382605163141518161494337 9 | //! * Curve equation: y^2 = x^3 + 7 10 | 11 | #![cfg_attr(not(feature = "std"), no_std)] 12 | 13 | pub mod curves; 14 | 15 | pub use ark_secp256k1::{fq, fq::*, fr, fr::*}; 16 | pub use curves::*; 17 | -------------------------------------------------------------------------------- /models/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-models-ext" 3 | description = "Replacement models for BLS12 and BW6 of ark-ec" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ff.workspace = true 15 | ark-ec.workspace = true 16 | ark-std.workspace = true 17 | ark-serialize.workspace = true 18 | 19 | derivative.workspace = true 20 | 21 | [features] 22 | default = [ "std" ] 23 | std = [ "ark-ff/std", "ark-serialize/std", "ark-std/std" ] 24 | parallel = [ "ark-std/parallel", "std" ] 25 | -------------------------------------------------------------------------------- /scripts/publish.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | args="$@" 6 | for arg in $args; do 7 | if [[ "$arg" == "--dry-run" ]]; then 8 | DRY_RUN=1 9 | break 10 | fi 11 | done 12 | 13 | if [[ -z $DRY_RUN && -z "$CARGO_REGISTRY_TOKEN" ]]; then 14 | echo "\$CARGO_REGISTRY_TOKEN is empty, please add it to your env variables" 15 | exit 1 16 | fi 17 | 18 | function publish() { 19 | local crate=$1 20 | echo "Publishing $crate crate (args: $args)" 21 | cargo publish -p $crate $args 22 | } 23 | 24 | publish ark-models-ext 25 | publish ark-bls12-377-ext 26 | publish ark-ed-on-bls12-377-ext 27 | publish ark-bls12-381-ext 28 | publish ark-bw6-761-ext 29 | publish ark-ed-on-bls12-381-bandersnatch-ext 30 | publish ark-vesta-ext 31 | publish ark-pallas-ext 32 | publish ark-secp256k1-ext 33 | -------------------------------------------------------------------------------- /curves/vesta/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_models_ext::CurveConfig; 5 | use ark_vesta::VestaConfig as ArkConfig; 6 | 7 | pub struct TestHooks; 8 | 9 | type Config = crate::VestaConfig; 10 | type Affine = crate::Affine; 11 | type Projective = crate::Projective; 12 | 13 | impl CurveHooks for TestHooks { 14 | fn msm(bases: &[Affine], scalars: &[::ScalarField]) -> Projective { 15 | test_utils::msm_sw_generic::(bases, scalars) 16 | } 17 | 18 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 19 | test_utils::mul_projective_sw_generic::(base, scalar) 20 | } 21 | } 22 | 23 | test_group!(sw; Projective; sw); 24 | -------------------------------------------------------------------------------- /curves/pallas/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_models_ext::CurveConfig; 5 | use ark_pallas::PallasConfig as ArkConfig; 6 | 7 | pub struct TestHooks; 8 | 9 | type Config = crate::PallasConfig; 10 | type Affine = crate::Affine; 11 | type Projective = crate::Projective; 12 | 13 | impl CurveHooks for TestHooks { 14 | fn msm(bases: &[Affine], scalars: &[::ScalarField]) -> Projective { 15 | test_utils::msm_sw_generic::(bases, scalars) 16 | } 17 | 18 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 19 | test_utils::mul_projective_sw_generic::(base, scalar) 20 | } 21 | } 22 | 23 | test_group!(sw; Projective; sw); 24 | -------------------------------------------------------------------------------- /curves/secp256k1/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_models_ext::CurveConfig; 5 | use ark_secp256k1::Config as ArkConfig; 6 | 7 | pub struct TestHooks; 8 | 9 | type Config = crate::Secp256k1Config; 10 | type Affine = crate::Affine; 11 | type Projective = crate::Projective; 12 | 13 | impl CurveHooks for TestHooks { 14 | fn msm(bases: &[Affine], scalars: &[::ScalarField]) -> Projective { 15 | test_utils::msm_sw_generic::(bases, scalars) 16 | } 17 | 18 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 19 | test_utils::mul_projective_sw_generic::(base, scalar) 20 | } 21 | } 22 | 23 | test_group!(sw; Projective; sw); 24 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_377/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_ed_on_bls12_377::EdwardsConfig as ArkConfig; 5 | use ark_models_ext::CurveConfig; 6 | 7 | struct TestHooks; 8 | 9 | type Config = crate::EdwardsConfig; 10 | type Affine = crate::EdwardsAffine; 11 | type Projective = crate::EdwardsProjective; 12 | 13 | impl CurveHooks for TestHooks { 14 | fn msm(bases: &[Affine], scalars: &[::ScalarField]) -> Projective { 15 | test_utils::msm_te_generic::(bases, scalars) 16 | } 17 | 18 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 19 | test_utils::mul_projective_te_generic::(base, scalar) 20 | } 21 | } 22 | 23 | test_group!(te; Projective; te); 24 | -------------------------------------------------------------------------------- /curves/pallas/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the prime-order curve Pallas, generated by 2 | //! [Daira Hopwood](https://github.com/zcash/pasta). The main feature of this 3 | //! curve is that it forms a cycle with Vesta, i.e. its scalar field and base 4 | //! field respectively are the base field and scalar field of Vesta. 5 | //! 6 | //! 7 | //! Curve information: 8 | //! * Base field: q = 9 | //! 28948022309329048855892746252171976963363056481941560715954676764349967630337 10 | //! * Scalar field: r = 11 | //! 28948022309329048855892746252171976963363056481941647379679742748393362948097 12 | //! * Curve equation: y^2 = x^3 + 5 13 | //! * Valuation(q - 1, 2) = 32 14 | //! * Valuation(r - 1, 2) = 32 15 | 16 | #![cfg_attr(not(feature = "std"), no_std)] 17 | 18 | pub mod curves; 19 | 20 | pub use ark_pallas::{fq, fq::*, fr, fr::*}; 21 | pub use curves::*; 22 | -------------------------------------------------------------------------------- /curves/vesta/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the prime-order curve Vesta, generated by 2 | //! [Daira Hopwood](https://github.com/zcash/pasta). The main feature of this 3 | //! curve is that it forms a cycle with Pallas, i.e. its scalar field and base 4 | //! field respectively are the base field and scalar field of Pallas. 5 | //! 6 | //! 7 | //! Curve information: 8 | //! Vesta: 9 | //! * Base field: q = 10 | //! 28948022309329048855892746252171976963363056481941647379679742748393362948097 11 | //! * Scalar field: r = 12 | //! 28948022309329048855892746252171976963363056481941560715954676764349967630337 13 | //! * Curve equation: y^2 = x^3 + 5 14 | //! * Valuation(q - 1, 2) = 32 15 | //! * Valuation(r - 1, 2) = 32 16 | 17 | #![cfg_attr(not(feature = "std"), no_std)] 18 | 19 | pub mod curves; 20 | 21 | pub use ark_vesta::{fq, fq::*, fr, fr::*}; 22 | pub use curves::*; 23 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lists some code owners. 2 | # 3 | # A codeowner just oversees some part of the codebase. If an owned file is changed then the 4 | # corresponding codeowner receives a review request. An approval of the codeowner might be 5 | # required for merging a PR (depends on repository settings). 6 | # 7 | # For details about syntax, see: 8 | # https://help.github.com/en/articles/about-code-owners 9 | # But here are some important notes: 10 | # 11 | # - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core` 12 | # which can be everywhere. 13 | # - Multiple owners are supported. 14 | # - Either handle (e.g, @github_user or @github/team) or email can be used. Keep in mind, 15 | # that handles might work better because they are more recognizable on GitHub, 16 | # eyou can use them for mentioning unlike an email. 17 | # - The latest matching rule, if multiple, takes precedence. 18 | 19 | * @davxy 20 | -------------------------------------------------------------------------------- /curves/bw6_761/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-bw6-761-ext" 3 | description = "Extensions for the BW6-761 pairing-friendly elliptic curve" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | 14 | [dependencies] 15 | ark-ec.workspace = true 16 | ark-ff.workspace = true 17 | ark-std.workspace = true 18 | ark-bw6-761.workspace = true 19 | ark-models-ext.workspace = true 20 | 21 | [dev-dependencies] 22 | ark-serialize.workspace = true 23 | ark-algebra-test-templates.workspace = true 24 | test-utils.workspace = true 25 | 26 | [features] 27 | default = [ "std" ] 28 | std = [ 29 | "ark-bw6-761/std", 30 | "ark-ec/std", 31 | "ark-ff/std", 32 | "ark-models-ext/std", 33 | "ark-serialize/std", 34 | "ark-std/std", 35 | ] 36 | parallel = [ 37 | "ark-ec/parallel", 38 | "ark-ff/parallel", 39 | "ark-std/parallel" 40 | ] 41 | -------------------------------------------------------------------------------- /curves/bls12_381/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-bls12-381-ext" 3 | description = "Extensions for the BLS12-381 pairing-friendly elliptic curve" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-bls12-381.workspace = true 18 | ark-models-ext.workspace = true 19 | ark-serialize.workspace = true 20 | 21 | [dev-dependencies] 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-bls12-381/std", 29 | "ark-ec/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | -------------------------------------------------------------------------------- /curves/secp256k1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-secp256k1-ext" 3 | description = "Extensions for the SECP256k1 elliptic curve famously used in bitcoin" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-secp256k1.workspace = true 18 | ark-models-ext.workspace = true 19 | ark-serialize.workspace = true 20 | 21 | [dev-dependencies] 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-secp256k1/std", 29 | "ark-ec/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_377/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements a twisted Edwards curve whose base field is the 2 | //! scalar field of the curve BLS12-377. This allows defining cryptographic 3 | //! primitives that use elliptic curves over the scalar field of the latter 4 | //! curve. This curve was generated as part of the paper [\[BCGMMW20, “Zexe”\]](https://eprint.iacr.org/2018/962). 5 | //! 6 | //! Curve information: 7 | //! * Base field: q = 8444461749428370424248824938781546531375899335154063827935233455917409239041 8 | //! * Scalar field: r = 2111115437357092606062206234695386632838870926408408195193685246394721360383 9 | //! * Valuation(q - 1, 2) = 47 10 | //! * Valuation(r - 1, 2) = 1 11 | //! * Curve equation: ax^2 + y^2 =1 + dx^2y^2, where 12 | //! * a = -1 13 | //! * d = 3021 14 | 15 | #![cfg_attr(not(feature = "std"), no_std)] 16 | 17 | pub mod curves; 18 | 19 | pub use ark_ed_on_bls12_377::{fq, fq::*, fr, fr::*}; 20 | pub use curves::*; 21 | 22 | #[cfg(feature = "r1cs")] 23 | pub use ark_ed_on_bls12_377::constraints; 24 | -------------------------------------------------------------------------------- /curves/vesta/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-vesta-ext" 3 | description = "Extensions for the Vesta elliptic curve famously which forms the curve cycle with Pallas" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-vesta.workspace = true 18 | ark-models-ext.workspace = true 19 | ark-serialize.workspace = true 20 | 21 | [dev-dependencies] 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-vesta/std", 29 | "ark-ec/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | -------------------------------------------------------------------------------- /curves/pallas/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-pallas-ext" 3 | description = "Extensions for the Pallas elliptic curve famously which forms the curve cycle with Vesta" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-pallas.workspace = true 18 | ark-models-ext.workspace = true 19 | ark-serialize.workspace = true 20 | 21 | [dev-dependencies] 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-pallas/std", 29 | "ark-ec/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | -------------------------------------------------------------------------------- /curves/bls12_381/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the BLS12_381 curve generated by [Sean Bowe](https://electriccoin.co/blog/new-snark-curve/). 2 | //! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 3 | //! 12, defined over a 381-bit (prime) field. 4 | //! This curve was intended to replace the BN254 curve to provide a higher 5 | //! security level without incurring a large performance overhead. 6 | //! 7 | //! 8 | //! Curve information: 9 | //! * Base field: q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 10 | //! * Scalar field: r = 11 | //! 52435875175126190479447740508185965837690552500527637822603658699938581184513 12 | //! * valuation(q - 1, 2) = 1 13 | //! * valuation(r - 1, 2) = 32 14 | //! * G1 curve equation: y^2 = x^3 + 4 15 | //! * G2 curve equation: y^2 = x^3 + Fq2(4, 4) 16 | 17 | #![cfg_attr(not(feature = "std"), no_std)] 18 | 19 | mod curves; 20 | 21 | pub use ark_bls12_381::{fq, fq::*, fq12, fq12::*, fq2, fq2::*, fq6, fq6::*, fr, fr::*}; 22 | pub use curves::*; 23 | -------------------------------------------------------------------------------- /curves/bls12_377/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-bls12-377-ext" 3 | description = "Extensions for the BLS12-377 pairing-friendly elliptic curve" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ff.workspace = true 15 | ark-ec.workspace = true 16 | ark-std.workspace = true 17 | ark-bls12-377.workspace = true 18 | ark-models-ext.workspace = true 19 | 20 | [dev-dependencies] 21 | ark-serialize.workspace = true 22 | ark-algebra-test-templates.workspace = true 23 | ark-ff.workspace = true 24 | test-utils.workspace = true 25 | 26 | [features] 27 | default = [ "std" ] 28 | std = [ 29 | "ark-bls12-377/std", 30 | "ark-ec/std", 31 | "ark-ff/std", 32 | "ark-models-ext/std", 33 | "ark-serialize/std", 34 | "ark-std/std", 35 | ] 36 | parallel = [ 37 | "ark-ec/parallel", 38 | "ark-ff/parallel", 39 | "ark-std/parallel" 40 | ] 41 | r1cs = [ "ark-bls12-377/r1cs" ] 42 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_377/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-ed-on-bls12-377-ext" 3 | description = "Extensions for Twisted Edwards curve defined over the scalar field of the BLS12-377 curve" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-ed-on-bls12-377.workspace = true 18 | ark-models-ext.workspace = true 19 | 20 | [dev-dependencies] 21 | ark-serialize.workspace = true 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-ec/std", 29 | "ark-ed-on-bls12-377/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | r1cs = [ "ark-ed-on-bls12-377/r1cs" ] 41 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_381_bandersnatch/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ark-ed-on-bls12-381-bandersnatch-ext" 3 | description = "Extensions for Bandersnatch curve defined over the scalar field of the BLS12-381 curve" 4 | version.workspace = true 5 | authors.workspace = true 6 | repository.workspace = true 7 | keywords.workspace = true 8 | categories.workspace = true 9 | include.workspace = true 10 | license.workspace = true 11 | edition.workspace = true 12 | 13 | [dependencies] 14 | ark-ec.workspace = true 15 | ark-ff.workspace = true 16 | ark-std.workspace = true 17 | ark-ed-on-bls12-381-bandersnatch.workspace = true 18 | ark-models-ext.workspace = true 19 | 20 | [dev-dependencies] 21 | ark-serialize.workspace = true 22 | ark-algebra-test-templates.workspace = true 23 | test-utils.workspace = true 24 | 25 | [features] 26 | default = [ "std" ] 27 | std = [ 28 | "ark-ec/std", 29 | "ark-ed-on-bls12-381-bandersnatch/std", 30 | "ark-ff/std", 31 | "ark-models-ext/std", 32 | "ark-serialize/std", 33 | "ark-std/std", 34 | ] 35 | parallel = [ 36 | "ark-ec/parallel", 37 | "ark-ff/parallel", 38 | "ark-std/parallel" 39 | ] 40 | r1cs = [ "ark-ed-on-bls12-381-bandersnatch/r1cs" ] 41 | -------------------------------------------------------------------------------- /curves/bw6_761/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the BW6_761 curve generated in [\[EG20\]](https://eprint.iacr.org/2020/351). 2 | //! The name denotes that it is a curve generated using the Brezing--Weng 3 | //! method, and that its embedding degree is 6. 4 | //! The main feature of this curve is that the scalar field equals the base 5 | //! field of the BLS12_377 curve. 6 | //! 7 | //! Curve information: 8 | //! * Base field: q = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299 9 | //! * Scalar field: r = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177 10 | //! * valuation(q - 1, 2) = 1 11 | //! * valuation(r - 1, 2) = 46 12 | //! 13 | //! G1 curve equation: y^2 = x^3 + ax + b, where 14 | //! * a = 0, 15 | //! * b = -1, 16 | //! 17 | //! G2 curve equation: y^2 = x^3 + Ax + B 18 | //! * A = 0 19 | //! * B = 4 20 | 21 | #![cfg_attr(not(feature = "std"), no_std)] 22 | 23 | pub mod curves; 24 | 25 | pub use ark_bw6_761::{fq, fq::*, fq3, fq3::*, fq6, fq6::*, fr, fr::*}; 26 | pub use curves::*; 27 | -------------------------------------------------------------------------------- /curves/bls12_377/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the BLS12_377 curve generated in [\[BCGMMW20, “Zexe”\]](https://eprint.iacr.org/2018/962). 2 | //! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 3 | //! 12, defined over a 377-bit (prime) field. The main feature of this curve is 4 | //! that both the scalar field and the base field are highly 2-adic. 5 | //! (This is in contrast to the BLS12_381 curve for which only the scalar field 6 | //! is highly 2-adic.) 7 | //! 8 | //! 9 | //! Curve information: 10 | //! * Base field: q = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177 11 | //! * Scalar field: r = 8444461749428370424248824938781546531375899335154063827935233455917409239041 12 | //! * valuation(q - 1, 2) = 46 13 | //! * valuation(r - 1, 2) = 47 14 | //! * G1 curve equation: y^2 = x^3 + 1 15 | //! * G2 curve equation: y^2 = x^3 + B, where 16 | //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) 17 | 18 | #![cfg_attr(not(feature = "std"), no_std)] 19 | 20 | mod curves; 21 | 22 | pub use ark_bls12_377::{fq12, fq2, fr, Fq, Fq12Config, Fq2, Fq2Config, Fq6Config, Fr, FrConfig}; 23 | pub use curves::*; 24 | 25 | #[cfg(feature = "r1cs")] 26 | pub use ark_bls12_377::constraints; 27 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_381_bandersnatch/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_ed_on_bls12_381_bandersnatch::BandersnatchConfig as ArkConfig; 5 | use ark_models_ext::CurveConfig; 6 | 7 | pub struct TestHooks; 8 | 9 | type Config = crate::BandersnatchConfig; 10 | type EdwardsAffine = crate::EdwardsAffine; 11 | type EdwardsProjective = crate::EdwardsProjective; 12 | type SWAffine = crate::SWAffine; 13 | type SWProjective = crate::SWProjective; 14 | 15 | impl CurveHooks for TestHooks { 16 | fn msm_te( 17 | bases: &[EdwardsAffine], 18 | scalars: &[::ScalarField], 19 | ) -> EdwardsProjective { 20 | test_utils::msm_te_generic::(bases, scalars) 21 | } 22 | 23 | fn mul_projective_te(base: &EdwardsProjective, scalar: &[u64]) -> EdwardsProjective { 24 | test_utils::mul_projective_te_generic::(base, scalar) 25 | } 26 | 27 | fn msm_sw( 28 | bases: &[SWAffine], 29 | scalars: &[::ScalarField], 30 | ) -> SWProjective { 31 | test_utils::msm_sw_generic::(bases, scalars) 32 | } 33 | 34 | fn mul_projective_sw(base: &SWProjective, scalar: &[u64]) -> SWProjective { 35 | test_utils::mul_projective_sw_generic::(base, scalar) 36 | } 37 | } 38 | 39 | test_group!(te; EdwardsProjective; te); 40 | test_group!(sw; SWProjective; sw); 41 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_381_bandersnatch/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This library implements the Bendersnatch curve, a twisted Edwards curve 2 | //! whose base field is the scalar field of the curve BLS12-381. This allows 3 | //! defining cryptographic primitives that use elliptic curves over the scalar 4 | //! field of the latter curve. This curve was generated by Simon Masson from 5 | //! Anoma, and Antonio Sanso from Ethereum Foundation, and is also known as [bandersnatch](https://ethresear.ch/t/introducing-bandersnatch-a-fast-elliptic-curve-built-over-the-bls12-381-scalar-field/9957). 6 | //! 7 | //! See [here](https://github.com/asanso/Bandersnatch/blob/main/README.md) for the specification of the curve. 8 | //! There was also a Python implementation [here](https://github.com/asanso/Bandersnatch/). 9 | //! 10 | //! Curve information: 11 | //! * Base field: q = 12 | //! 52435875175126190479447740508185965837690552500527637822603658699938581184513 13 | //! * Scalar field: r = 14 | //! 13108968793781547619861935127046491459309155893440570251786403306729687672801 15 | //! * Valuation(q - 1, 2) = 32 16 | //! * Valuation(r - 1, 2) = 5 17 | //! * Curve equation: ax^2 + y^2 =1 + dx^2y^2, where 18 | //! * a = -5 19 | //! * d = 45022363124591815672509500913686876175488063829319466900776701791074614335719 20 | 21 | #![cfg_attr(not(feature = "std"), no_std)] 22 | 23 | pub mod curves; 24 | 25 | pub use ark_ed_on_bls12_381_bandersnatch::{fq, fq::*, fr, fr::*}; 26 | pub use curves::*; 27 | 28 | #[cfg(feature = "r1cs")] 29 | pub use ark_ed_on_bls12_381_bandersnatch::constraints; 30 | -------------------------------------------------------------------------------- /models/src/models/bw6/g1.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | bw6::BW6Config, 3 | short_weierstrass::{Affine, Projective}, 4 | AffineRepr, CurveGroup, 5 | }; 6 | use ark_serialize::*; 7 | use ark_std::vec::Vec; 8 | use derivative::Derivative; 9 | 10 | pub type G1Affine

= Affine<

::G1Config>; 11 | pub type G1Projective

= Projective<

::G1Config>; 12 | 13 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] 14 | #[derivative( 15 | Copy(bound = "P: BW6Config"), 16 | Clone(bound = "P: BW6Config"), 17 | PartialEq(bound = "P: BW6Config"), 18 | Eq(bound = "P: BW6Config"), 19 | Debug(bound = "P: BW6Config") 20 | )] 21 | pub struct G1Prepared(pub G1Affine

); 22 | 23 | impl From> for G1Prepared

{ 24 | fn from(other: G1Affine

) -> Self { 25 | G1Prepared(other) 26 | } 27 | } 28 | 29 | impl From> for G1Prepared

{ 30 | fn from(q: G1Projective

) -> Self { 31 | q.into_affine().into() 32 | } 33 | } 34 | 35 | impl<'a, P: BW6Config> From<&'a G1Affine

> for G1Prepared

{ 36 | fn from(other: &'a G1Affine

) -> Self { 37 | G1Prepared(*other) 38 | } 39 | } 40 | 41 | impl<'a, P: BW6Config> From<&'a G1Projective

> for G1Prepared

{ 42 | fn from(q: &'a G1Projective

) -> Self { 43 | q.into_affine().into() 44 | } 45 | } 46 | 47 | impl G1Prepared

{ 48 | pub fn is_zero(&self) -> bool { 49 | self.0.infinity 50 | } 51 | } 52 | 53 | impl Default for G1Prepared

{ 54 | fn default() -> Self { 55 | G1Prepared(G1Affine::

::generator()) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /models/src/models/bw6/g2.rs: -------------------------------------------------------------------------------- 1 | use ark_serialize::*; 2 | use ark_std::vec::Vec; 3 | use derivative::Derivative; 4 | 5 | use crate::{ 6 | bw6::BW6Config, 7 | short_weierstrass::{Affine, Projective}, 8 | AffineRepr, CurveGroup, 9 | }; 10 | 11 | pub type G2Affine

= Affine<

::G2Config>; 12 | pub type G2Projective

= Projective<

::G2Config>; 13 | 14 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] 15 | #[derivative( 16 | Copy(bound = "P: BW6Config"), 17 | Clone(bound = "P: BW6Config"), 18 | PartialEq(bound = "P: BW6Config"), 19 | Eq(bound = "P: BW6Config"), 20 | Debug(bound = "P: BW6Config") 21 | )] 22 | pub struct G2Prepared(pub G2Affine

); 23 | 24 | impl From> for G2Prepared

{ 25 | fn from(other: G2Affine

) -> Self { 26 | G2Prepared(other) 27 | } 28 | } 29 | 30 | impl From> for G2Prepared

{ 31 | fn from(q: G2Projective

) -> Self { 32 | q.into_affine().into() 33 | } 34 | } 35 | 36 | impl<'a, P: BW6Config> From<&'a G2Affine

> for G2Prepared

{ 37 | fn from(other: &'a G2Affine

) -> Self { 38 | G2Prepared(*other) 39 | } 40 | } 41 | 42 | impl<'a, P: BW6Config> From<&'a G2Projective

> for G2Prepared

{ 43 | fn from(q: &'a G2Projective

) -> Self { 44 | q.into_affine().into() 45 | } 46 | } 47 | 48 | impl G2Prepared

{ 49 | pub fn is_zero(&self) -> bool { 50 | self.0.infinity 51 | } 52 | } 53 | 54 | impl Default for G2Prepared

{ 55 | fn default() -> Self { 56 | G2Prepared(G2Affine::

::generator()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /models/src/models/bls12/g1.rs: -------------------------------------------------------------------------------- 1 | use crate::models::{ 2 | bls12::Bls12Config, 3 | short_weierstrass::{Affine, Projective}, 4 | }; 5 | use ark_ec::{AffineRepr, CurveGroup}; 6 | use ark_serialize::*; 7 | use ark_std::vec::Vec; 8 | use derivative::Derivative; 9 | 10 | pub type G1Affine

= Affine<

::G1Config>; 11 | pub type G1Projective

= Projective<

::G1Config>; 12 | 13 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] 14 | #[derivative( 15 | Copy(bound = "P: Bls12Config"), 16 | Clone(bound = "P: Bls12Config"), 17 | PartialEq(bound = "P: Bls12Config"), 18 | Eq(bound = "P: Bls12Config"), 19 | Debug(bound = "P: Bls12Config") 20 | )] 21 | pub struct G1Prepared(pub G1Affine

); 22 | 23 | impl From> for G1Prepared

{ 24 | fn from(other: G1Affine

) -> Self { 25 | G1Prepared(other) 26 | } 27 | } 28 | 29 | impl From> for G1Prepared

{ 30 | fn from(q: G1Projective

) -> Self { 31 | q.into_affine().into() 32 | } 33 | } 34 | 35 | impl<'a, P: Bls12Config> From<&'a G1Affine

> for G1Prepared

{ 36 | fn from(other: &'a G1Affine

) -> Self { 37 | G1Prepared(*other) 38 | } 39 | } 40 | 41 | impl<'a, P: Bls12Config> From<&'a G1Projective

> for G1Prepared

{ 42 | fn from(q: &'a G1Projective

) -> Self { 43 | q.into_affine().into() 44 | } 45 | } 46 | 47 | impl G1Prepared

{ 48 | pub fn is_zero(&self) -> bool { 49 | self.0.is_zero() 50 | } 51 | } 52 | 53 | impl Default for G1Prepared

{ 54 | fn default() -> Self { 55 | G1Prepared(G1Affine::

::generator()) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /models/src/models/bls12/g2.rs: -------------------------------------------------------------------------------- 1 | use crate::models::{ 2 | bls12::Bls12Config, 3 | short_weierstrass::{Affine, Projective}, 4 | }; 5 | use ark_ec::{AffineRepr, CurveGroup}; 6 | use ark_serialize::*; 7 | use ark_std::vec::Vec; 8 | use derivative::Derivative; 9 | 10 | pub type G2Affine

= Affine<

::G2Config>; 11 | pub type G2Projective

= Projective<

::G2Config>; 12 | 13 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] 14 | #[derivative( 15 | Copy(bound = "P: Bls12Config"), 16 | Clone(bound = "P: Bls12Config"), 17 | PartialEq(bound = "P: Bls12Config"), 18 | Eq(bound = "P: Bls12Config"), 19 | Debug(bound = "P: Bls12Config") 20 | )] 21 | pub struct G2Prepared(pub G2Affine

); 22 | 23 | impl From> for G2Prepared

{ 24 | fn from(other: G2Affine

) -> Self { 25 | G2Prepared(other) 26 | } 27 | } 28 | 29 | impl From> for G2Prepared

{ 30 | fn from(q: G2Projective

) -> Self { 31 | q.into_affine().into() 32 | } 33 | } 34 | 35 | impl<'a, P: Bls12Config> From<&'a G2Affine

> for G2Prepared

{ 36 | fn from(other: &'a G2Affine

) -> Self { 37 | G2Prepared(*other) 38 | } 39 | } 40 | 41 | impl<'a, P: Bls12Config> From<&'a G2Projective

> for G2Prepared

{ 42 | fn from(q: &'a G2Projective

) -> Self { 43 | q.into_affine().into() 44 | } 45 | } 46 | 47 | impl G2Prepared

{ 48 | pub fn is_zero(&self) -> bool { 49 | self.0.is_zero() 50 | } 51 | } 52 | 53 | impl Default for G2Prepared

{ 54 | fn default() -> Self { 55 | G2Prepared(G2Affine::

::generator()) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "curves/bls12_381", 4 | "curves/bls12_377", 5 | "curves/bw6_761", 6 | "curves/ed_on_bls12_377", 7 | "curves/ed_on_bls12_381_bandersnatch", 8 | "models", 9 | "test-utils", "curves/pallas", "curves/vesta", "curves/secp256k1", 10 | ] 11 | resolver = "2" 12 | 13 | [workspace.package] 14 | version = "0.5.0" 15 | authors = [ 16 | "Davide Galassi ", 17 | "Achim Schneider ", 18 | "Parity Technologies ", 19 | ] 20 | repository = "https://github.com/paritytech/arkworks-extensions" 21 | keywords = ["cryptography", "elliptic-curves", "pairing", "arkworks"] 22 | categories = ["cryptography"] 23 | include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] 24 | license = "MIT/Apache-2.0" 25 | edition = "2021" 26 | 27 | [workspace.dependencies] 28 | ark-ec = { version = "0.5", default-features = false } 29 | ark-ff = { version = "0.5", default-features = false } 30 | ark-std = { version = "0.5", default-features = false } 31 | ark-serialize = { version = "0.5", default-features = false } 32 | ark-pallas = { version = "0.5", default-features = false , features = ["curve"]} 33 | ark-vesta = { version = "0.5", default-features = false } 34 | ark-secp256k1 = { version = "0.5", default-features = false } 35 | ark-bls12-377 = { version = "0.5", default-features = false, features = ["curve"] } 36 | ark-bls12-381 = { version = "0.5", default-features = false, features = ["curve"] } 37 | ark-bw6-761 = { version = "0.5", default-features = false } 38 | ark-ed-on-bls12-377 = { version = "0.5", default-features = false } 39 | ark-ed-on-bls12-381-bandersnatch = { version = "0.5", default-features = false } 40 | ark-algebra-test-templates = { version = "0.5", default-features = false } 41 | ark-models-ext = { version = "0.5", path = "./models", default-features = false } 42 | test-utils = { path = "./test-utils", default-features = false } 43 | derivative = { version = "2.2", default-features = false, features = ["use_core"] } 44 | num-traits = { version = "0.2", default-features = false } 45 | -------------------------------------------------------------------------------- /curves/bw6_761/src/curves/g2.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_bw6_761::g2::Config as ArkConfig; 4 | use ark_models_ext::{ 5 | bw6, 6 | {short_weierstrass::SWCurveConfig, CurveConfig}, 7 | }; 8 | use ark_std::marker::PhantomData; 9 | 10 | pub use ark_bw6_761::g2::{G2_GENERATOR_X, G2_GENERATOR_Y}; 11 | 12 | pub type G2Affine = bw6::G2Affine>; 13 | pub type G2Projective = bw6::G2Projective>; 14 | 15 | #[derive(Clone, Copy)] 16 | pub struct Config(PhantomData H>); 17 | 18 | impl CurveConfig for Config { 19 | const COFACTOR: &'static [u64] = ::COFACTOR; 20 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 21 | 22 | type BaseField = ::BaseField; 23 | type ScalarField = ::ScalarField; 24 | } 25 | 26 | impl SWCurveConfig for Config { 27 | const COEFF_A: Self::BaseField = ::COEFF_A; 28 | const COEFF_B: Self::BaseField = ::COEFF_B; 29 | 30 | const GENERATOR: G2Affine = G2Affine::::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); 31 | 32 | /// Multi scalar multiplication jumping into the user-defined `msm_g2` hook. 33 | #[inline(always)] 34 | fn msm(bases: &[G2Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 35 | if bases.len() != scalars.len() { 36 | return Err(bases.len().min(scalars.len())); 37 | } 38 | Ok(H::msm_g2(bases, scalars)) 39 | } 40 | 41 | /// Projective multiplication jumping into the user-defined `mul_projective_g2` hook. 42 | #[inline(always)] 43 | fn mul_projective(base: &G2Projective, scalar: &[u64]) -> G2Projective { 44 | H::mul_projective_g2(base, scalar) 45 | } 46 | 47 | /// Affine multiplication jumping into the user-defined `mul_projective_g2` hook. 48 | #[inline(always)] 49 | fn mul_affine(base: &G2Affine, scalar: &[u64]) -> G2Projective { 50 | Self::mul_projective(&(*base).into(), scalar) 51 | } 52 | 53 | #[inline(always)] 54 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 55 | ::mul_by_a(elem) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /curves/secp256k1/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_models_ext::{ 2 | models::CurveConfig, 3 | short_weierstrass::{self, SWCurveConfig}, 4 | }; 5 | use ark_secp256k1::{Config as ArkConfig, G_GENERATOR_X, G_GENERATOR_Y}; 6 | use ark_std::marker::PhantomData; 7 | 8 | #[cfg(test)] 9 | mod tests; 10 | 11 | pub type Affine = short_weierstrass::Affine>; 12 | pub type Projective = short_weierstrass::Projective>; 13 | 14 | #[derive(Clone, Copy)] 15 | pub struct Secp256k1Config(PhantomData H>); 16 | 17 | /// Hooks for *Secp256k1*. 18 | pub trait CurveHooks: 'static + Sized { 19 | /// Short Weierstrass multi scalar multiplication. 20 | fn msm( 21 | bases: &[Affine], 22 | scalars: &[ as CurveConfig>::ScalarField], 23 | ) -> Projective; 24 | 25 | /// Short Weierstrass projective multiplication. 26 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective; 27 | } 28 | 29 | impl CurveConfig for Secp256k1Config { 30 | const COFACTOR: &'static [u64] = ::COFACTOR; 31 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 32 | 33 | type BaseField = ::BaseField; 34 | type ScalarField = ::ScalarField; 35 | } 36 | 37 | impl SWCurveConfig for Secp256k1Config { 38 | const COEFF_A: Self::BaseField = ::COEFF_A; 39 | const COEFF_B: Self::BaseField = ::COEFF_B; 40 | 41 | const GENERATOR: Affine = Affine::::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y); 42 | 43 | /// Multi scalar multiplication jumping into the user-defined `msm` hook. 44 | #[inline(always)] 45 | fn msm(bases: &[Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 46 | if bases.len() != scalars.len() { 47 | return Err(bases.len().min(scalars.len())); 48 | } 49 | Ok(H::msm(bases, scalars)) 50 | } 51 | 52 | /// Projective multiplication jumping into the user-defined `mul_projective` hook. 53 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 54 | H::mul_projective(base, scalar) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /curves/pallas/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_models_ext::{ 2 | models::CurveConfig, 3 | short_weierstrass::{self, SWCurveConfig}, 4 | }; 5 | use ark_pallas::{PallasConfig as ArkConfig, G_GENERATOR_X, G_GENERATOR_Y}; 6 | use ark_std::marker::PhantomData; 7 | 8 | #[cfg(test)] 9 | mod tests; 10 | 11 | pub type Affine = short_weierstrass::Affine>; 12 | pub type Projective = short_weierstrass::Projective>; 13 | 14 | #[derive(Clone, Copy)] 15 | pub struct PallasConfig(PhantomData H>); 16 | 17 | /// Hooks for *Pallas*. 18 | pub trait CurveHooks: 'static + Sized { 19 | /// Short Weierstrass multi scalar multiplication. 20 | fn msm( 21 | bases: &[Affine], 22 | scalars: &[ as CurveConfig>::ScalarField], 23 | ) -> Projective; 24 | 25 | /// Short Weierstrass projective multiplication. 26 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective; 27 | } 28 | 29 | impl CurveConfig for PallasConfig { 30 | const COFACTOR: &'static [u64] = ::COFACTOR; 31 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 32 | 33 | type BaseField = ::BaseField; 34 | type ScalarField = ::ScalarField; 35 | } 36 | 37 | impl SWCurveConfig for PallasConfig { 38 | const COEFF_A: Self::BaseField = ::COEFF_A; 39 | const COEFF_B: Self::BaseField = ::COEFF_B; 40 | 41 | const GENERATOR: Affine = Affine::::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y); 42 | 43 | /// Multi scalar multiplication jumping into the user-defined `msm` hook. 44 | #[inline(always)] 45 | fn msm(bases: &[Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 46 | if bases.len() != scalars.len() { 47 | return Err(bases.len().min(scalars.len())); 48 | } 49 | Ok(H::msm(bases, scalars)) 50 | } 51 | 52 | /// Projective multiplication jumping into the user-defined `mul_projective` hook. 53 | #[inline(always)] 54 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 55 | H::mul_projective(base, scalar) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /curves/bw6_761/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_bw6_761::{g1::Config as ArkG1Config, g2::Config as ArkG2Config, BW6_761 as ArkBW6_761}; 5 | use ark_models_ext::{ 6 | pairing::{Pairing, PairingOutput}, 7 | CurveConfig, 8 | }; 9 | 10 | struct TestHooks; 11 | 12 | type BW6_761 = crate::BW6_761; 13 | type G1Projective = crate::G1Projective; 14 | type G2Projective = crate::G2Projective; 15 | type G1Affine = crate::G1Affine; 16 | type G2Affine = crate::G2Affine; 17 | type G1Config = crate::g1::Config; 18 | type G2Config = crate::g2::Config; 19 | 20 | impl CurveHooks for TestHooks { 21 | fn multi_miller_loop( 22 | g1: impl Iterator::G1Prepared>, 23 | g2: impl Iterator::G2Prepared>, 24 | ) -> ::TargetField { 25 | test_utils::multi_miller_loop_generic::(g1, g2) 26 | } 27 | 28 | fn final_exponentiation( 29 | target: ::TargetField, 30 | ) -> ::TargetField { 31 | test_utils::final_exponentiation_generic::(target) 32 | } 33 | 34 | fn msm_g1( 35 | bases: &[G1Affine], 36 | scalars: &[::ScalarField], 37 | ) -> G1Projective { 38 | test_utils::msm_sw_generic::(bases, scalars) 39 | } 40 | 41 | fn msm_g2( 42 | bases: &[G2Affine], 43 | scalars: &[::ScalarField], 44 | ) -> G2Projective { 45 | test_utils::msm_sw_generic::(bases, scalars) 46 | } 47 | 48 | fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective { 49 | test_utils::mul_projective_sw_generic::(base, scalar) 50 | } 51 | 52 | fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective { 53 | test_utils::mul_projective_sw_generic::(base, scalar) 54 | } 55 | } 56 | 57 | test_group!(g1; G1Projective; sw); 58 | test_group!(g2; G2Projective; sw); 59 | test_group!(pairing_output; PairingOutput; msm); 60 | test_pairing!(pairing; crate::BW6_761); 61 | -------------------------------------------------------------------------------- /curves/vesta/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_models_ext::{ 2 | models::CurveConfig, 3 | short_weierstrass::{self, SWCurveConfig}, 4 | }; 5 | use ark_std::marker::PhantomData; 6 | use ark_vesta::{VestaConfig as ArkConfig, G_GENERATOR_X, G_GENERATOR_Y}; 7 | 8 | #[cfg(test)] 9 | mod tests; 10 | 11 | pub type Affine = short_weierstrass::Affine>; 12 | pub type Projective = short_weierstrass::Projective>; 13 | 14 | #[derive(Clone, Copy)] 15 | pub struct VestaConfig(PhantomData H>); 16 | 17 | /// Hooks for *Vesta*. 18 | pub trait CurveHooks: 'static + Sized { 19 | /// Short Weierstrass multi scalar multiplication. 20 | fn msm( 21 | bases: &[Affine], 22 | scalars: &[ as CurveConfig>::ScalarField], 23 | ) -> Projective; 24 | 25 | /// Short Weierstrass projective multiplication. 26 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective; 27 | } 28 | 29 | impl CurveConfig for VestaConfig { 30 | const COFACTOR: &'static [u64] = ::COFACTOR; 31 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 32 | 33 | type BaseField = ::BaseField; 34 | type ScalarField = ::ScalarField; 35 | } 36 | 37 | impl SWCurveConfig for VestaConfig { 38 | const COEFF_A: Self::BaseField = ::COEFF_A; 39 | const COEFF_B: Self::BaseField = ::COEFF_B; 40 | 41 | const GENERATOR: Affine = Affine::::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y); 42 | 43 | /// Multi scalar multiplication jumping into the user-defined `vesta_msm` hook. 44 | #[inline(always)] 45 | fn msm(bases: &[Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 46 | if bases.len() != scalars.len() { 47 | return Err(bases.len().min(scalars.len())); 48 | } 49 | Ok(H::msm(bases, scalars)) 50 | } 51 | 52 | /// Projective multiplication jumping into the user-defined `vesta_mul_projective` hook. 53 | #[inline(always)] 54 | fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective { 55 | H::mul_projective(base, scalar) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /curves/bw6_761/src/curves/g1.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_bw6_761::g1::Config as ArkConfig; 4 | use ark_models_ext::{ 5 | bw6, 6 | {short_weierstrass::SWCurveConfig, CurveConfig}, 7 | }; 8 | use ark_std::marker::PhantomData; 9 | 10 | pub use ark_bw6_761::g1::{G1_GENERATOR_X, G1_GENERATOR_Y}; 11 | 12 | pub type G1Affine = bw6::G1Affine>; 13 | pub type G1Projective = bw6::G1Projective>; 14 | 15 | #[derive(Clone, Copy)] 16 | pub struct Config(PhantomData H>); 17 | 18 | impl CurveConfig for Config { 19 | const COFACTOR: &'static [u64] = ::COFACTOR; 20 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 21 | 22 | type BaseField = ::BaseField; 23 | type ScalarField = ::ScalarField; 24 | } 25 | 26 | impl SWCurveConfig for Config { 27 | const COEFF_A: Self::BaseField = ::COEFF_A; 28 | const COEFF_B: Self::BaseField = ::COEFF_B; 29 | 30 | const GENERATOR: G1Affine = G1Affine::::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); 31 | 32 | /// Multi scalar multiplication jumping into the user-defined `msm_g1` hook. 33 | #[inline(always)] 34 | fn msm(bases: &[G1Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 35 | if bases.len() != scalars.len() { 36 | return Err(bases.len().min(scalars.len())); 37 | } 38 | Ok(H::msm_g1(bases, scalars)) 39 | } 40 | 41 | /// Projective multiplication jumping into the user-defined `mul_projective_g1` hook. 42 | #[inline(always)] 43 | fn mul_projective(base: &G1Projective, scalar: &[u64]) -> G1Projective { 44 | H::mul_projective_g1(base, scalar) 45 | } 46 | 47 | /// Affine multiplication jumping into the user-defined `mul_projective_g1` hook. 48 | #[inline(always)] 49 | fn mul_affine(base: &G1Affine, scalar: &[u64]) -> G1Projective { 50 | ::mul_projective(&(*base).into(), scalar) 51 | } 52 | 53 | #[inline(always)] 54 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 55 | ::mul_by_a(elem) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /curves/bls12_377/src/curves/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | use ark_algebra_test_templates::*; 3 | use ark_bls12_377::{ 4 | g1::Config as ArkG1Config, g2::Config as ArkG2Config, Bls12_377 as ArkBls12_377, 5 | }; 6 | use ark_models_ext::{ 7 | pairing::{Pairing, PairingOutput}, 8 | CurveConfig, 9 | }; 10 | 11 | struct TestHooks; 12 | 13 | type Bls12_377 = crate::Bls12_377; 14 | type G1Projective = crate::G1Projective; 15 | type G2Projective = crate::G2Projective; 16 | type G1Affine = crate::G1Affine; 17 | type G2Affine = crate::G2Affine; 18 | type G1Config = crate::g1::Config; 19 | type G2Config = crate::g2::Config; 20 | 21 | impl CurveHooks for TestHooks { 22 | fn multi_miller_loop( 23 | g1: impl Iterator::G1Prepared>, 24 | g2: impl Iterator::G2Prepared>, 25 | ) -> ::TargetField { 26 | test_utils::multi_miller_loop_generic::(g1, g2) 27 | } 28 | 29 | fn final_exponentiation( 30 | target: ::TargetField, 31 | ) -> ::TargetField { 32 | test_utils::final_exponentiation_generic::(target) 33 | } 34 | 35 | fn msm_g1( 36 | bases: &[G1Affine], 37 | scalars: &[::ScalarField], 38 | ) -> G1Projective { 39 | test_utils::msm_sw_generic::(bases, scalars) 40 | } 41 | 42 | fn msm_g2( 43 | bases: &[G2Affine], 44 | scalars: &[::ScalarField], 45 | ) -> G2Projective { 46 | test_utils::msm_sw_generic::(bases, scalars) 47 | } 48 | 49 | fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective { 50 | test_utils::mul_projective_sw_generic::(base, scalar) 51 | } 52 | 53 | fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective { 54 | test_utils::mul_projective_sw_generic::(base, scalar) 55 | } 56 | } 57 | 58 | test_group!(g1; G1Projective; sw); 59 | test_group!(g2; G2Projective; sw); 60 | test_group!(pairing_output; PairingOutput; msm); 61 | test_pairing!(pairing; crate::Bls12_377); 62 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | # Run CI on push only for 'main' branch 5 | push: 6 | branches: [main] 7 | # Run CI on pull request for all branches 8 | pull_request: 9 | branches: ["**"] 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | RUSTFLAGS: "-D warnings" 14 | RUST_BACKTRACE: 1 15 | 16 | jobs: 17 | fmt: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Install toolchain 22 | uses: actions-rs/toolchain@v1 23 | with: 24 | profile: minimal 25 | toolchain: stable 26 | components: rustfmt 27 | - name: Format 28 | run: cargo fmt --all --check 29 | 30 | clippy: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v3 34 | - name: Install toolchain 35 | uses: actions-rs/toolchain@v1 36 | with: 37 | profile: minimal 38 | toolchain: stable 39 | components: clippy 40 | - name: Clippy 41 | run: cargo clippy --all-targets --all-features 42 | 43 | build: 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v3 47 | - name: Install toolchain 48 | uses: actions-rs/toolchain@v1 49 | with: 50 | profile: minimal 51 | toolchain: stable 52 | - name: Build 53 | run: cargo build --verbose --all-features 54 | 55 | build-wasm32: 56 | runs-on: ubuntu-latest 57 | steps: 58 | - uses: actions/checkout@v3 59 | - name: Install toolchain 60 | uses: actions-rs/toolchain@v1 61 | with: 62 | profile: minimal 63 | toolchain: stable 64 | target: wasm32-unknown-unknown 65 | - name: Build 66 | run: cargo build --verbose --no-default-features --target wasm32-unknown-unknown 67 | 68 | test: 69 | runs-on: ubuntu-latest 70 | steps: 71 | - uses: actions/checkout@v3 72 | - name: Install toolchain 73 | uses: actions-rs/toolchain@v1 74 | with: 75 | profile: minimal 76 | toolchain: stable 77 | - name: Run tests 78 | run: cargo test --release --all-features 79 | 80 | publish-dry-run: 81 | runs-on: ubuntu-latest 82 | steps: 83 | - uses: actions/checkout@v3 84 | - name: Install toolchain 85 | uses: actions-rs/toolchain@v1 86 | with: 87 | profile: minimal 88 | toolchain: stable 89 | - name: Publish dry-run 90 | run: bash scripts/publish.sh --dry-run 91 | -------------------------------------------------------------------------------- /curves/bls12_377/src/curves/g2.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_bls12_377::g2::Config as ArkConfig; 4 | use ark_models_ext::{bls12, short_weierstrass::SWCurveConfig, CurveConfig}; 5 | use ark_std::marker::PhantomData; 6 | 7 | pub use ark_bls12_377::g2::{ 8 | G2_GENERATOR_X, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1, G2_GENERATOR_Y, G2_GENERATOR_Y_C0, 9 | G2_GENERATOR_Y_C1, 10 | }; 11 | 12 | pub type G2Affine = bls12::G2Affine>; 13 | pub type G2Projective = bls12::G2Projective>; 14 | 15 | #[derive(Clone, Copy)] 16 | pub struct Config(PhantomData H>); 17 | 18 | impl CurveConfig for Config { 19 | type BaseField = ::BaseField; 20 | type ScalarField = ::ScalarField; 21 | 22 | const COFACTOR: &'static [u64] = ::COFACTOR; 23 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 24 | } 25 | 26 | impl SWCurveConfig for Config { 27 | const COEFF_A: Self::BaseField = ::COEFF_A; 28 | const COEFF_B: Self::BaseField = ::COEFF_B; 29 | 30 | const GENERATOR: G2Affine = G2Affine::::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); 31 | 32 | /// Multi scalar multiplication jumping into the user-defined `msm_g2` hook. 33 | /// 34 | /// On any internal error returns `Err(0)`. 35 | #[inline(always)] 36 | fn msm(bases: &[G2Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 37 | if bases.len() != scalars.len() { 38 | return Err(bases.len().min(scalars.len())); 39 | } 40 | Ok(H::msm_g2(bases, scalars)) 41 | } 42 | 43 | /// Projective multiplication jumping into the user-defined `mul_projective_g2` hook. 44 | /// 45 | /// On any internal error returns `Projective::zero()`. 46 | #[inline(always)] 47 | fn mul_projective(base: &G2Projective, scalar: &[u64]) -> G2Projective { 48 | H::mul_projective_g2(base, scalar) 49 | } 50 | 51 | /// Affine multiplication jumping into the user-defined `mul_projective_g2` hook. 52 | /// 53 | /// On any internal error returns `Projective::zero()`. 54 | #[inline(always)] 55 | fn mul_affine(base: &G2Affine, scalar: &[u64]) -> G2Projective { 56 | Self::mul_projective(&(*base).into(), scalar) 57 | } 58 | 59 | #[inline(always)] 60 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 61 | ::mul_by_a(elem) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /models/src/models/bw6/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | models::{short_weierstrass::SWCurveConfig, CurveConfig}, 3 | pairing::{MillerLoopOutput, Pairing, PairingOutput}, 4 | }; 5 | 6 | pub use ark_ec::bw6::TwistType; 7 | use ark_ff::fields::{ 8 | fp3::Fp3Config, 9 | fp6_2over3::{Fp6, Fp6Config}, 10 | PrimeField, 11 | }; 12 | use ark_std::marker::PhantomData; 13 | use derivative::Derivative; 14 | 15 | pub trait BW6Config: 'static + Sized { 16 | const X: ::BigInt; 17 | const X_IS_NEGATIVE: bool; 18 | const ATE_LOOP_COUNT_1: &'static [u64]; 19 | const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool; 20 | const ATE_LOOP_COUNT_2: &'static [i8]; 21 | const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool; 22 | const TWIST_TYPE: TwistType; 23 | type Fp: PrimeField + Into<::BigInt>; 24 | type Fp3Config: Fp3Config; 25 | type Fp6Config: Fp6Config; 26 | type G1Config: SWCurveConfig; 27 | type G2Config: SWCurveConfig< 28 | BaseField = Self::Fp, 29 | ScalarField = ::ScalarField, 30 | >; 31 | 32 | fn final_exponentiation(f: MillerLoopOutput>) -> Option>>; 33 | 34 | fn multi_miller_loop( 35 | a: impl IntoIterator>>, 36 | b: impl IntoIterator>>, 37 | ) -> MillerLoopOutput>; 38 | } 39 | 40 | pub mod g1; 41 | pub mod g2; 42 | 43 | pub use self::{ 44 | g1::{G1Affine, G1Prepared, G1Projective}, 45 | g2::{G2Affine, G2Prepared, G2Projective}, 46 | }; 47 | 48 | #[derive(Derivative)] 49 | #[derivative(Copy, Clone, PartialEq, Eq, Debug, Hash)] 50 | pub struct BW6(PhantomData P>); 51 | 52 | impl Pairing for BW6

{ 53 | type BaseField = ::BaseField; 54 | type ScalarField = ::ScalarField; 55 | type G1 = G1Projective

; 56 | type G1Affine = G1Affine

; 57 | type G1Prepared = G1Prepared

; 58 | type G2 = G2Projective

; 59 | type G2Affine = G2Affine

; 60 | type G2Prepared = G2Prepared

; 61 | type TargetField = Fp6; 62 | 63 | fn final_exponentiation(f: MillerLoopOutput) -> Option> { 64 | P::final_exponentiation(f) 65 | } 66 | 67 | fn multi_miller_loop( 68 | a: impl IntoIterator>, 69 | b: impl IntoIterator>, 70 | ) -> MillerLoopOutput { 71 | P::multi_miller_loop(a, b) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /models/src/models/bls12/mod.rs: -------------------------------------------------------------------------------- 1 | pub use ark_ec::models::bls12::TwistType; 2 | use ark_ec::{ 3 | models::CurveConfig, 4 | pairing::{MillerLoopOutput, Pairing, PairingOutput}, 5 | }; 6 | use ark_ff::{ 7 | fields::{ 8 | fp12_2over3over2::{Fp12, Fp12Config}, 9 | fp2::Fp2Config, 10 | fp6_3over2::Fp6Config, 11 | Fp2, 12 | }, 13 | PrimeField, 14 | }; 15 | use ark_std::marker::PhantomData; 16 | use derivative::Derivative; 17 | 18 | use crate::models::short_weierstrass::SWCurveConfig; 19 | 20 | pub trait Bls12Config: 'static + Sized { 21 | /// Parameterizes the BLS12 family. 22 | const X: &'static [u64]; 23 | /// Is `Self::X` negative? 24 | const X_IS_NEGATIVE: bool; 25 | /// What kind of twist is this? 26 | const TWIST_TYPE: TwistType; 27 | 28 | type Fp: PrimeField + Into<::BigInt>; 29 | type Fp2Config: Fp2Config; 30 | type Fp6Config: Fp6Config; 31 | type Fp12Config: Fp12Config; 32 | type G1Config: SWCurveConfig; 33 | type G2Config: SWCurveConfig< 34 | BaseField = Fp2, 35 | ScalarField = ::ScalarField, 36 | >; 37 | 38 | fn multi_miller_loop( 39 | a_vec: impl IntoIterator>>, 40 | b_vec: impl IntoIterator>>, 41 | ) -> MillerLoopOutput>; 42 | 43 | fn final_exponentiation(f: MillerLoopOutput>) 44 | -> Option>>; 45 | } 46 | 47 | pub mod g1; 48 | pub mod g2; 49 | 50 | pub use self::{ 51 | g1::{G1Affine, G1Prepared, G1Projective}, 52 | g2::{G2Affine, G2Prepared, G2Projective}, 53 | }; 54 | 55 | #[derive(Derivative)] 56 | #[derivative(Copy, Clone, PartialEq, Eq, Debug, Hash)] 57 | pub struct Bls12(PhantomData P>); 58 | 59 | impl Pairing for Bls12

{ 60 | type BaseField = ::BaseField; 61 | type ScalarField = ::ScalarField; 62 | type G1 = G1Projective

; 63 | type G1Affine = G1Affine

; 64 | type G1Prepared = G1Prepared

; 65 | type G2 = G2Projective

; 66 | type G2Affine = G2Affine

; 67 | type G2Prepared = G2Prepared

; 68 | type TargetField = Fp12; 69 | 70 | fn multi_miller_loop( 71 | a: impl IntoIterator>, 72 | b: impl IntoIterator>, 73 | ) -> MillerLoopOutput { 74 | P::multi_miller_loop(a, b) 75 | } 76 | 77 | fn final_exponentiation(f: MillerLoopOutput) -> Option> { 78 | P::final_exponentiation(f) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_377/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_ed_on_bls12_377::{EdwardsConfig as ArkConfig, GENERATOR_X, GENERATOR_Y}; 2 | use ark_models_ext::{ 3 | twisted_edwards::{self, MontCurveConfig, TECurveConfig}, 4 | CurveConfig, 5 | }; 6 | use ark_std::marker::PhantomData; 7 | 8 | #[cfg(test)] 9 | mod tests; 10 | 11 | pub type EdwardsAffine = twisted_edwards::Affine>; 12 | pub type EdwardsProjective = twisted_edwards::Projective>; 13 | 14 | #[derive(Clone, Copy)] 15 | pub struct EdwardsConfig(PhantomData H>); 16 | 17 | /// Hooks for *Ed-on-BLS12-377*. 18 | pub trait CurveHooks: 'static + Sized { 19 | /// Twisted Edwards multi scalar multiplication. 20 | fn msm( 21 | bases: &[EdwardsAffine], 22 | scalars: &[ as CurveConfig>::ScalarField], 23 | ) -> EdwardsProjective; 24 | 25 | /// Twisted Edwards projective multiplication. 26 | fn mul_projective(base: &EdwardsProjective, scalar: &[u64]) -> EdwardsProjective; 27 | } 28 | 29 | impl CurveConfig for EdwardsConfig { 30 | const COFACTOR: &'static [u64] = ::COFACTOR; 31 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 32 | 33 | type BaseField = ::BaseField; 34 | type ScalarField = ::ScalarField; 35 | } 36 | 37 | impl TECurveConfig for EdwardsConfig { 38 | const COEFF_A: Self::BaseField = ::COEFF_A; 39 | const COEFF_D: Self::BaseField = ::COEFF_D; 40 | 41 | const GENERATOR: EdwardsAffine = EdwardsAffine::::new_unchecked(GENERATOR_X, GENERATOR_Y); 42 | 43 | type MontCurveConfig = Self; 44 | 45 | /// Multi scalar multiplication jumping into the user-defined `msm` hook. 46 | #[inline(always)] 47 | fn msm( 48 | bases: &[EdwardsAffine], 49 | scalars: &[Self::ScalarField], 50 | ) -> Result, usize> { 51 | if bases.len() != scalars.len() { 52 | return Err(bases.len().min(scalars.len())); 53 | } 54 | Ok(H::msm(bases, scalars)) 55 | } 56 | 57 | /// Projective multiplication jumping into the user-defined `mul_projective` hook. 58 | #[inline(always)] 59 | fn mul_projective(base: &EdwardsProjective, scalar: &[u64]) -> EdwardsProjective { 60 | H::mul_projective(base, scalar) 61 | } 62 | 63 | /// Affine multiplication jumping into the user-defined `mul_projective_g2` hook. 64 | #[inline(always)] 65 | fn mul_affine(base: &EdwardsAffine, scalar: &[u64]) -> EdwardsProjective { 66 | Self::mul_projective(&(*base).into(), scalar) 67 | } 68 | 69 | #[inline(always)] 70 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 71 | ::mul_by_a(elem) 72 | } 73 | } 74 | 75 | impl MontCurveConfig for EdwardsConfig { 76 | const COEFF_A: Self::BaseField = ::COEFF_A; 77 | const COEFF_B: Self::BaseField = ::COEFF_B; 78 | 79 | type TECurveConfig = Self; 80 | } 81 | -------------------------------------------------------------------------------- /curves/bls12_377/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_377::Config as ArkConfig; 2 | use ark_ec::bls12::Bls12Config as ArkBls12Config; 3 | use ark_models_ext::{ 4 | bls12::{Bls12, Bls12Config, G1Prepared, G2Prepared, TwistType}, 5 | pairing::{MillerLoopOutput, Pairing, PairingOutput}, 6 | CurveConfig, 7 | }; 8 | use ark_std::marker::PhantomData; 9 | 10 | pub mod g1; 11 | pub mod g2; 12 | 13 | #[cfg(test)] 14 | mod tests; 15 | 16 | pub use self::{ 17 | g1::{G1Affine, G1Projective}, 18 | g2::{G2Affine, G2Projective}, 19 | }; 20 | 21 | /// Hooks for *BLS12-377* curve. 22 | pub trait CurveHooks: 'static + Sized { 23 | /// Pairing multi Miller loop. 24 | fn multi_miller_loop( 25 | g1: impl Iterator as Pairing>::G1Prepared>, 26 | g2: impl Iterator as Pairing>::G2Prepared>, 27 | ) -> as Pairing>::TargetField; 28 | 29 | /// Pairing final exponentiation. 30 | fn final_exponentiation( 31 | target: as Pairing>::TargetField, 32 | ) -> as Pairing>::TargetField; 33 | 34 | /// Multi scalar multiplication on G1. 35 | fn msm_g1( 36 | bases: &[g1::G1Affine], 37 | scalars: &[ as CurveConfig>::ScalarField], 38 | ) -> g1::G1Projective; 39 | 40 | /// Multi scalar multiplication on G2. 41 | fn msm_g2( 42 | bases: &[g2::G2Affine], 43 | scalars: &[ as CurveConfig>::ScalarField], 44 | ) -> g2::G2Projective; 45 | 46 | /// Projective multiplication on G1. 47 | fn mul_projective_g1(base: &g1::G1Projective, scalar: &[u64]) -> g1::G1Projective; 48 | 49 | /// Projective multiplication on G2. 50 | fn mul_projective_g2(base: &g2::G2Projective, scalar: &[u64]) -> g2::G2Projective; 51 | } 52 | 53 | #[derive(Clone, Copy)] 54 | pub struct Config(PhantomData H>); 55 | 56 | pub type Bls12_377 = Bls12>; 57 | 58 | impl Bls12Config for Config { 59 | const X: &'static [u64] = ::X; 60 | const X_IS_NEGATIVE: bool = ::X_IS_NEGATIVE; 61 | const TWIST_TYPE: TwistType = ::TWIST_TYPE; 62 | 63 | type Fp = ::Fp; 64 | type Fp2Config = ::Fp2Config; 65 | type Fp6Config = ::Fp6Config; 66 | type Fp12Config = ::Fp12Config; 67 | 68 | type G1Config = g1::Config; 69 | type G2Config = g2::Config; 70 | 71 | /// Multi Miller loop jumping into the user-defined `multi_miller_loop` hook. 72 | #[inline(always)] 73 | fn multi_miller_loop( 74 | g1: impl IntoIterator>>, 75 | g2: impl IntoIterator>>, 76 | ) -> MillerLoopOutput> { 77 | let g1 = g1.into_iter().map(|item| item.into()); 78 | let g2 = g2.into_iter().map(|item| item.into()); 79 | let res = H::multi_miller_loop(g1, g2); 80 | MillerLoopOutput(res) 81 | } 82 | 83 | /// Final exponentiation jumping into the user-defined `final_exponentiation` hook. 84 | #[inline(always)] 85 | fn final_exponentiation( 86 | target: MillerLoopOutput>, 87 | ) -> Option>> { 88 | let res = H::final_exponentiation(target.0); 89 | Some(PairingOutput(res)) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_381::Config as ArkConfig; 2 | use ark_ec::bls12::Bls12Config as ArkBls12Config; 3 | use ark_models_ext::{ 4 | bls12::{Bls12, Bls12Config, G1Prepared, G2Prepared, TwistType}, 5 | pairing::{MillerLoopOutput, Pairing, PairingOutput}, 6 | CurveConfig, 7 | }; 8 | use ark_std::marker::PhantomData; 9 | 10 | pub mod g1; 11 | pub mod g2; 12 | pub(crate) mod util; 13 | 14 | #[cfg(test)] 15 | mod tests; 16 | 17 | pub use self::{ 18 | g1::{G1Affine, G1Projective}, 19 | g2::{G2Affine, G2Projective}, 20 | }; 21 | 22 | /// Hooks for *BLS12-381* curve. 23 | pub trait CurveHooks: 'static + Sized { 24 | /// Pairing multi Miller loop. 25 | fn multi_miller_loop( 26 | g1: impl Iterator as Pairing>::G1Prepared>, 27 | g2: impl Iterator as Pairing>::G2Prepared>, 28 | ) -> as Pairing>::TargetField; 29 | 30 | /// Pairing final exponentiation. 31 | fn final_exponentiation( 32 | target: as Pairing>::TargetField, 33 | ) -> as Pairing>::TargetField; 34 | 35 | /// Multi scalar multiplication on G1. 36 | fn msm_g1( 37 | bases: &[g1::G1Affine], 38 | scalars: &[ as CurveConfig>::ScalarField], 39 | ) -> G1Projective; 40 | 41 | /// Multi scalar multiplication on G2. 42 | fn msm_g2( 43 | bases: &[g2::G2Affine], 44 | scalars: &[ as CurveConfig>::ScalarField], 45 | ) -> G2Projective; 46 | 47 | /// Projective multiplication on G1. 48 | fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective; 49 | 50 | /// Projective multiplication on G2. 51 | fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective; 52 | } 53 | 54 | #[derive(Clone, Copy)] 55 | pub struct Config(PhantomData H>); 56 | 57 | pub type Bls12_381 = Bls12>; 58 | 59 | impl Bls12Config for Config { 60 | const X: &'static [u64] = ::X; 61 | const X_IS_NEGATIVE: bool = ::X_IS_NEGATIVE; 62 | const TWIST_TYPE: TwistType = ::TWIST_TYPE; 63 | 64 | type Fp = ::Fp; 65 | type Fp2Config = ::Fp2Config; 66 | type Fp6Config = ::Fp6Config; 67 | type Fp12Config = ::Fp12Config; 68 | 69 | type G1Config = g1::Config; 70 | type G2Config = g2::Config; 71 | 72 | /// Multi Miller loop jumping into the user-defined `multi_miller_loop` hook. 73 | #[inline(always)] 74 | fn multi_miller_loop( 75 | g1: impl IntoIterator>>, 76 | g2: impl IntoIterator>>, 77 | ) -> MillerLoopOutput> { 78 | let g1 = g1.into_iter().map(|item| item.into()); 79 | let g2 = g2.into_iter().map(|item| item.into()); 80 | let res = H::multi_miller_loop(g1, g2); 81 | MillerLoopOutput(res) 82 | } 83 | 84 | /// Final exponentiation jumping into the user-defined `final_exponentiation` hook. 85 | #[inline(always)] 86 | fn final_exponentiation( 87 | target: MillerLoopOutput>, 88 | ) -> Option>> { 89 | let res = H::final_exponentiation(target.0); 90 | Some(PairingOutput(res)) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /curves/bw6_761/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_bw6_761::Config as ArkConfig; 2 | use ark_ec::bw6::BW6Config as ArkBW6Config; 3 | use ark_ff::PrimeField; 4 | use ark_models_ext::{ 5 | bw6::{BW6Config, G1Prepared, G2Prepared, TwistType, BW6}, 6 | pairing::{MillerLoopOutput, Pairing, PairingOutput}, 7 | CurveConfig, 8 | }; 9 | use ark_std::marker::PhantomData; 10 | 11 | pub mod g1; 12 | pub mod g2; 13 | 14 | #[cfg(test)] 15 | mod tests; 16 | 17 | pub use self::{ 18 | g1::{G1Affine, G1Projective}, 19 | g2::{G2Affine, G2Projective}, 20 | }; 21 | 22 | /// Hooks for *BW6-761* curve. 23 | pub trait CurveHooks: 'static + Sized { 24 | /// Pairing multi Miller loop. 25 | fn multi_miller_loop( 26 | g1: impl Iterator as Pairing>::G1Prepared>, 27 | g2: impl Iterator as Pairing>::G2Prepared>, 28 | ) -> as Pairing>::TargetField; 29 | 30 | /// Pairing final exponentiation. 31 | fn final_exponentiation( 32 | target: as Pairing>::TargetField, 33 | ) -> as Pairing>::TargetField; 34 | 35 | /// Multi scalar multiplication on G1. 36 | fn msm_g1( 37 | bases: &[g1::G1Affine], 38 | scalars: &[ as CurveConfig>::ScalarField], 39 | ) -> g1::G1Projective; 40 | 41 | /// Multi scalar multiplication on G2. 42 | fn msm_g2( 43 | bases: &[g2::G2Affine], 44 | scalars: &[ as CurveConfig>::ScalarField], 45 | ) -> g2::G2Projective; 46 | 47 | /// Projective multiplication on G1. 48 | fn mul_projective_g1(base: &g1::G1Projective, scalar: &[u64]) -> g1::G1Projective; 49 | 50 | /// Projective multiplication on G2. 51 | fn mul_projective_g2(base: &g2::G2Projective, scalar: &[u64]) -> g2::G2Projective; 52 | } 53 | 54 | #[derive(Clone, Copy)] 55 | pub struct Config(PhantomData H>); 56 | 57 | pub type BW6_761 = BW6>; 58 | 59 | impl BW6Config for Config { 60 | const X: ::BigInt = ::X; 61 | const X_IS_NEGATIVE: bool = ::X_IS_NEGATIVE; 62 | const TWIST_TYPE: TwistType = ::TWIST_TYPE; 63 | 64 | const ATE_LOOP_COUNT_1: &'static [u64] = ::ATE_LOOP_COUNT_1; 65 | const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = 66 | ::ATE_LOOP_COUNT_1_IS_NEGATIVE; 67 | 68 | const ATE_LOOP_COUNT_2: &'static [i8] = ::ATE_LOOP_COUNT_2; 69 | const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = 70 | ::ATE_LOOP_COUNT_2_IS_NEGATIVE; 71 | 72 | type Fp = ::Fp; 73 | type Fp3Config = ::Fp3Config; 74 | type Fp6Config = ::Fp6Config; 75 | 76 | type G1Config = g1::Config; 77 | type G2Config = g2::Config; 78 | 79 | /// Multi Miller loop jumping into the user-defined `multi_miller_loop` hook. 80 | /// 81 | /// For any internal error returns `TargetField::zero()`. 82 | #[inline(always)] 83 | fn multi_miller_loop( 84 | g1: impl IntoIterator>>, 85 | g2: impl IntoIterator>>, 86 | ) -> MillerLoopOutput> { 87 | let g1 = g1.into_iter().map(|item| item.into()); 88 | let g2 = g2.into_iter().map(|item| item.into()); 89 | let res = H::multi_miller_loop(g1, g2); 90 | MillerLoopOutput(res) 91 | } 92 | 93 | /// Final exponentiation jumping into the user-defined `final_exponentiation` hook. 94 | /// 95 | /// For any internal error returns `None`. 96 | #[inline(always)] 97 | fn final_exponentiation( 98 | target: MillerLoopOutput>, 99 | ) -> Option>> { 100 | let res = H::final_exponentiation(target.0); 101 | Some(PairingOutput(res)) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /curves/bls12_377/src/curves/g1.rs: -------------------------------------------------------------------------------- 1 | use crate::CurveHooks; 2 | 3 | use ark_bls12_377::g1::Config as ArkConfig; 4 | use ark_models_ext::{ 5 | bls12, 6 | short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, 7 | twisted_edwards::{ 8 | Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig, 9 | }, 10 | CurveConfig, 11 | }; 12 | use ark_std::marker::PhantomData; 13 | 14 | pub use ark_bls12_377::g1::{G1_GENERATOR_X, G1_GENERATOR_Y, TE_GENERATOR_X, TE_GENERATOR_Y}; 15 | 16 | pub type G1Affine = bls12::G1Affine>; 17 | pub type G1Projective = bls12::G1Projective>; 18 | 19 | #[derive(Clone, Copy)] 20 | pub struct Config(PhantomData H>); 21 | 22 | impl CurveConfig for Config { 23 | type BaseField = ::BaseField; 24 | type ScalarField = ::ScalarField; 25 | 26 | const COFACTOR: &'static [u64] = ::COFACTOR; 27 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 28 | } 29 | 30 | pub type G1SWAffine = SWAffine>; 31 | pub type G1SWProjective = SWProjective>; 32 | pub type G1TEAffine = TEAffine>; 33 | pub type G1TEProjective = TEProjective>; 34 | 35 | impl SWCurveConfig for Config { 36 | const COEFF_A: Self::BaseField = ::COEFF_A; 37 | const COEFF_B: Self::BaseField = ::COEFF_B; 38 | 39 | const GENERATOR: G1SWAffine = G1SWAffine::::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); 40 | 41 | /// Multi scalar multiplication jumping into the user-defined `msm_g1` hook. 42 | #[inline(always)] 43 | fn msm( 44 | bases: &[G1SWAffine], 45 | scalars: &[Self::ScalarField], 46 | ) -> Result, usize> { 47 | if bases.len() != scalars.len() { 48 | return Err(bases.len().min(scalars.len())); 49 | } 50 | Ok(H::msm_g1(bases, scalars)) 51 | } 52 | 53 | /// Projective multiplication jumping into the user-defined `mul_projective_g1` hook. 54 | #[inline(always)] 55 | fn mul_projective(base: &G1SWProjective, scalar: &[u64]) -> G1SWProjective { 56 | H::mul_projective_g1(base, scalar) 57 | } 58 | 59 | /// Affine multiplication jumping into the user-defined `mul_projective_g1` hook. 60 | #[inline(always)] 61 | fn mul_affine(base: &G1SWAffine, scalar: &[u64]) -> G1SWProjective { 62 | ::mul_projective(&(*base).into(), scalar) 63 | } 64 | 65 | #[inline(always)] 66 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 67 | ::mul_by_a(elem) 68 | } 69 | 70 | #[inline(always)] 71 | fn is_in_correct_subgroup_assuming_on_curve(item: &G1SWAffine) -> bool { 72 | if Self::cofactor_is_one() { 73 | true 74 | } else { 75 | // Workaround for: https://github.com/arkworks-rs/algebra/issues/948 76 | use ark_ff::Field; 77 | use ark_std::Zero; 78 | let char = Self::ScalarField::characteristic(); 79 | let l1 = [0, 0, char[2], char[3]]; 80 | let l2 = [char[0], char[1], 0, 0]; 81 | (::mul_affine(item, &l1) 82 | + ::mul_affine(item, &l2)) 83 | .is_zero() 84 | } 85 | } 86 | } 87 | 88 | impl TECurveConfig for Config { 89 | const COEFF_A: Self::BaseField = ::COEFF_A; 90 | const COEFF_D: Self::BaseField = ::COEFF_D; 91 | 92 | const GENERATOR: G1TEAffine = G1TEAffine::::new_unchecked(TE_GENERATOR_X, TE_GENERATOR_Y); 93 | 94 | type MontCurveConfig = Self; 95 | 96 | #[inline(always)] 97 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 98 | ::mul_by_a(elem) 99 | } 100 | } 101 | 102 | impl MontCurveConfig for Config { 103 | const COEFF_A: Self::BaseField = ::COEFF_A; 104 | const COEFF_B: Self::BaseField = ::COEFF_B; 105 | 106 | type TECurveConfig = Self; 107 | } 108 | -------------------------------------------------------------------------------- /test-utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Implementations for test hooks. 2 | //! 3 | //! We just safely transmute from Arkworks-Ext types to Arkworks upstream types by 4 | //! encoding and deconding and jump into the *Arkworks* upstream methods. 5 | 6 | #![cfg_attr(not(feature = "std"), no_std)] 7 | 8 | use ark_ec::{ 9 | pairing::{MillerLoopOutput, Pairing}, 10 | short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, 11 | twisted_edwards::{Affine as TEAffine, Projective as TEProjective, TECurveConfig}, 12 | CurveConfig, VariableBaseMSM, 13 | }; 14 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 15 | use ark_std::vec::Vec; 16 | 17 | trait TryTransmute { 18 | fn try_transmute(self) -> Result; 19 | } 20 | 21 | impl TryTransmute for T { 22 | fn try_transmute(self) -> Result { 23 | let mut buf = Vec::new(); 24 | self.serialize_uncompressed(&mut buf).map_err(|_| ())?; 25 | U::deserialize_uncompressed_unchecked(&mut &buf[..]).map_err(|_| ()) 26 | } 27 | } 28 | 29 | macro_rules! default_on_fail { 30 | ($($body:tt)*) => { 31 | let fallible = || { 32 | $($body)* 33 | }; 34 | fallible().unwrap_or_default() 35 | }; 36 | } 37 | 38 | /// On any error returns `Pairing::TargetField::default()`. 39 | pub fn multi_miller_loop_generic( 40 | g1: impl Iterator, 41 | g2: impl Iterator, 42 | ) -> ExtPairing::TargetField { 43 | default_on_fail! { 44 | let g1: Vec = g1.collect::>().try_transmute()?; 45 | let g2: Vec = g2.collect::>().try_transmute()?; 46 | let res = ArkPairing::multi_miller_loop(g1, g2).0; 47 | res.try_transmute() 48 | } 49 | } 50 | 51 | /// On any error returns `Pairing::TargetField::default()`. 52 | pub fn final_exponentiation_generic( 53 | target: ExtPairing::TargetField, 54 | ) -> ExtPairing::TargetField { 55 | default_on_fail! { 56 | let target: ArkPairing::TargetField = target.try_transmute()?; 57 | let res = ArkPairing::final_exponentiation(MillerLoopOutput(target)).ok_or(())?; 58 | res.try_transmute() 59 | } 60 | } 61 | 62 | /// On any error returns `SWProjective::default()`. 63 | pub fn msm_sw_generic( 64 | bases: &[SWAffine], 65 | scalars: &[ExtCurve::ScalarField], 66 | ) -> SWProjective { 67 | default_on_fail! { 68 | let bases: Vec> = bases.try_transmute()?; 69 | let scalars: Vec = scalars.try_transmute()?; 70 | let res = 71 | as VariableBaseMSM>::msm(&bases, &scalars).map_err(|_| ())?; 72 | res.try_transmute() 73 | } 74 | } 75 | 76 | pub fn msm_te_generic( 77 | bases: &[TEAffine], 78 | scalars: &[ExtConfig::ScalarField], 79 | ) -> TEProjective { 80 | default_on_fail! { 81 | let bases: Vec> = bases.try_transmute()?; 82 | let scalars: Vec<::ScalarField> = scalars.try_transmute()?; 83 | let res = 84 | as VariableBaseMSM>::msm(&bases, &scalars).map_err(|_| ())?; 85 | res.try_transmute() 86 | } 87 | } 88 | 89 | /// On any error returns `SWProjective::default()`. 90 | pub fn mul_projective_sw_generic( 91 | base: &SWProjective, 92 | scalar: &[u64], 93 | ) -> SWProjective { 94 | default_on_fail! { 95 | let base: SWProjective = base.try_transmute()?; 96 | let res = ::mul_projective(&base, scalar); 97 | res.try_transmute() 98 | } 99 | } 100 | 101 | /// On any error returns `TEProjective::default()`. 102 | pub fn mul_projective_te_generic( 103 | base: &TEProjective, 104 | scalar: &[u64], 105 | ) -> TEProjective { 106 | default_on_fail! { 107 | let base: TEProjective = base.try_transmute()?; 108 | let res = ::mul_projective(&base, scalar); 109 | res.try_transmute() 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /curves/ed_on_bls12_381_bandersnatch/src/curves/mod.rs: -------------------------------------------------------------------------------- 1 | use ark_ed_on_bls12_381_bandersnatch::{ 2 | BandersnatchConfig as ArkConfig, SW_GENERATOR_X, SW_GENERATOR_Y, TE_GENERATOR_X, TE_GENERATOR_Y, 3 | }; 4 | use ark_models_ext::{ 5 | models::CurveConfig, 6 | short_weierstrass::{self, SWCurveConfig}, 7 | twisted_edwards::{self, MontCurveConfig, TECurveConfig}, 8 | }; 9 | use ark_std::marker::PhantomData; 10 | 11 | #[cfg(test)] 12 | mod tests; 13 | 14 | pub type EdwardsAffine = twisted_edwards::Affine>; 15 | pub type EdwardsProjective = twisted_edwards::Projective>; 16 | 17 | pub type SWAffine = short_weierstrass::Affine>; 18 | pub type SWProjective = short_weierstrass::Projective>; 19 | 20 | #[derive(Clone, Copy)] 21 | pub struct BandersnatchConfig(PhantomData H>); 22 | 23 | pub type EdwardsConfig = BandersnatchConfig; 24 | pub type SWConfig = BandersnatchConfig; 25 | 26 | /// Hooks for *Ed-on-BLS12-377-Bandernatch*. 27 | pub trait CurveHooks: 'static + Sized { 28 | /// Twisted Edwards multi scalar multiplication. 29 | fn msm_te( 30 | bases: &[EdwardsAffine], 31 | scalars: &[ as CurveConfig>::ScalarField], 32 | ) -> EdwardsProjective; 33 | 34 | /// Twisted Edwards projective multiplication. 35 | fn mul_projective_te(base: &EdwardsProjective, scalar: &[u64]) 36 | -> EdwardsProjective; 37 | 38 | /// Short Weierstrass multi scalar multiplication. 39 | fn msm_sw( 40 | bases: &[SWAffine], 41 | scalars: &[ as CurveConfig>::ScalarField], 42 | ) -> SWProjective; 43 | 44 | /// Short Weierstrass projective multiplication. 45 | fn mul_projective_sw(base: &SWProjective, scalar: &[u64]) -> SWProjective; 46 | } 47 | 48 | impl CurveConfig for BandersnatchConfig { 49 | const COFACTOR: &'static [u64] = ::COFACTOR; 50 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 51 | 52 | type BaseField = ::BaseField; 53 | type ScalarField = ::ScalarField; 54 | } 55 | 56 | impl TECurveConfig for BandersnatchConfig { 57 | const COEFF_A: Self::BaseField = ::COEFF_A; 58 | const COEFF_D: Self::BaseField = ::COEFF_D; 59 | 60 | const GENERATOR: EdwardsAffine = 61 | EdwardsAffine::::new_unchecked(TE_GENERATOR_X, TE_GENERATOR_Y); 62 | 63 | type MontCurveConfig = Self; 64 | 65 | /// Multi scalar multiplication jumping into the user-defined `te_msm` hook. 66 | #[inline(always)] 67 | fn msm( 68 | bases: &[EdwardsAffine], 69 | scalars: &[Self::ScalarField], 70 | ) -> Result, usize> { 71 | if bases.len() != scalars.len() { 72 | return Err(bases.len().min(scalars.len())); 73 | } 74 | Ok(H::msm_te(bases, scalars)) 75 | } 76 | 77 | /// Projective multiplication jumping into the user-defined `te_mul_projective` hook. 78 | #[inline(always)] 79 | fn mul_projective(base: &EdwardsProjective, scalar: &[u64]) -> EdwardsProjective { 80 | H::mul_projective_te(base, scalar) 81 | } 82 | 83 | /// Affine multiplication jumping into the user-defined `te_mul_projective` hook. 84 | #[inline(always)] 85 | fn mul_affine(base: &EdwardsAffine, scalar: &[u64]) -> EdwardsProjective { 86 | ::mul_projective(&(*base).into(), scalar) 87 | } 88 | 89 | #[inline(always)] 90 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 91 | ::mul_by_a(elem) 92 | } 93 | } 94 | 95 | impl SWCurveConfig for BandersnatchConfig { 96 | const COEFF_A: Self::BaseField = ::COEFF_A; 97 | const COEFF_B: Self::BaseField = ::COEFF_B; 98 | 99 | const GENERATOR: SWAffine = SWAffine::::new_unchecked(SW_GENERATOR_X, SW_GENERATOR_Y); 100 | 101 | /// Multi scalar multiplication jumping into the user-defined `sw_msm` hook. 102 | /// 103 | /// On any internal error returns `Err(0)`. 104 | #[inline(always)] 105 | fn msm(bases: &[SWAffine], scalars: &[Self::ScalarField]) -> Result, usize> { 106 | if bases.len() != scalars.len() { 107 | return Err(bases.len().min(scalars.len())); 108 | } 109 | Ok(H::msm_sw(bases, scalars)) 110 | } 111 | 112 | /// Projective multiplication jumping into the user-defined `sw_mul_projective` hook. 113 | /// 114 | /// On any internal error returns `Projective::zero()`. 115 | #[inline(always)] 116 | fn mul_projective(base: &SWProjective, scalar: &[u64]) -> SWProjective { 117 | H::mul_projective_sw(base, scalar) 118 | } 119 | 120 | /// Affine multiplication jumping into the user-defined `sw_mul_projective` hook. 121 | #[inline(always)] 122 | fn mul_affine(base: &SWAffine, scalar: &[u64]) -> SWProjective { 123 | ::mul_projective(&(*base).into(), scalar) 124 | } 125 | } 126 | 127 | impl MontCurveConfig for BandersnatchConfig { 128 | const COEFF_A: Self::BaseField = ::COEFF_A; 129 | const COEFF_B: Self::BaseField = ::COEFF_B; 130 | 131 | type TECurveConfig = Self; 132 | } 133 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/g1.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | util::{ 3 | read_g1_compressed, read_g1_uncompressed, serialize_fq, EncodingFlags, G1_SERIALIZED_SIZE, 4 | }, 5 | CurveHooks, 6 | }; 7 | 8 | use ark_bls12_381::g1::Config as ArkConfig; 9 | use ark_ff::PrimeField; 10 | use ark_models_ext::{ 11 | bls12, 12 | bls12::Bls12Config, 13 | short_weierstrass::{Affine, SWCurveConfig}, 14 | AffineRepr, CurveConfig, PrimeGroup, 15 | }; 16 | use ark_serialize::{Compress, SerializationError, Validate}; 17 | use ark_std::{ 18 | io::{Read, Write}, 19 | marker::PhantomData, 20 | ops::Neg, 21 | One, 22 | }; 23 | 24 | pub use ark_bls12_381::g1::{BETA, G1_GENERATOR_X, G1_GENERATOR_Y}; 25 | 26 | pub type G1Affine = bls12::G1Affine>; 27 | pub type G1Projective = bls12::G1Projective>; 28 | 29 | #[derive(Clone, Copy)] 30 | pub struct Config(PhantomData H>); 31 | 32 | impl CurveConfig for Config { 33 | const COFACTOR: &'static [u64] = ::COFACTOR; 34 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 35 | 36 | type BaseField = ::BaseField; 37 | type ScalarField = ::ScalarField; 38 | } 39 | 40 | impl SWCurveConfig for Config { 41 | const COEFF_A: Self::BaseField = ::COEFF_A; 42 | const COEFF_B: Self::BaseField = ::COEFF_B; 43 | 44 | const GENERATOR: G1Affine = G1Affine::::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); 45 | 46 | /// Multi scalar multiplication jumping into the user-defined `msm_g1` hook. 47 | #[inline(always)] 48 | fn msm(bases: &[G1Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 49 | if bases.len() != scalars.len() { 50 | return Err(bases.len().min(scalars.len())); 51 | } 52 | Ok(H::msm_g1(bases, scalars)) 53 | } 54 | 55 | /// Projective multiplication jumping into the user-defined `mul_projective_g1` hook. 56 | #[inline(always)] 57 | fn mul_projective(base: &G1Projective, scalar: &[u64]) -> G1Projective { 58 | H::mul_projective_g1(base, scalar) 59 | } 60 | 61 | /// Affine multiplication jumping into the user-defined `mul_projective` hook. 62 | #[inline(always)] 63 | fn mul_affine(base: &G1Affine, scalar: &[u64]) -> G1Projective { 64 | Self::mul_projective(&(*base).into(), scalar) 65 | } 66 | 67 | #[inline(always)] 68 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 69 | ::mul_by_a(elem) 70 | } 71 | 72 | // Verbatim copy of upstream implementation. 73 | // 74 | // Can't call it directly because of different `Affine` configuration. 75 | #[inline(always)] 76 | fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool { 77 | let x_times_p = p.mul_bigint(crate::Config::::X); 78 | if x_times_p.eq(p) && !p.infinity { 79 | return false; 80 | } 81 | 82 | let minus_x_squared_times_p = x_times_p.mul_bigint(crate::Config::::X).neg(); 83 | let endomorphism_p = endomorphism(p); 84 | minus_x_squared_times_p.eq(&endomorphism_p) 85 | } 86 | 87 | // Verbatim copy of upstream implementation. 88 | // 89 | // Can't call it directly because of different `Affine` configuration. 90 | #[inline(always)] 91 | fn clear_cofactor(p: &G1Affine) -> G1Affine { 92 | let h_eff = 93 | one_minus_x(crate::Config::::X_IS_NEGATIVE, crate::Config::::X).into_bigint(); 94 | Self::mul_affine(p, h_eff.as_ref()).into() 95 | } 96 | 97 | #[inline(always)] 98 | fn serialized_size(compress: Compress) -> usize { 99 | ::serialized_size(compress) 100 | } 101 | 102 | // Verbatim copy of upstream implementation. 103 | // 104 | // Can't call it directly because of different `Affine` configuration. 105 | fn serialize_with_mode( 106 | item: &G1Affine, 107 | mut writer: W, 108 | compress: Compress, 109 | ) -> Result<(), SerializationError> { 110 | let encoding = EncodingFlags { 111 | is_compressed: compress == Compress::Yes, 112 | is_infinity: item.is_zero(), 113 | is_lexographically_largest: item.y > -item.y, 114 | }; 115 | let mut p = *item; 116 | if encoding.is_infinity { 117 | p = Affine::::zero(); 118 | } 119 | // need to access the field struct `x` directly, otherwise we get None from xy() 120 | // method 121 | let x_bytes = serialize_fq(p.x); 122 | if encoding.is_compressed { 123 | let mut bytes: [u8; G1_SERIALIZED_SIZE] = x_bytes; 124 | 125 | encoding.encode_flags(&mut bytes); 126 | writer.write_all(&bytes)?; 127 | } else { 128 | let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE]; 129 | bytes[0..G1_SERIALIZED_SIZE].copy_from_slice(&x_bytes[..]); 130 | bytes[G1_SERIALIZED_SIZE..].copy_from_slice(&serialize_fq(p.y)[..]); 131 | 132 | encoding.encode_flags(&mut bytes); 133 | writer.write_all(&bytes)?; 134 | }; 135 | Ok(()) 136 | } 137 | 138 | // Verbatim copy of upstream implementation. 139 | // 140 | // Can't call it directly because of different `Affine` configuration. 141 | fn deserialize_with_mode( 142 | mut reader: R, 143 | compress: Compress, 144 | validate: Validate, 145 | ) -> Result, SerializationError> { 146 | let p = if compress == Compress::Yes { 147 | read_g1_compressed(&mut reader)? 148 | } else { 149 | read_g1_uncompressed(&mut reader)? 150 | }; 151 | 152 | if validate == Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve() { 153 | return Err(SerializationError::InvalidData); 154 | } 155 | Ok(p) 156 | } 157 | } 158 | 159 | fn one_minus_x( 160 | x_is_negative: bool, 161 | x_value: &'static [u64], 162 | ) -> ::ScalarField { 163 | let x = ::ScalarField::from_sign_and_limbs(!x_is_negative, x_value); 164 | ::ScalarField::one() - x 165 | } 166 | 167 | pub fn endomorphism(p: &G1Affine) -> G1Affine { 168 | // Endomorphism of the points on the curve. 169 | // endomorphism_p(x,y) = (BETA * x, y) 170 | // where BETA is a non-trivial cubic root of unity in fq. 171 | let mut res = *p; 172 | res.x *= BETA; 173 | res 174 | } 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arkworks Extensions 2 | 3 | ## Overview 4 | 5 | This library extends [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra). 6 | 7 | We fork the popular elliptic curves `BLS12_381`, `BLS12_377`, `BW6_761`, 8 | `ED_ON_BLS12_381_BANDERSNATCH`, `Pallas`, `Vesta`, `SECP256K1` and `ED_ON_BLS12_377` in a way which allows 9 | delegating some of the most computationally expensive operations to some user 10 | defined hooks. 11 | 12 | We also provide forks of the models `BW6` and `BLS12` to avoid the point 13 | preparation before the hooks calls during pairing operations. Therefore, we 14 | redefine the elliptic curve sub-groups `G2` for both models as thin wrappers 15 | around the affine points and move the point preparation procedure to the 16 | user defined hook. 17 | 18 | ## Usage 19 | 20 | The following usage example is extracted from the hooks provided by 21 | [substrate-curves](https://github.com/paritytech/substrate-curves) project. 22 | 23 | The project provides a set of ready to use `CurveHooks` implementations compatible with 24 | [Substrate](https://github.com/paritytech/polkadot-sdk/primitives/crypto/ec-utils) 25 | host functions to jump from *wasm32* computational domain into the native host. 26 | 27 | The motivation is: 28 | - native target is typically more efficient that *wasm32*. 29 | - *wasm32* is single thread while in the native target we can hopefully leverage 30 | the Arkworks `parallel` feature. 31 | 32 | Note that Substrate elliptic curves host functions take and return raw byte arrays 33 | representing SCALE encoded values. 34 | 35 | ### BLS12-377 36 | 37 | ```rust 38 | use ark_bls12_377_ext::CurveHooks; 39 | use ark_ec::{pairing::Pairing, CurveConfig} 40 | use ark_scale::{ 41 | ark_serialize::{Compress, Validate}, 42 | scale::{Decode, Encode}, 43 | }; 44 | use sp_crypto_ec_utils::bls12_377_ops; 45 | 46 | 47 | const SCALE_USAGE: u8 = ark_scale::make_usage(Compress::No, Validate::No); 48 | type ArkScale = ark_scale::ArkScale;o 49 | type ArkScaleProjective = ark_scale::hazmat::ArkScaleProjective; 50 | 51 | #[derive(Copy, Clone)] 52 | pub struct HostHooks; 53 | 54 | type Bls12_377 = ark_bls12_377_ext::Bls12_377; 55 | type G1Affine = ark_bls12_377_ext::g1::G1Affine; 56 | type G1Config = ark_bls12_377_ext::g1::Config; 57 | type G2Affine = ark_bls12_377_ext::g2::G2Affine; 58 | type G2Config = ark_bls12_377_ext::g2::Config; 59 | 60 | 61 | impl CurveHooks for HostHooks { 62 | fn bls12_377_multi_miller_loop( 63 | g1: impl Iterator::G1Prepared>, 64 | g2: impl Iterator::G2Prepared>, 65 | ) -> Result<::TargetField, ()> { 66 | // Encode to SCALE to call into Substrate HF 67 | let g1 = ArkScale::from(g1.collect::>()).encode(); 68 | let g2 = ArkScale::from(g2.collect::>()).encode(); 69 | // Call into native host function 70 | let res = bls12_377_ops::bls12_377_multi_miller_loop(g1, g2).unwrap_or_default(); 71 | // Decode from SCALE 72 | let res = ArkScale::<::TargetField>::decode(&mut res.as_slice()); 73 | res.map(|v| v.0).map_err(|_| ()) 74 | } 75 | 76 | fn bls12_377_final_exponentiation( 77 | target: ::TargetField, 78 | ) -> Result<::TargetField, ()> { 79 | let target = ArkScale::from(target).encode(); 80 | let res = bls12_377_ops::bls12_377_final_exponentiation(target).unwrap_or_default(); 81 | let res = ArkScale::<::TargetField>::decode(&mut res.as_slice()); 82 | res.map(|v| v.0).map_err(|_| ()) 83 | } 84 | 85 | fn bls12_377_msm_g1( 86 | bases: &[G1Affine], 87 | scalars: &[::ScalarField], 88 | ) -> Result { 89 | let bases = ArkScale::from(bases).encode(); 90 | let scalars = ArkScale::from(scalars).encode(); 91 | let res = bls12_377_ops::bls12_377_msm_g1(bases, scalars).unwrap_or_default(); 92 | let res = ArkScaleProjective::::decode(&mut res.as_slice()); 93 | res.map(|v| v.0).map_err(|_| ()) 94 | } 95 | 96 | fn bls12_377_msm_g2( 97 | bases: &[G2Affine], 98 | scalars: &[::ScalarField], 99 | ) -> Result { 100 | let bases = ArkScale::from(bases).encode(); 101 | let scalars = ArkScale::from(scalars).encode(); 102 | let res = bls12_377_ops::bls12_377_msm_g2(bases, scalars).unwrap_or_default(); 103 | let res = ArkScaleProjective::::decode(&mut res.as_slice()); 104 | res.map(|v| v.0).map_err(|_| ()) 105 | } 106 | 107 | fn bls12_377_mul_projective_g1( 108 | base: &G1Projective, 109 | scalar: &[u64], 110 | ) -> Result { 111 | let base = ArkScaleProjective::from(base).encode(); 112 | let scalar = ArkScale::from(scalar).encode(); 113 | let res = bls12_377_ops::bls12_377_mul_projective_g1(base, scalar).unwrap_or_default(); 114 | let res = ArkScaleProjective::::decode(&mut res.as_slice()); 115 | res.map(|v| v.0).map_err(|_| ()) 116 | } 117 | 118 | fn bls12_377_mul_projective_g2( 119 | base: &G2Projective, 120 | scalar: &[u64], 121 | ) -> Result { 122 | let base = ArkScaleProjective::from(base).encode(); 123 | let scalar = ArkScale::from(scalar).encode(); 124 | let res = bls12_377_ops::bls12_377_mul_projective_g2(base, scalar).unwrap_or_default(); 125 | let res = ArkScaleProjective::::decode(&mut res.as_slice()); 126 | res.map(|v| v.0).map_err(|_| ()) 127 | }o 128 | } 129 | ``` 130 | 131 | For more working examples refer to [Ark Substrate](https://github.com/davxy/ark-substrate-examples). 132 | 133 | 134 | ## ⚠️ Known Limitations ⚠️ 135 | 136 | Be aware that, while in the hook context, any usage of functions which may 137 | re-enter into the same hook with the same value, may cause an infinite loop. 138 | 139 | We are aware of hooks re-entrancy issues when using **point checked 140 | deserialization** in projective multiplication hooks. 141 | 142 | In particular, if you serialize and deserialize (**with point checking**) the 143 | input point in one of the projective multiplication hooks then we end up 144 | re-entering the multiplication hook with the same value as a consequence of the 145 | internally performed check. 146 | 147 | The following invocation flow applies: 148 | 149 | 1. [Validation of deserialized value](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/mod.rs#L145-L147). 150 | 2. [Check if point is in the correct subgroup](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/affine.rs#L321). 151 | 3. [Jump into the `TECurveConfig` for the check](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/affine.rs#L159). 152 | 4. Calls the "custom" (defined by this crate) implementation of `mul_affine` which calls `mul_projective`. 153 | 5. Goto 1 154 | 155 | So pay special attention to the actions in your `CurveHooks` implementations. 156 | 157 | If you encounter any other way to trigger the open, please file an issue. 158 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/util.rs: -------------------------------------------------------------------------------- 1 | use ark_ff::{BigInteger384, PrimeField}; 2 | use ark_models_ext::{short_weierstrass::Affine, AffineRepr}; 3 | use ark_serialize::SerializationError; 4 | use ark_std::{io::Read, vec::Vec}; 5 | 6 | use crate::CurveHooks; 7 | use crate::{g1::Config as G1Config, g2::Config as G2Config}; 8 | use ark_bls12_381::{fq::Fq, fq2::Fq2}; 9 | 10 | pub const G1_SERIALIZED_SIZE: usize = 48; 11 | pub const G2_SERIALIZED_SIZE: usize = 96; 12 | 13 | pub struct EncodingFlags { 14 | pub is_compressed: bool, 15 | pub is_infinity: bool, 16 | pub is_lexographically_largest: bool, 17 | } 18 | 19 | impl EncodingFlags { 20 | pub fn get_flags(bytes: Vec) -> Self { 21 | let compression_flag_set = (bytes[0] >> 7) & 1; 22 | let infinity_flag_set = (bytes[0] >> 6) & 1; 23 | let sort_flag_set = (bytes[0] >> 5) & 1; 24 | 25 | Self { 26 | is_compressed: compression_flag_set == 1, 27 | is_infinity: infinity_flag_set == 1, 28 | is_lexographically_largest: sort_flag_set == 1, 29 | } 30 | } 31 | pub fn encode_flags(&self, bytes: &mut [u8]) { 32 | if self.is_compressed { 33 | bytes[0] |= 1 << 7; 34 | } 35 | 36 | if self.is_infinity { 37 | bytes[0] |= 1 << 6; 38 | } 39 | 40 | if self.is_compressed && !self.is_infinity && self.is_lexographically_largest { 41 | bytes[0] |= 1 << 5; 42 | } 43 | } 44 | } 45 | 46 | pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option { 47 | let mut tmp = BigInteger384::new([0, 0, 0, 0, 0, 0]); 48 | 49 | // Note: The following unwraps are if the compiler cannot convert 50 | // the byte slice into [u8;8], we know this is infallible since we 51 | // are providing the indices at compile time and bytes has a fixed size 52 | tmp.0[5] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[0..8].to_vec()).unwrap()); 53 | tmp.0[4] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[8..16].to_vec()).unwrap()); 54 | tmp.0[3] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[16..24].to_vec()).unwrap()); 55 | tmp.0[2] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[24..32].to_vec()).unwrap()); 56 | tmp.0[1] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[32..40].to_vec()).unwrap()); 57 | tmp.0[0] = u64::from_be_bytes(<[u8; 8]>::try_from(bytes[40..48].to_vec()).unwrap()); 58 | 59 | Fq::from_bigint(tmp) 60 | } 61 | 62 | pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] { 63 | let mut result = [0u8; 48]; 64 | 65 | let rep = field.into_bigint(); 66 | 67 | result[0..8].copy_from_slice(&rep.0[5].to_be_bytes()); 68 | result[8..16].copy_from_slice(&rep.0[4].to_be_bytes()); 69 | result[16..24].copy_from_slice(&rep.0[3].to_be_bytes()); 70 | result[24..32].copy_from_slice(&rep.0[2].to_be_bytes()); 71 | result[32..40].copy_from_slice(&rep.0[1].to_be_bytes()); 72 | result[40..48].copy_from_slice(&rep.0[0].to_be_bytes()); 73 | 74 | result 75 | } 76 | 77 | pub(crate) fn read_fq_with_offset( 78 | bytes: Vec, 79 | offset: usize, 80 | mask: bool, 81 | ) -> Result { 82 | let mut tmp = [0; G1_SERIALIZED_SIZE]; 83 | // read `G1_SERIALIZED_SIZE` bytes 84 | tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]); 85 | 86 | if mask { 87 | // Mask away the flag bits 88 | tmp[0] &= 0b0001_1111; 89 | } 90 | deserialize_fq(tmp).ok_or(SerializationError::InvalidData) 91 | } 92 | 93 | pub(crate) fn read_g1_compressed( 94 | mut reader: R, 95 | ) -> Result>, SerializationError> { 96 | let mut bytes = [0u8; G1_SERIALIZED_SIZE]; 97 | reader 98 | .read_exact(&mut bytes) 99 | .ok() 100 | .ok_or(SerializationError::InvalidData)?; 101 | 102 | // Obtain the three flags from the start of the byte sequence 103 | let flags = EncodingFlags::get_flags(bytes[..].to_vec()); 104 | 105 | // we expect to be deserializing a compressed point 106 | if !flags.is_compressed { 107 | return Err(SerializationError::UnexpectedFlags); 108 | } 109 | 110 | if flags.is_infinity { 111 | return Ok(Affine::>::zero()); 112 | } 113 | 114 | // Attempt to obtain the x-coordinate 115 | let x = read_fq_with_offset(bytes.to_vec(), 0, true)?; 116 | 117 | let p = Affine::>::get_point_from_x_unchecked(x, flags.is_lexographically_largest) 118 | .ok_or(SerializationError::InvalidData)?; 119 | 120 | Ok(p) 121 | } 122 | 123 | pub(crate) fn read_g1_uncompressed( 124 | mut reader: R, 125 | ) -> Result>, SerializationError> { 126 | let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE]; 127 | reader 128 | .read_exact(&mut bytes) 129 | .map_err(|_| SerializationError::InvalidData)?; 130 | 131 | // Obtain the three flags from the start of the byte sequence 132 | let flags = EncodingFlags::get_flags(bytes[..].to_vec()); 133 | 134 | // we expect to be deserializing an uncompressed point 135 | if flags.is_compressed { 136 | return Err(SerializationError::UnexpectedFlags); 137 | } 138 | 139 | if flags.is_infinity { 140 | return Ok(Affine::>::zero()); 141 | } 142 | 143 | // Attempt to obtain the x-coordinate 144 | let x = read_fq_with_offset(bytes.to_vec(), 0, true)?; 145 | // Attempt to obtain the y-coordinate 146 | let y = read_fq_with_offset(bytes.to_vec(), 1, false)?; 147 | 148 | let p = Affine::>::new_unchecked(x, y); 149 | 150 | Ok(p) 151 | } 152 | 153 | pub(crate) fn read_g2_compressed( 154 | mut reader: R, 155 | ) -> Result>, SerializationError> { 156 | let mut bytes = [0u8; G2_SERIALIZED_SIZE]; 157 | reader 158 | .read_exact(&mut bytes) 159 | .map_err(|_| SerializationError::InvalidData)?; 160 | 161 | // Obtain the three flags from the start of the byte sequence 162 | let flags = EncodingFlags::get_flags(bytes.to_vec()); 163 | 164 | // we expect to be deserializing a compressed point 165 | if !flags.is_compressed { 166 | return Err(SerializationError::UnexpectedFlags); 167 | } 168 | 169 | if flags.is_infinity { 170 | return Ok(Affine::>::zero()); 171 | } 172 | 173 | // Attempt to obtain the x-coordinate 174 | let xc1 = read_fq_with_offset(bytes.to_vec(), 0, true)?; 175 | let xc0 = read_fq_with_offset(bytes.to_vec(), 1, false)?; 176 | 177 | let x = Fq2::new(xc0, xc1); 178 | 179 | let p = Affine::>::get_point_from_x_unchecked(x, flags.is_lexographically_largest) 180 | .ok_or(SerializationError::InvalidData)?; 181 | 182 | Ok(p) 183 | } 184 | 185 | pub(crate) fn read_g2_uncompressed( 186 | mut reader: R, 187 | ) -> Result>, SerializationError> { 188 | let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE]; 189 | reader 190 | .read_exact(&mut bytes) 191 | .map_err(|_| SerializationError::InvalidData)?; 192 | 193 | // Obtain the three flags from the start of the byte sequence 194 | let flags = EncodingFlags::get_flags(bytes.to_vec()); 195 | 196 | // we expect to be deserializing an uncompressed point 197 | if flags.is_compressed { 198 | return Err(SerializationError::UnexpectedFlags); 199 | } 200 | 201 | if flags.is_infinity { 202 | return Ok(Affine::>::zero()); 203 | } 204 | 205 | // Attempt to obtain the x-coordinate 206 | let xc1 = read_fq_with_offset(bytes.to_vec(), 0, true)?; 207 | let xc0 = read_fq_with_offset(bytes.to_vec(), 1, false)?; 208 | let x = Fq2::new(xc0, xc1); 209 | 210 | // Attempt to obtain the y-coordinate 211 | let yc1 = read_fq_with_offset(bytes.to_vec(), 2, false)?; 212 | let yc0 = read_fq_with_offset(bytes.to_vec(), 3, false)?; 213 | let y = Fq2::new(yc0, yc1); 214 | 215 | let p = Affine::>::new_unchecked(x, y); 216 | 217 | Ok(p) 218 | } 219 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/tests/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::{fq::Fq, fq2::Fq2, fr::Fr, CurveHooks}; 2 | 3 | use ark_algebra_test_templates::*; 4 | use ark_bls12_381::{ 5 | g1::Config as ArkG1Config, g2::Config as ArkG2Config, Bls12_381 as ArkBls12_381, 6 | }; 7 | use ark_ff::{fields::Field, One, Zero}; 8 | use ark_models_ext::{ 9 | pairing::{Pairing, PairingOutput}, 10 | short_weierstrass::SWCurveConfig, 11 | AffineRepr, CurveConfig, CurveGroup, PrimeGroup, 12 | }; 13 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate}; 14 | use ark_std::{rand::Rng, test_rng, vec, UniformRand}; 15 | 16 | struct TestHooks; 17 | 18 | type Bls12_381 = crate::Bls12_381; 19 | type G1Projective = crate::G1Projective; 20 | type G2Projective = crate::G2Projective; 21 | type G1Affine = crate::G1Affine; 22 | type G2Affine = crate::G2Affine; 23 | type G1Config = crate::g1::Config; 24 | type G2Config = crate::g2::Config; 25 | 26 | impl CurveHooks for TestHooks { 27 | fn multi_miller_loop( 28 | g1: impl Iterator::G1Prepared>, 29 | g2: impl Iterator::G2Prepared>, 30 | ) -> ::TargetField { 31 | test_utils::multi_miller_loop_generic::(g1, g2) 32 | } 33 | 34 | fn final_exponentiation( 35 | target: ::TargetField, 36 | ) -> ::TargetField { 37 | test_utils::final_exponentiation_generic::(target) 38 | } 39 | 40 | fn msm_g1( 41 | bases: &[G1Affine], 42 | scalars: &[::ScalarField], 43 | ) -> G1Projective { 44 | test_utils::msm_sw_generic::(bases, scalars) 45 | } 46 | 47 | fn msm_g2( 48 | bases: &[G2Affine], 49 | scalars: &[::ScalarField], 50 | ) -> G2Projective { 51 | test_utils::msm_sw_generic::(bases, scalars) 52 | } 53 | 54 | fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective { 55 | test_utils::mul_projective_sw_generic::(base, scalar) 56 | } 57 | 58 | fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective { 59 | test_utils::mul_projective_sw_generic::(base, scalar) 60 | } 61 | } 62 | 63 | test_group!(g1; G1Projective; sw); 64 | test_group!(g2; G2Projective; sw); 65 | test_group!(pairing_output; PairingOutput; msm); 66 | test_pairing!(ark_pairing; crate::Bls12_381); 67 | 68 | #[test] 69 | fn test_g1_endomorphism_beta() { 70 | assert!(crate::g1::BETA.pow([3u64]).is_one()); 71 | } 72 | 73 | #[test] 74 | fn test_g1_subgroup_membership_via_endomorphism() { 75 | let mut rng = test_rng(); 76 | let generator = G1Projective::rand(&mut rng).into_affine(); 77 | assert!(generator.is_in_correct_subgroup_assuming_on_curve()); 78 | } 79 | 80 | #[test] 81 | fn test_g1_subgroup_non_membership_via_endomorphism() { 82 | let mut rng = test_rng(); 83 | loop { 84 | let x = Fq::rand(&mut rng); 85 | let greatest = rng.gen(); 86 | if let Some(p) = G1Affine::get_point_from_x_unchecked(x, greatest) { 87 | // As internally the characteristic is loaded into an Fr instance scalar, 88 | // this is reduced modulo Fr order, thus we end up multiplying by zero. 89 | // to prevent this we split the characteristic scalar. 90 | let char = Fr::characteristic(); 91 | let l1 = [0, 0, char[2], char[3]]; 92 | let l2 = [char[0], char[1], 0, 0]; 93 | let v = p.mul_bigint(l1) + p.mul_bigint(l2); 94 | if !v.is_zero() { 95 | assert!(!p.is_in_correct_subgroup_assuming_on_curve()); 96 | return; 97 | } 98 | } 99 | } 100 | } 101 | 102 | #[test] 103 | fn test_g2_subgroup_membership_via_endomorphism() { 104 | let mut rng = test_rng(); 105 | let generator = G2Projective::rand(&mut rng).into_affine(); 106 | assert!(generator.is_in_correct_subgroup_assuming_on_curve()); 107 | } 108 | 109 | #[test] 110 | fn test_g2_subgroup_non_membership_via_endomorphism() { 111 | let mut rng = test_rng(); 112 | loop { 113 | let x = Fq2::rand(&mut rng); 114 | let greatest = rng.gen(); 115 | if let Some(p) = G2Affine::get_point_from_x_unchecked(x, greatest) { 116 | // As internally the characteristic is loaded into an Fr instance scalar, 117 | // this is reduced modulo Fr order, thus we end up multiplying by zero. 118 | // to prevent this we split the characteristic scalar. 119 | let char = Fr::characteristic(); 120 | let l1 = [0, 0, char[2], char[3]]; 121 | let l2 = [char[0], char[1], 0, 0]; 122 | let v = p.mul_bigint(l1) + p.mul_bigint(l2); 123 | if !v.is_zero() { 124 | assert!(!p.is_in_correct_subgroup_assuming_on_curve()); 125 | return; 126 | } 127 | } 128 | } 129 | } 130 | 131 | // Test vectors and macro adapted from https://github.com/zkcrypto/bls12_381/blob/e224ad4ea1babfc582ccd751c2bf128611d10936/src/tests/mod.rs 132 | macro_rules! test_vectors { 133 | ($projective:ident, $affine:ident, $compress:expr, $expected:ident) => { 134 | let mut e = $projective::zero(); 135 | 136 | let mut v = vec![]; 137 | { 138 | let mut expected = $expected; 139 | for _ in 0..1000 { 140 | let e_affine = $affine::from(e); 141 | let mut serialized = vec![0u8; e.serialized_size($compress)]; 142 | e_affine 143 | .serialize_with_mode(serialized.as_mut_slice(), $compress) 144 | .unwrap(); 145 | v.extend_from_slice(&serialized[..]); 146 | 147 | let mut decoded = serialized; 148 | let len_of_encoding = decoded.len(); 149 | (&mut decoded[..]).copy_from_slice(&expected[0..len_of_encoding]); 150 | expected = &expected[len_of_encoding..]; 151 | let decoded = 152 | $affine::deserialize_with_mode(&decoded[..], $compress, Validate::Yes).unwrap(); 153 | assert_eq!(e_affine, decoded); 154 | 155 | e += &$projective::generator(); 156 | } 157 | } 158 | 159 | assert_eq!(&v[..], $expected); 160 | }; 161 | } 162 | 163 | #[test] 164 | fn g1_compressed_valid_test_vectors() { 165 | let bytes: &'static [u8] = include_bytes!("g1_compressed_valid_test_vectors.bin"); 166 | test_vectors!(G1Projective, G1Affine, Compress::Yes, bytes); 167 | } 168 | 169 | #[test] 170 | fn g1_uncompressed_valid_test_vectors() { 171 | let bytes: &'static [u8] = include_bytes!("g1_uncompressed_valid_test_vectors.bin"); 172 | test_vectors!(G1Projective, G1Affine, Compress::No, bytes); 173 | } 174 | 175 | #[test] 176 | fn g2_compressed_valid_test_vectors() { 177 | let bytes: &'static [u8] = include_bytes!("g2_compressed_valid_test_vectors.bin"); 178 | test_vectors!(G2Projective, G2Affine, Compress::Yes, bytes); 179 | } 180 | 181 | #[test] 182 | fn g2_uncompressed_valid_test_vectors() { 183 | let bytes: &'static [u8] = include_bytes!("g2_uncompressed_valid_test_vectors.bin"); 184 | test_vectors!(G2Projective, G2Affine, Compress::No, bytes); 185 | } 186 | 187 | #[test] 188 | fn test_cofactor_clearing_g1() { 189 | let sample_unchecked = || { 190 | let mut rng = test_rng(); 191 | loop { 192 | let x = Fq::rand(&mut rng); 193 | let greatest = rng.gen(); 194 | 195 | if let Some(p) = 196 | ark_ec::short_weierstrass::Affine::get_point_from_x_unchecked(x, greatest) 197 | { 198 | return p; 199 | } 200 | } 201 | }; 202 | const SAMPLES: usize = 100; 203 | for _ in 0..SAMPLES { 204 | let p: G1Affine = sample_unchecked(); 205 | let p = p.clear_cofactor(); 206 | assert!(p.is_on_curve()); 207 | assert!(p.is_in_correct_subgroup_assuming_on_curve()); 208 | } 209 | } 210 | 211 | #[test] 212 | fn test_cofactor_clearing_g2() { 213 | // Multiplying by h_eff and clearing the cofactor by the efficient 214 | // endomorphism-based method should yield the same result. 215 | let h_eff: &'static [u64] = &[ 216 | 0xe8020005aaa95551, 217 | 0x59894c0adebbf6b4, 218 | 0xe954cbc06689f6a3, 219 | 0x2ec0ec69d7477c1a, 220 | 0x6d82bf015d1212b0, 221 | 0x329c2f178731db95, 222 | 0x9986ff031508ffe1, 223 | 0x88e2a8e9145ad768, 224 | 0x584c6a0ea91b3528, 225 | 0xbc69f08f2ee75b3, 226 | ]; 227 | let mut rng = ark_std::test_rng(); 228 | const SAMPLES: usize = 10; 229 | for _ in 0..SAMPLES { 230 | let p = G2Affine::rand(&mut rng); 231 | let optimised = p.clear_cofactor().into_group(); 232 | let naive = crate::g2::Config::::mul_affine(&p, h_eff); 233 | assert_eq!(optimised, naive); 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /curves/bls12_381/src/curves/g2.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_381::{fq2::Fq2, g2::Config as ArkConfig, Fq}; 2 | use ark_ec::AdditiveGroup; 3 | use ark_ff::{Field, MontFp}; 4 | use ark_models_ext::{ 5 | bls12, bls12::Bls12Config, short_weierstrass::SWCurveConfig, AffineRepr, CurveConfig, 6 | CurveGroup, PrimeGroup, 7 | }; 8 | use ark_serialize::{Compress, SerializationError, Validate}; 9 | use ark_std::{ 10 | io::{Read, Write}, 11 | marker::PhantomData, 12 | ops::Neg, 13 | }; 14 | 15 | use crate::{ 16 | util::{ 17 | read_g2_compressed, read_g2_uncompressed, serialize_fq, EncodingFlags, G2_SERIALIZED_SIZE, 18 | }, 19 | CurveHooks, 20 | }; 21 | 22 | pub use ark_bls12_381::g2::{ 23 | G2_GENERATOR_X, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1, G2_GENERATOR_Y, G2_GENERATOR_Y_C0, 24 | G2_GENERATOR_Y_C1, 25 | }; 26 | 27 | // PSI_X = 1/(u+1)^((p-1)/3) 28 | const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = Fq2::new( 29 | Fq::ZERO, 30 | MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437") 31 | ); 32 | 33 | // PSI_Y = 1/(u+1)^((p-1)/2) 34 | const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new( 35 | MontFp!("2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"), 36 | MontFp!("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") 37 | ); 38 | 39 | // PSI_2_X = (u+1)^((1-p^2)/3) 40 | const DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0: Fq2 = Fq2::new( 41 | MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"), 42 | Fq::ZERO 43 | ); 44 | 45 | pub type G2Affine = bls12::G2Affine>; 46 | pub type G2Projective = bls12::G2Projective>; 47 | 48 | #[derive(Clone, Copy)] 49 | pub struct Config(PhantomData H>); 50 | 51 | impl CurveConfig for Config { 52 | const COFACTOR: &'static [u64] = ::COFACTOR; 53 | const COFACTOR_INV: Self::ScalarField = ::COFACTOR_INV; 54 | 55 | type BaseField = ::BaseField; 56 | type ScalarField = ::ScalarField; 57 | } 58 | 59 | impl SWCurveConfig for Config { 60 | const COEFF_A: Self::BaseField = ::COEFF_A; 61 | const COEFF_B: Self::BaseField = ::COEFF_B; 62 | 63 | const GENERATOR: G2Affine = G2Affine::::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); 64 | 65 | /// Multi scalar multiplication jumping into the user-defined `msm_g2` hook. 66 | #[inline(always)] 67 | fn msm(bases: &[G2Affine], scalars: &[Self::ScalarField]) -> Result, usize> { 68 | if bases.len() != scalars.len() { 69 | return Err(bases.len().min(scalars.len())); 70 | } 71 | Ok(H::msm_g2(bases, scalars)) 72 | } 73 | 74 | /// Projective multiplication jumping into the user-defined `mul_projective_g2` hook. 75 | #[inline(always)] 76 | fn mul_projective(base: &G2Projective, scalar: &[u64]) -> G2Projective { 77 | H::mul_projective_g2(base, scalar) 78 | } 79 | 80 | /// Affine multiplication jumping into the user-defined `mul_projective_g2` hook. 81 | #[inline(always)] 82 | fn mul_affine(base: &G2Affine, scalar: &[u64]) -> G2Projective { 83 | Self::mul_projective(&(*base).into(), scalar) 84 | } 85 | 86 | #[inline(always)] 87 | fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { 88 | ::mul_by_a(elem) 89 | } 90 | 91 | // Verbatim copy of upstream implementation. 92 | // 93 | // Can't call it directly because of different `Affine` configuration. 94 | #[inline(always)] 95 | fn is_in_correct_subgroup_assuming_on_curve(point: &G2Affine) -> bool { 96 | let mut x_times_point = point.mul_bigint(crate::Config::::X); 97 | if crate::Config::::X_IS_NEGATIVE { 98 | x_times_point = -x_times_point; 99 | } 100 | 101 | let p_times_point = p_power_endomorphism(point); 102 | 103 | x_times_point.eq(&p_times_point) 104 | } 105 | 106 | // Verbatim copy of upstream implementation. 107 | // 108 | // Can't call it directly because of different `Affine` configuration. 109 | #[inline] 110 | fn clear_cofactor(p: &G2Affine) -> G2Affine { 111 | // Based on Section 4.1 of https://eprint.iacr.org/2017/419.pdf 112 | // [h(ψ)]P = [x^2 − x − 1]P + [x − 1]ψ(P) + (ψ^2)(2P) 113 | 114 | // x = -15132376222941642752 115 | // When multiplying, use -c1 instead, and then negate the result. That's much 116 | // more efficient, since the scalar -c1 has less limbs and a much lower Hamming 117 | // weight. 118 | let x: &'static [u64] = crate::Config::::X; 119 | let p_projective = p.into_group(); 120 | 121 | // [x]P 122 | let x_p = Config::mul_affine(p, x).neg(); 123 | // ψ(P) 124 | let psi_p = p_power_endomorphism(p); 125 | // (ψ^2)(2P) 126 | let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double()); 127 | 128 | // tmp = [x]P + ψ(P) 129 | let mut tmp = x_p; 130 | tmp += &psi_p; 131 | 132 | // tmp2 = [x^2]P + [x]ψ(P) 133 | let mut tmp2: G2Projective = tmp; 134 | tmp2 = tmp2.mul_bigint(x).neg(); 135 | 136 | // add up all the terms 137 | psi2_p2 += tmp2; 138 | psi2_p2 -= x_p; 139 | psi2_p2 += &-psi_p; 140 | (psi2_p2 - p_projective).into_affine() 141 | } 142 | 143 | // Verbatim copy of upstream implementation. 144 | // 145 | // Can't call it directly because of different `Affine` configuration. 146 | fn deserialize_with_mode( 147 | mut reader: R, 148 | compress: Compress, 149 | validate: Validate, 150 | ) -> Result, SerializationError> { 151 | let p = if compress == Compress::Yes { 152 | read_g2_compressed(&mut reader)? 153 | } else { 154 | read_g2_uncompressed(&mut reader)? 155 | }; 156 | 157 | if validate == Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve() { 158 | return Err(SerializationError::InvalidData); 159 | } 160 | Ok(p) 161 | } 162 | 163 | // Verbatim copy of upstream implementation. 164 | // 165 | // Can't call it directly because of different `Affine` configuration. 166 | fn serialize_with_mode( 167 | item: &G2Affine, 168 | mut writer: W, 169 | compress: Compress, 170 | ) -> Result<(), SerializationError> { 171 | let encoding = EncodingFlags { 172 | is_compressed: compress == Compress::Yes, 173 | is_infinity: item.is_zero(), 174 | is_lexographically_largest: item.y > -item.y, 175 | }; 176 | let mut p = *item; 177 | if encoding.is_infinity { 178 | p = G2Affine::::zero(); 179 | } 180 | 181 | let mut x_bytes = [0u8; G2_SERIALIZED_SIZE]; 182 | let c1_bytes = serialize_fq(p.x.c1); 183 | let c0_bytes = serialize_fq(p.x.c0); 184 | x_bytes[0..48].copy_from_slice(&c1_bytes[..]); 185 | x_bytes[48..96].copy_from_slice(&c0_bytes[..]); 186 | if encoding.is_compressed { 187 | let mut bytes: [u8; G2_SERIALIZED_SIZE] = x_bytes; 188 | 189 | encoding.encode_flags(&mut bytes); 190 | writer.write_all(&bytes)?; 191 | } else { 192 | let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE]; 193 | 194 | let mut y_bytes = [0u8; G2_SERIALIZED_SIZE]; 195 | let c1_bytes = serialize_fq(p.y.c1); 196 | let c0_bytes = serialize_fq(p.y.c0); 197 | y_bytes[0..48].copy_from_slice(&c1_bytes[..]); 198 | y_bytes[48..96].copy_from_slice(&c0_bytes[..]); 199 | bytes[0..G2_SERIALIZED_SIZE].copy_from_slice(&x_bytes); 200 | bytes[G2_SERIALIZED_SIZE..].copy_from_slice(&y_bytes); 201 | 202 | encoding.encode_flags(&mut bytes); 203 | writer.write_all(&bytes)?; 204 | }; 205 | 206 | Ok(()) 207 | } 208 | 209 | // Verbatim copy of upstream implementation. 210 | // 211 | // Can't call it directly because of different `Affine` configuration. 212 | fn serialized_size(compress: Compress) -> usize { 213 | ::serialized_size(compress) 214 | } 215 | } 216 | 217 | /// psi(P) is the untwist-Frobenius-twist endomorhism on E'(Fq2) 218 | fn p_power_endomorphism(p: &G2Affine) -> G2Affine { 219 | // The p-power endomorphism for G2 is defined as follows: 220 | // 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1). 221 | // To map a point (x, y) in E' to (s, t) in E, 222 | // set s = x / ((u+1) ^ (1/3)), t = y / ((u+1) ^ (1/2)), 223 | // because E: y^2 = x^3 + 4. 224 | // 2. Apply theFrobenius endomorphism (s, t) => (s', t'), 225 | // another point on curve E, where s' = s^p, t' = t^p. 226 | // 3. Map the point From E back to E'; that is, 227 | // set x' = s' * ((u+1) ^ (1/3)), y' = t' * ((u+1) ^ (1/2)). 228 | // 229 | // To sum up, it maps 230 | // (x,y) -> (x^p / ((u+1)^((p-1)/3)), y^p / ((u+1)^((p-1)/2))) 231 | // as implemented in the code as follows. 232 | 233 | let mut res = *p; 234 | res.x.frobenius_map_in_place(1); 235 | res.y.frobenius_map_in_place(1); 236 | 237 | let tmp_x = res.x; 238 | res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * tmp_x.c1; 239 | res.x.c1 = P_POWER_ENDOMORPHISM_COEFF_0.c1 * tmp_x.c0; 240 | res.y *= P_POWER_ENDOMORPHISM_COEFF_1; 241 | 242 | res 243 | } 244 | 245 | /// For a p-power endomorphism psi(P), compute psi(psi(P)) 246 | fn double_p_power_endomorphism(p: &G2Projective) -> G2Projective { 247 | let mut res = *p; 248 | 249 | res.x *= DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0; 250 | res.y = res.y.neg(); 251 | 252 | res 253 | } 254 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2022 arkworks contributors 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.8.11" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 10 | dependencies = [ 11 | "cfg-if", 12 | "once_cell", 13 | "version_check", 14 | "zerocopy", 15 | ] 16 | 17 | [[package]] 18 | name = "allocator-api2" 19 | version = "0.2.21" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 22 | 23 | [[package]] 24 | name = "ark-algebra-test-templates" 25 | version = "0.5.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "fd4c6293624cb11978fe9940af61faa16e85431fa9993ed2e11ea422099a564c" 28 | dependencies = [ 29 | "ark-ec", 30 | "ark-ff", 31 | "ark-serialize", 32 | "ark-std", 33 | "hex", 34 | "num-bigint", 35 | "num-integer", 36 | "num-traits", 37 | "serde", 38 | "serde_derive", 39 | "serde_json", 40 | "sha2", 41 | ] 42 | 43 | [[package]] 44 | name = "ark-bls12-377" 45 | version = "0.5.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "bfedac3173d12820a5e0d6cd4de31b49719a74f4a41dc09b6652d0276a3b2cd4" 48 | dependencies = [ 49 | "ark-ec", 50 | "ark-ff", 51 | "ark-r1cs-std", 52 | "ark-std", 53 | ] 54 | 55 | [[package]] 56 | name = "ark-bls12-377-ext" 57 | version = "0.5.0" 58 | dependencies = [ 59 | "ark-algebra-test-templates", 60 | "ark-bls12-377", 61 | "ark-ec", 62 | "ark-ff", 63 | "ark-models-ext", 64 | "ark-serialize", 65 | "ark-std", 66 | "test-utils", 67 | ] 68 | 69 | [[package]] 70 | name = "ark-bls12-381" 71 | version = "0.5.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" 74 | dependencies = [ 75 | "ark-ec", 76 | "ark-ff", 77 | "ark-serialize", 78 | "ark-std", 79 | ] 80 | 81 | [[package]] 82 | name = "ark-bls12-381-ext" 83 | version = "0.5.0" 84 | dependencies = [ 85 | "ark-algebra-test-templates", 86 | "ark-bls12-381", 87 | "ark-ec", 88 | "ark-ff", 89 | "ark-models-ext", 90 | "ark-serialize", 91 | "ark-std", 92 | "test-utils", 93 | ] 94 | 95 | [[package]] 96 | name = "ark-bw6-761" 97 | version = "0.5.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "1cc9cae367e0c3c0b52e3ef13371122752654f45d0212ec7306fb0c1c012cd98" 100 | dependencies = [ 101 | "ark-bls12-377", 102 | "ark-ec", 103 | "ark-ff", 104 | "ark-std", 105 | ] 106 | 107 | [[package]] 108 | name = "ark-bw6-761-ext" 109 | version = "0.5.0" 110 | dependencies = [ 111 | "ark-algebra-test-templates", 112 | "ark-bw6-761", 113 | "ark-ec", 114 | "ark-ff", 115 | "ark-models-ext", 116 | "ark-serialize", 117 | "ark-std", 118 | "test-utils", 119 | ] 120 | 121 | [[package]] 122 | name = "ark-ec" 123 | version = "0.5.0" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" 126 | dependencies = [ 127 | "ahash", 128 | "ark-ff", 129 | "ark-poly", 130 | "ark-serialize", 131 | "ark-std", 132 | "educe", 133 | "fnv", 134 | "hashbrown", 135 | "itertools", 136 | "num-bigint", 137 | "num-integer", 138 | "num-traits", 139 | "rayon", 140 | "zeroize", 141 | ] 142 | 143 | [[package]] 144 | name = "ark-ed-on-bls12-377" 145 | version = "0.5.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "ebbf817b2db27d2787009b2ff76304a5b90b4b01bb16aa8351701fd40f5f37b2" 148 | dependencies = [ 149 | "ark-bls12-377", 150 | "ark-ec", 151 | "ark-ff", 152 | "ark-r1cs-std", 153 | "ark-std", 154 | ] 155 | 156 | [[package]] 157 | name = "ark-ed-on-bls12-377-ext" 158 | version = "0.5.0" 159 | dependencies = [ 160 | "ark-algebra-test-templates", 161 | "ark-ec", 162 | "ark-ed-on-bls12-377", 163 | "ark-ff", 164 | "ark-models-ext", 165 | "ark-serialize", 166 | "ark-std", 167 | "test-utils", 168 | ] 169 | 170 | [[package]] 171 | name = "ark-ed-on-bls12-381-bandersnatch" 172 | version = "0.5.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "1786b2e3832f6f0f7c8d62d5d5a282f6952a1ab99981c54cd52b6ac1d8f02df5" 175 | dependencies = [ 176 | "ark-bls12-381", 177 | "ark-ec", 178 | "ark-ff", 179 | "ark-r1cs-std", 180 | "ark-std", 181 | ] 182 | 183 | [[package]] 184 | name = "ark-ed-on-bls12-381-bandersnatch-ext" 185 | version = "0.5.0" 186 | dependencies = [ 187 | "ark-algebra-test-templates", 188 | "ark-ec", 189 | "ark-ed-on-bls12-381-bandersnatch", 190 | "ark-ff", 191 | "ark-models-ext", 192 | "ark-serialize", 193 | "ark-std", 194 | "test-utils", 195 | ] 196 | 197 | [[package]] 198 | name = "ark-ff" 199 | version = "0.5.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" 202 | dependencies = [ 203 | "ark-ff-asm", 204 | "ark-ff-macros", 205 | "ark-serialize", 206 | "ark-std", 207 | "arrayvec", 208 | "digest", 209 | "educe", 210 | "itertools", 211 | "num-bigint", 212 | "num-traits", 213 | "paste", 214 | "rayon", 215 | "zeroize", 216 | ] 217 | 218 | [[package]] 219 | name = "ark-ff-asm" 220 | version = "0.5.0" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" 223 | dependencies = [ 224 | "quote", 225 | "syn 2.0.98", 226 | ] 227 | 228 | [[package]] 229 | name = "ark-ff-macros" 230 | version = "0.5.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" 233 | dependencies = [ 234 | "num-bigint", 235 | "num-traits", 236 | "proc-macro2", 237 | "quote", 238 | "syn 2.0.98", 239 | ] 240 | 241 | [[package]] 242 | name = "ark-models-ext" 243 | version = "0.5.0" 244 | dependencies = [ 245 | "ark-ec", 246 | "ark-ff", 247 | "ark-serialize", 248 | "ark-std", 249 | "derivative", 250 | ] 251 | 252 | [[package]] 253 | name = "ark-pallas" 254 | version = "0.5.0" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "9c676d42c65f0b2d334fc0ae72a422de2e62ed75beb3022050c0e8a81f6ccc0f" 257 | dependencies = [ 258 | "ark-ec", 259 | "ark-ff", 260 | "ark-std", 261 | ] 262 | 263 | [[package]] 264 | name = "ark-pallas-ext" 265 | version = "0.5.0" 266 | dependencies = [ 267 | "ark-algebra-test-templates", 268 | "ark-ec", 269 | "ark-ff", 270 | "ark-models-ext", 271 | "ark-pallas", 272 | "ark-serialize", 273 | "ark-std", 274 | "test-utils", 275 | ] 276 | 277 | [[package]] 278 | name = "ark-poly" 279 | version = "0.5.0" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" 282 | dependencies = [ 283 | "ahash", 284 | "ark-ff", 285 | "ark-serialize", 286 | "ark-std", 287 | "educe", 288 | "fnv", 289 | "hashbrown", 290 | ] 291 | 292 | [[package]] 293 | name = "ark-r1cs-std" 294 | version = "0.5.0" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" 297 | dependencies = [ 298 | "ark-ec", 299 | "ark-ff", 300 | "ark-relations", 301 | "ark-std", 302 | "educe", 303 | "num-bigint", 304 | "num-integer", 305 | "num-traits", 306 | "tracing", 307 | ] 308 | 309 | [[package]] 310 | name = "ark-relations" 311 | version = "0.5.1" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" 314 | dependencies = [ 315 | "ark-ff", 316 | "ark-std", 317 | "tracing", 318 | ] 319 | 320 | [[package]] 321 | name = "ark-secp256k1" 322 | version = "0.5.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "f8bd211c48debd3037b48873a7aa22c3aba034e83388aa4124795c9f220b88c7" 325 | dependencies = [ 326 | "ark-ec", 327 | "ark-ff", 328 | "ark-std", 329 | ] 330 | 331 | [[package]] 332 | name = "ark-secp256k1-ext" 333 | version = "0.5.0" 334 | dependencies = [ 335 | "ark-algebra-test-templates", 336 | "ark-ec", 337 | "ark-ff", 338 | "ark-models-ext", 339 | "ark-secp256k1", 340 | "ark-serialize", 341 | "ark-std", 342 | "test-utils", 343 | ] 344 | 345 | [[package]] 346 | name = "ark-serialize" 347 | version = "0.5.0" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" 350 | dependencies = [ 351 | "ark-serialize-derive", 352 | "ark-std", 353 | "arrayvec", 354 | "digest", 355 | "num-bigint", 356 | "rayon", 357 | ] 358 | 359 | [[package]] 360 | name = "ark-serialize-derive" 361 | version = "0.5.0" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" 364 | dependencies = [ 365 | "proc-macro2", 366 | "quote", 367 | "syn 2.0.98", 368 | ] 369 | 370 | [[package]] 371 | name = "ark-std" 372 | version = "0.5.0" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" 375 | dependencies = [ 376 | "num-traits", 377 | "rand", 378 | "rayon", 379 | ] 380 | 381 | [[package]] 382 | name = "ark-vesta" 383 | version = "0.5.0" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "a3a6d658e5e7380af710828550b2dc2c7b033c9f3103d2690711cb07d5a62df6" 386 | dependencies = [ 387 | "ark-ec", 388 | "ark-ff", 389 | "ark-pallas", 390 | "ark-std", 391 | ] 392 | 393 | [[package]] 394 | name = "ark-vesta-ext" 395 | version = "0.5.0" 396 | dependencies = [ 397 | "ark-algebra-test-templates", 398 | "ark-ec", 399 | "ark-ff", 400 | "ark-models-ext", 401 | "ark-serialize", 402 | "ark-std", 403 | "ark-vesta", 404 | "test-utils", 405 | ] 406 | 407 | [[package]] 408 | name = "arrayvec" 409 | version = "0.7.6" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 412 | 413 | [[package]] 414 | name = "autocfg" 415 | version = "1.4.0" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 418 | 419 | [[package]] 420 | name = "block-buffer" 421 | version = "0.10.4" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 424 | dependencies = [ 425 | "generic-array", 426 | ] 427 | 428 | [[package]] 429 | name = "byteorder" 430 | version = "1.5.0" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 433 | 434 | [[package]] 435 | name = "cfg-if" 436 | version = "1.0.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 439 | 440 | [[package]] 441 | name = "cpufeatures" 442 | version = "0.2.17" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 445 | dependencies = [ 446 | "libc", 447 | ] 448 | 449 | [[package]] 450 | name = "crossbeam-deque" 451 | version = "0.8.6" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 454 | dependencies = [ 455 | "crossbeam-epoch", 456 | "crossbeam-utils", 457 | ] 458 | 459 | [[package]] 460 | name = "crossbeam-epoch" 461 | version = "0.9.18" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 464 | dependencies = [ 465 | "crossbeam-utils", 466 | ] 467 | 468 | [[package]] 469 | name = "crossbeam-utils" 470 | version = "0.8.21" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 473 | 474 | [[package]] 475 | name = "crypto-common" 476 | version = "0.1.6" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 479 | dependencies = [ 480 | "generic-array", 481 | "typenum", 482 | ] 483 | 484 | [[package]] 485 | name = "derivative" 486 | version = "2.2.0" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 489 | dependencies = [ 490 | "proc-macro2", 491 | "quote", 492 | "syn 1.0.109", 493 | ] 494 | 495 | [[package]] 496 | name = "digest" 497 | version = "0.10.7" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 500 | dependencies = [ 501 | "block-buffer", 502 | "crypto-common", 503 | ] 504 | 505 | [[package]] 506 | name = "educe" 507 | version = "0.6.0" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" 510 | dependencies = [ 511 | "enum-ordinalize", 512 | "proc-macro2", 513 | "quote", 514 | "syn 2.0.98", 515 | ] 516 | 517 | [[package]] 518 | name = "either" 519 | version = "1.14.0" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" 522 | 523 | [[package]] 524 | name = "enum-ordinalize" 525 | version = "4.3.0" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" 528 | dependencies = [ 529 | "enum-ordinalize-derive", 530 | ] 531 | 532 | [[package]] 533 | name = "enum-ordinalize-derive" 534 | version = "4.3.1" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" 537 | dependencies = [ 538 | "proc-macro2", 539 | "quote", 540 | "syn 2.0.98", 541 | ] 542 | 543 | [[package]] 544 | name = "fnv" 545 | version = "1.0.7" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 548 | 549 | [[package]] 550 | name = "generic-array" 551 | version = "0.14.7" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 554 | dependencies = [ 555 | "typenum", 556 | "version_check", 557 | ] 558 | 559 | [[package]] 560 | name = "hashbrown" 561 | version = "0.15.2" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 564 | dependencies = [ 565 | "allocator-api2", 566 | ] 567 | 568 | [[package]] 569 | name = "hex" 570 | version = "0.4.3" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 573 | 574 | [[package]] 575 | name = "itertools" 576 | version = "0.13.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 579 | dependencies = [ 580 | "either", 581 | ] 582 | 583 | [[package]] 584 | name = "itoa" 585 | version = "1.0.14" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 588 | 589 | [[package]] 590 | name = "libc" 591 | version = "0.2.170" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" 594 | 595 | [[package]] 596 | name = "memchr" 597 | version = "2.7.4" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 600 | 601 | [[package]] 602 | name = "num-bigint" 603 | version = "0.4.6" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 606 | dependencies = [ 607 | "num-integer", 608 | "num-traits", 609 | ] 610 | 611 | [[package]] 612 | name = "num-integer" 613 | version = "0.1.46" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 616 | dependencies = [ 617 | "num-traits", 618 | ] 619 | 620 | [[package]] 621 | name = "num-traits" 622 | version = "0.2.19" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 625 | dependencies = [ 626 | "autocfg", 627 | ] 628 | 629 | [[package]] 630 | name = "once_cell" 631 | version = "1.20.3" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" 634 | 635 | [[package]] 636 | name = "paste" 637 | version = "1.0.15" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 640 | 641 | [[package]] 642 | name = "pin-project-lite" 643 | version = "0.2.16" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 646 | 647 | [[package]] 648 | name = "ppv-lite86" 649 | version = "0.2.20" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 652 | dependencies = [ 653 | "zerocopy", 654 | ] 655 | 656 | [[package]] 657 | name = "proc-macro2" 658 | version = "1.0.93" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 661 | dependencies = [ 662 | "unicode-ident", 663 | ] 664 | 665 | [[package]] 666 | name = "quote" 667 | version = "1.0.38" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 670 | dependencies = [ 671 | "proc-macro2", 672 | ] 673 | 674 | [[package]] 675 | name = "rand" 676 | version = "0.8.5" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 679 | dependencies = [ 680 | "rand_chacha", 681 | "rand_core", 682 | ] 683 | 684 | [[package]] 685 | name = "rand_chacha" 686 | version = "0.3.1" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 689 | dependencies = [ 690 | "ppv-lite86", 691 | "rand_core", 692 | ] 693 | 694 | [[package]] 695 | name = "rand_core" 696 | version = "0.6.4" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 699 | 700 | [[package]] 701 | name = "rayon" 702 | version = "1.10.0" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 705 | dependencies = [ 706 | "either", 707 | "rayon-core", 708 | ] 709 | 710 | [[package]] 711 | name = "rayon-core" 712 | version = "1.12.1" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 715 | dependencies = [ 716 | "crossbeam-deque", 717 | "crossbeam-utils", 718 | ] 719 | 720 | [[package]] 721 | name = "ryu" 722 | version = "1.0.19" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 725 | 726 | [[package]] 727 | name = "serde" 728 | version = "1.0.218" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" 731 | dependencies = [ 732 | "serde_derive", 733 | ] 734 | 735 | [[package]] 736 | name = "serde_derive" 737 | version = "1.0.218" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" 740 | dependencies = [ 741 | "proc-macro2", 742 | "quote", 743 | "syn 2.0.98", 744 | ] 745 | 746 | [[package]] 747 | name = "serde_json" 748 | version = "1.0.139" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" 751 | dependencies = [ 752 | "itoa", 753 | "memchr", 754 | "ryu", 755 | "serde", 756 | ] 757 | 758 | [[package]] 759 | name = "sha2" 760 | version = "0.10.8" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 763 | dependencies = [ 764 | "cfg-if", 765 | "cpufeatures", 766 | "digest", 767 | ] 768 | 769 | [[package]] 770 | name = "syn" 771 | version = "1.0.109" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 774 | dependencies = [ 775 | "proc-macro2", 776 | "quote", 777 | "unicode-ident", 778 | ] 779 | 780 | [[package]] 781 | name = "syn" 782 | version = "2.0.98" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 785 | dependencies = [ 786 | "proc-macro2", 787 | "quote", 788 | "unicode-ident", 789 | ] 790 | 791 | [[package]] 792 | name = "test-utils" 793 | version = "0.5.0" 794 | dependencies = [ 795 | "ark-ec", 796 | "ark-serialize", 797 | "ark-std", 798 | ] 799 | 800 | [[package]] 801 | name = "tracing" 802 | version = "0.1.41" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 805 | dependencies = [ 806 | "pin-project-lite", 807 | "tracing-attributes", 808 | "tracing-core", 809 | ] 810 | 811 | [[package]] 812 | name = "tracing-attributes" 813 | version = "0.1.28" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 816 | dependencies = [ 817 | "proc-macro2", 818 | "quote", 819 | "syn 2.0.98", 820 | ] 821 | 822 | [[package]] 823 | name = "tracing-core" 824 | version = "0.1.33" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 827 | 828 | [[package]] 829 | name = "typenum" 830 | version = "1.18.0" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 833 | 834 | [[package]] 835 | name = "unicode-ident" 836 | version = "1.0.17" 837 | source = "registry+https://github.com/rust-lang/crates.io-index" 838 | checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" 839 | 840 | [[package]] 841 | name = "version_check" 842 | version = "0.9.5" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 845 | 846 | [[package]] 847 | name = "zerocopy" 848 | version = "0.7.35" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 851 | dependencies = [ 852 | "byteorder", 853 | "zerocopy-derive", 854 | ] 855 | 856 | [[package]] 857 | name = "zerocopy-derive" 858 | version = "0.7.35" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 861 | dependencies = [ 862 | "proc-macro2", 863 | "quote", 864 | "syn 2.0.98", 865 | ] 866 | 867 | [[package]] 868 | name = "zeroize" 869 | version = "1.8.1" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 872 | dependencies = [ 873 | "zeroize_derive", 874 | ] 875 | 876 | [[package]] 877 | name = "zeroize_derive" 878 | version = "1.4.2" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 881 | dependencies = [ 882 | "proc-macro2", 883 | "quote", 884 | "syn 2.0.98", 885 | ] 886 | --------------------------------------------------------------------------------