From 66a1fc9cf73f82696a94ce334aa5856d78ec9e49 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 19 Oct 2020 12:45:23 -0700 Subject: [PATCH] Add constraints for relevant curves (#3) --- .github/workflows/ci.yml | 11 +- Cargo.lock | 458 ------------------ Cargo.toml | 1 + bls12_377/Cargo.toml | 4 + bls12_377/src/constraints/curves.rs | 29 ++ bls12_377/src/constraints/fields.rs | 32 ++ bls12_377/src/constraints/mod.rs | 163 +++++++ bls12_377/src/constraints/pairing.rs | 10 + bls12_377/src/lib.rs | 3 + curve-constraint-tests/Cargo.toml | 27 ++ curve-constraint-tests/src/lib.rs | 551 ++++++++++++++++++++++ ed_on_bls12_377/Cargo.toml | 4 + ed_on_bls12_377/src/constraints/curves.rs | 12 + ed_on_bls12_377/src/constraints/fields.rs | 10 + ed_on_bls12_377/src/constraints/mod.rs | 107 +++++ ed_on_bls12_377/src/lib.rs | 2 + ed_on_bls12_381/Cargo.toml | 4 + ed_on_bls12_381/src/constraints/curves.rs | 12 + ed_on_bls12_381/src/constraints/fields.rs | 9 + ed_on_bls12_381/src/constraints/mod.rs | 107 +++++ ed_on_bls12_381/src/lib.rs | 2 + ed_on_bn254/Cargo.toml | 4 + ed_on_bn254/src/constraints/curves.rs | 12 + ed_on_bn254/src/constraints/fields.rs | 9 + ed_on_bn254/src/constraints/mod.rs | 107 +++++ ed_on_bn254/src/lib.rs | 2 + ed_on_bw6_761/Cargo.toml | 6 + ed_on_bw6_761/src/constraints/mod.rs | 103 ++++ ed_on_bw6_761/src/lib.rs | 3 + ed_on_cp6_782/Cargo.toml | 4 + ed_on_cp6_782/src/constraints/curves.rs | 12 + ed_on_cp6_782/src/constraints/fields.rs | 10 + ed_on_cp6_782/src/constraints/mod.rs | 108 +++++ ed_on_cp6_782/src/lib.rs | 2 + ed_on_mnt4_298/Cargo.toml | 4 + ed_on_mnt4_298/src/constraints/curves.rs | 12 + ed_on_mnt4_298/src/constraints/fields.rs | 10 + ed_on_mnt4_298/src/constraints/mod.rs | 107 +++++ ed_on_mnt4_298/src/lib.rs | 2 + ed_on_mnt4_753/Cargo.toml | 4 + ed_on_mnt4_753/src/constraints/curves.rs | 12 + ed_on_mnt4_753/src/constraints/fields.rs | 10 + ed_on_mnt4_753/src/constraints/mod.rs | 107 +++++ ed_on_mnt4_753/src/lib.rs | 2 + mnt4_298/Cargo.toml | 4 + mnt4_298/src/constraints/curves.rs | 29 ++ mnt4_298/src/constraints/fields.rs | 26 + mnt4_298/src/constraints/mod.rs | 163 +++++++ mnt4_298/src/constraints/pairing.rs | 10 + mnt4_298/src/lib.rs | 3 + mnt4_753/Cargo.toml | 4 + mnt4_753/src/constraints/curves.rs | 29 ++ mnt4_753/src/constraints/fields.rs | 26 + mnt4_753/src/constraints/mod.rs | 163 +++++++ mnt4_753/src/constraints/pairing.rs | 10 + mnt4_753/src/lib.rs | 2 + mnt6_298/Cargo.toml | 4 + mnt6_298/src/constraints/curves.rs | 29 ++ mnt6_298/src/constraints/fields.rs | 26 + mnt6_298/src/constraints/mod.rs | 158 +++++++ mnt6_298/src/constraints/pairing.rs | 10 + mnt6_298/src/lib.rs | 2 + mnt6_753/Cargo.toml | 4 + mnt6_753/src/constraints/curves.rs | 29 ++ mnt6_753/src/constraints/fields.rs | 26 + mnt6_753/src/constraints/mod.rs | 158 +++++++ mnt6_753/src/constraints/pairing.rs | 10 + mnt6_753/src/lib.rs | 2 + 68 files changed, 2670 insertions(+), 467 deletions(-) delete mode 100644 Cargo.lock create mode 100644 bls12_377/src/constraints/curves.rs create mode 100644 bls12_377/src/constraints/fields.rs create mode 100644 bls12_377/src/constraints/mod.rs create mode 100644 bls12_377/src/constraints/pairing.rs create mode 100644 curve-constraint-tests/Cargo.toml create mode 100644 curve-constraint-tests/src/lib.rs create mode 100644 ed_on_bls12_377/src/constraints/curves.rs create mode 100644 ed_on_bls12_377/src/constraints/fields.rs create mode 100644 ed_on_bls12_377/src/constraints/mod.rs create mode 100644 ed_on_bls12_381/src/constraints/curves.rs create mode 100644 ed_on_bls12_381/src/constraints/fields.rs create mode 100644 ed_on_bls12_381/src/constraints/mod.rs create mode 100644 ed_on_bn254/src/constraints/curves.rs create mode 100644 ed_on_bn254/src/constraints/fields.rs create mode 100644 ed_on_bn254/src/constraints/mod.rs create mode 100644 ed_on_bw6_761/src/constraints/mod.rs create mode 100644 ed_on_cp6_782/src/constraints/curves.rs create mode 100644 ed_on_cp6_782/src/constraints/fields.rs create mode 100644 ed_on_cp6_782/src/constraints/mod.rs create mode 100644 ed_on_mnt4_298/src/constraints/curves.rs create mode 100644 ed_on_mnt4_298/src/constraints/fields.rs create mode 100644 ed_on_mnt4_298/src/constraints/mod.rs create mode 100644 ed_on_mnt4_753/src/constraints/curves.rs create mode 100644 ed_on_mnt4_753/src/constraints/fields.rs create mode 100644 ed_on_mnt4_753/src/constraints/mod.rs create mode 100644 mnt4_298/src/constraints/curves.rs create mode 100644 mnt4_298/src/constraints/fields.rs create mode 100644 mnt4_298/src/constraints/mod.rs create mode 100644 mnt4_298/src/constraints/pairing.rs create mode 100644 mnt4_753/src/constraints/curves.rs create mode 100644 mnt4_753/src/constraints/fields.rs create mode 100644 mnt4_753/src/constraints/mod.rs create mode 100644 mnt4_753/src/constraints/pairing.rs create mode 100644 mnt6_298/src/constraints/curves.rs create mode 100644 mnt6_298/src/constraints/fields.rs create mode 100644 mnt6_298/src/constraints/mod.rs create mode 100644 mnt6_298/src/constraints/pairing.rs create mode 100644 mnt6_753/src/constraints/curves.rs create mode 100644 mnt6_753/src/constraints/fields.rs create mode 100644 mnt6_753/src/constraints/mod.rs create mode 100644 mnt6_753/src/constraints/pairing.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2aa4fa..143477c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,13 +94,6 @@ jobs: uses: actions/checkout@v2 - name: Install Rust (${{ matrix.rust }}) - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: thumbv6m-none-eabi - override: true - - - name: Install Rust ARM64 (${{ matrix.rust }}) uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -119,10 +112,10 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --examples --workspace --exclude ark-curve-tests --exclude ark-curve-benches --target thumbv6m-none-eabi + args: --examples --workspace --exclude ark-curve-tests --exclude ark-curve-constraint-tests --exclude ark-curve-benches --target aarch64-unknown-none - name: build uses: actions-rs/cargo@v1 with: command: build - args: --workspace --exclude ark-curve-tests --exclude ark-curve-benches --target thumbv6m-none-eabi + args: --workspace --exclude ark-curve-tests --exclude ark-curve-constraint-tests --exclude ark-curve-benches --target aarch64-unknown-none diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 5edf2d7..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,458 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "ark-bls12-377" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-bls12-381" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-bn254" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-bw6-761" -version = "0.1.0" -dependencies = [ - "ark-bls12-377", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-cp6-782" -version = "0.1.0" -dependencies = [ - "ark-bls12-377", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-curve-benches" -version = "0.1.1-alpha.0" -dependencies = [ - "ark-bls12-377", - "ark-bls12-381", - "ark-bn254", - "ark-bw6-761", - "ark-cp6-782", - "ark-ec", - "ark-ff", - "ark-mnt4-298", - "ark-mnt4-753", - "ark-mnt6-298", - "ark-mnt6-753", - "ark-serialize", - "paste", - "rand", - "rand_xorshift", - "rustc_version", -] - -[[package]] -name = "ark-curve-tests" -version = "0.1.0" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ec" -version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "num-traits", - "rand", -] - -[[package]] -name = "ark-ed-on-bls12-377" -version = "0.1.0" -dependencies = [ - "ark-bls12-377", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ed-on-bls12-381" -version = "0.1.0" -dependencies = [ - "ark-bls12-381", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ed-on-bn254" -version = "0.1.0" -dependencies = [ - "ark-bn254", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ed-on-bw6-761" -version = "0.1.0" -dependencies = [ - "ark-ed-on-cp6-782", -] - -[[package]] -name = "ark-ed-on-cp6-782" -version = "0.1.0" -dependencies = [ - "ark-bls12-377", - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ed-on-mnt4-298" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-mnt4-298", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-ff" -version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4" -dependencies = [ - "ark-ff-asm", - "ark-serialize", - "ark-std", - "derivative", - "num-traits", - "rand", - "rustc_version", -] - -[[package]] -name = "ark-ff-asm" -version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "ark-mnt4-298" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-mnt4-753" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-mnt6-298" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-mnt4-298", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-mnt6-753" -version = "0.1.0" -dependencies = [ - "ark-curve-tests", - "ark-ec", - "ark-ff", - "ark-mnt4-753", - "ark-serialize", - "ark-std", - "rand", - "rand_xorshift", -] - -[[package]] -name = "ark-serialize" -version = "0.1.0" -source = "git+https://github.com/arkworks-rs/algebra#d5202f896ca9700c5c22d7a1266ada600f913dc4" -dependencies = [ - "ark-std", -] - -[[package]] -name = "ark-std" -version = "0.1.0" -source = "git+https://github.com/arkworks-rs/utils#7bde3ab01799da8429b8fa9c3f152201415cdfe7" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "derivative" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "getrandom" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "libc" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" - -[[package]] -name = "num-traits" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" -dependencies = [ - "autocfg", -] - -[[package]] -name = "paste" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0520af26d4cf99643dbbe093a61507922b57232d9978d8491fdc8f7b44573c8c" - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_xorshift" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "syn" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" diff --git a/Cargo.toml b/Cargo.toml index 418d5b0..995983f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "curve-benches", "curve-tests", + "curve-constraint-tests", "bls12_377", "ed_on_bls12_377", diff --git a/bls12_377/Cargo.toml b/bls12_377/Cargo.toml index 66860ce..4c36fb8 100644 --- a/bls12_377/Cargo.toml +++ b/bls12_377/Cargo.toml @@ -15,11 +15,14 @@ edition = "2018" [dependencies] ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" @@ -30,3 +33,4 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ] curve = [ "scalar_field", "base_field" ] scalar_field = [] base_field = [] +r1cs = [ "base_field", "ark-r1cs-std" ] \ No newline at end of file diff --git a/bls12_377/src/constraints/curves.rs b/bls12_377/src/constraints/curves.rs new file mode 100644 index 0000000..5441eba --- /dev/null +++ b/bls12_377/src/constraints/curves.rs @@ -0,0 +1,29 @@ +use crate::Parameters; +use ark_r1cs_std::groups::bls12; + +/// An element of G1 in the BLS12-377 bilinear group. +pub type G1Var = bls12::G1Var; +/// An element of G2 in the BLS12-377 bilinear group. +pub type G2Var = bls12::G2Var; + +/// Represents the cached precomputation that can be performed on a G1 element +/// which enables speeding up pairing computation. +pub type G1PreparedVar = bls12::G1PreparedVar; +/// Represents the cached precomputation that can be performed on a G2 element +/// which enables speeding up pairing computation. +pub type G2PreparedVar = bls12::G2PreparedVar; + +#[test] +fn test() { + use ark_ec::models::bls12::Bls12Parameters; + ark_curve_constraint_tests::curves::sw_test::< + ::G1Parameters, + G1Var, + >() + .unwrap(); + ark_curve_constraint_tests::curves::sw_test::< + ::G2Parameters, + G2Var, + >() + .unwrap(); +} diff --git a/bls12_377/src/constraints/fields.rs b/bls12_377/src/constraints/fields.rs new file mode 100644 index 0000000..7a626e6 --- /dev/null +++ b/bls12_377/src/constraints/fields.rs @@ -0,0 +1,32 @@ +use crate::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters}; + +use ark_r1cs_std::fields::{fp::FpVar, fp12::Fp12Var, fp2::Fp2Var, fp6_3over2::Fp6Var}; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq2`. +pub type Fq2Var = Fp2Var; +/// A variable that is the R1CS equivalent of `crate::Fq6`. +pub type Fq6Var = Fp6Var; +/// A variable that is the R1CS equivalent of `crate::Fq12`. +pub type Fq12Var = Fp12Var; + +#[test] +fn bls12_377_field_test() { + use super::*; + use crate::{Fq, Fq12, Fq2, Fq6}; + use ark_curve_constraint_tests::fields::*; + + field_test::<_, _, FqVar>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq2Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq6Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq12Var>().unwrap(); + frobenius_tests::(13).unwrap(); +} diff --git a/bls12_377/src/constraints/mod.rs b/bls12_377/src/constraints/mod.rs new file mode 100644 index 0000000..e04d9cf --- /dev/null +++ b/bls12_377/src/constraints/mod.rs @@ -0,0 +1,163 @@ +//! This module implements the R1CS equivalent of `crate`. +//! +//! It implements field variables for `crate::{Fq, Fq2, Fq6, Fq12}`, +//! group variables for `crate::{G1, G2}`, and implements constraint +//! generation for computing `Bls12_377::pairing`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_bls12_377::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `G1Var` and `G2Var`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_bls12_377::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `G1` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G1Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G1Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G1Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `G1`. +//! let zero = G1Var::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! Finally, one can check pairing computations as well: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_ec::PairingEngine; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_bls12_377::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate random `G1` and `G2` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G2Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G2Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G2Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let pairing_result_native = Bls12_377::pairing(a_native, b_native); +//! +//! // Prepare `a` and `b` for pairing. +//! let a_prep = constraints::PairingVar::prepare_g1(&a)?; +//! let b_prep = constraints::PairingVar::prepare_g2(&b)?; +//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!(pairing_result.value()?, pairing_result_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; +//! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?; +//! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?; +//! println!("Done here 3"); +//! +//! pairing_result.enforce_equal(&pairing_result_const)?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod fields; +pub use fields::*; + +#[cfg(feature = "curve")] +mod curves; +#[cfg(feature = "curve")] +mod pairing; + +#[cfg(feature = "curve")] +pub use curves::*; +#[cfg(feature = "curve")] +pub use pairing::*; diff --git a/bls12_377/src/constraints/pairing.rs b/bls12_377/src/constraints/pairing.rs new file mode 100644 index 0000000..f659f29 --- /dev/null +++ b/bls12_377/src/constraints/pairing.rs @@ -0,0 +1,10 @@ +use crate::Parameters; + +/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear group. +pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar; + +#[test] +fn test() { + use crate::Bls12_377; + ark_curve_constraint_tests::pairing::bilinearity_test::().unwrap() +} diff --git a/bls12_377/src/lib.rs b/bls12_377/src/lib.rs index 136c1f3..46d4b4a 100644 --- a/bls12_377/src/lib.rs +++ b/bls12_377/src/lib.rs @@ -29,6 +29,9 @@ mod curves; mod fields; +#[cfg(feature = "r1cs")] +pub mod constraints; + #[cfg(feature = "curve")] pub use curves::*; diff --git a/curve-constraint-tests/Cargo.toml b/curve-constraint-tests/Cargo.toml new file mode 100644 index 0000000..b5fdc25 --- /dev/null +++ b/curve-constraint-tests/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "ark-curve-constraint-tests" +version = "0.1.0" +authors = [ "arkworks contributors" ] +description = "A library for testing constraints for finite fields, elliptic curves, and pairings" +homepage = "https://arworks.rs" +repository = "https://github.com/arkworks/curves" +documentation = "https://docs.rs/ark-curve-constraint-tests/" +keywords = ["cryptography", "finite fields", "elliptic curves", "r1cs" ] +categories = ["cryptography"] +include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +license = "MIT/Apache-2.0" +edition = "2018" + +[dependencies] +ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false } +ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +rand = { version = "0.7", default-features = false} +rand_xorshift = { version = "0.2", default-features = false} + +[features] +default = [] +std = [ "ark-std/std", "ark-ff/std", "ark-serialize/std", "ark-ec/std", "ark-relations/std", "ark-r1cs-std/std" ] diff --git a/curve-constraint-tests/src/lib.rs b/curve-constraint-tests/src/lib.rs new file mode 100644 index 0000000..daa8452 --- /dev/null +++ b/curve-constraint-tests/src/lib.rs @@ -0,0 +1,551 @@ +#![no_std] +#![macro_use] +extern crate ark_relations; + +pub mod fields { + use rand::{self, SeedableRng}; + use rand_xorshift::XorShiftRng; + + use ark_ff::{test_rng, BitIteratorLE, Field, UniformRand}; + use ark_r1cs_std::prelude::*; + use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; + use ark_std::vec::Vec; + + pub fn field_test() -> Result<(), SynthesisError> + where + F: Field, + ConstraintF: Field, + AF: FieldVar, + AF: TwoBitLookupGadget, + for<'a> &'a AF: FieldOpsBounds<'a, F, AF>, + { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a_native = F::rand(&mut rng); + let b_native = F::rand(&mut rng); + let a = AF::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; + let b = AF::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; + let b_const = AF::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; + + let zero = AF::zero(); + let zero_native = zero.value()?; + zero.enforce_equal(&zero)?; + + let one = AF::one(); + let one_native = one.value()?; + one.enforce_equal(&one)?; + + one.enforce_not_equal(&zero)?; + + let one_dup = &zero + &one; + one_dup.enforce_equal(&one)?; + + let two = &one + &one; + two.enforce_equal(&two)?; + two.enforce_equal(&one.double()?)?; + two.enforce_not_equal(&one)?; + two.enforce_not_equal(&zero)?; + + // a + 0 = a + let a_plus_zero = &a + &zero; + assert_eq!(a_plus_zero.value()?, a_native); + a_plus_zero.enforce_equal(&a)?; + a_plus_zero.enforce_not_equal(&a.double()?)?; + + // a - 0 = a + let a_minus_zero = &a - &zero; + assert_eq!(a_minus_zero.value()?, a_native); + a_minus_zero.enforce_equal(&a)?; + + // a - a = 0 + let a_minus_a = &a - &a; + assert_eq!(a_minus_a.value()?, zero_native); + a_minus_a.enforce_equal(&zero)?; + + // a + b = b + a + let a_b = &a + &b; + let b_a = &b + &a; + assert_eq!(a_b.value()?, a_native + &b_native); + a_b.enforce_equal(&b_a)?; + + // (a + b) + a = a + (b + a) + let ab_a = &a_b + &a; + let a_ba = &a + &b_a; + assert_eq!(ab_a.value()?, a_native + &b_native + &a_native); + ab_a.enforce_equal(&a_ba)?; + + let b_times_a_plus_b = &a_b * &b; + let b_times_b_plus_a = &b_a * &b; + assert_eq!( + b_times_a_plus_b.value()?, + b_native * &(b_native + &a_native) + ); + assert_eq!( + b_times_a_plus_b.value()?, + (b_native + &a_native) * &b_native + ); + assert_eq!( + b_times_a_plus_b.value()?, + (a_native + &b_native) * &b_native + ); + b_times_b_plus_a.enforce_equal(&b_times_a_plus_b)?; + + // a * 1 = a + assert_eq!((&a * &one).value()?, a_native * &one_native); + + // a * b = b * a + let ab = &a * &b; + let ba = &b * &a; + assert_eq!(ab.value()?, ba.value()?); + assert_eq!(ab.value()?, a_native * &b_native); + + let ab_const = &a * &b_const; + let b_const_a = &b_const * &a; + assert_eq!(ab_const.value()?, b_const_a.value()?); + assert_eq!(ab_const.value()?, ab.value()?); + assert_eq!(ab_const.value()?, a_native * &b_native); + + // (a * b) * a = a * (b * a) + let ab_a = &ab * &a; + let a_ba = &a * &ba; + assert_eq!(ab_a.value()?, a_ba.value()?); + assert_eq!(ab_a.value()?, a_native * &b_native * &a_native); + + let aa = &a * &a; + let a_squared = a.square()?; + a_squared.enforce_equal(&aa)?; + assert_eq!(aa.value()?, a_squared.value()?); + assert_eq!(aa.value()?, a_native.square()); + + let aa = &a * a.value()?; + a_squared.enforce_equal(&aa)?; + assert_eq!(aa.value()?, a_squared.value()?); + assert_eq!(aa.value()?, a_native.square()); + + let a_b2 = &a + b_native; + a_b.enforce_equal(&a_b2)?; + assert_eq!(a_b.value()?, a_b2.value()?); + + let a_inv = a.inverse()?; + a_inv.mul_equals(&a, &one)?; + assert_eq!(a_inv.value()?, a.value()?.inverse().unwrap()); + assert_eq!(a_inv.value()?, a_native.inverse().unwrap()); + + let a_b_inv = a.mul_by_inverse(&b)?; + a_b_inv.mul_equals(&b, &a)?; + assert_eq!(a_b_inv.value()?, a_native * b_native.inverse().unwrap()); + + // a * a * a = a^3 + let bits = BitIteratorLE::without_trailing_zeros([3u64]) + .map(Boolean::constant) + .collect::>(); + assert_eq!(a_native.pow([0x3]), a.pow_le(&bits)?.value()?); + + // a * a * a = a^3 + assert_eq!(a_native.pow([0x3]), a.pow_by_constant(&[0x3])?.value()?); + assert!(cs.is_satisfied().unwrap()); + + // a * a * a = a^3 + let mut constants = [F::zero(); 4]; + for c in &mut constants { + *c = UniformRand::rand(&mut test_rng()); + } + let bits = [ + Boolean::::constant(false), + Boolean::constant(true), + ]; + let lookup_result = AF::two_bit_lookup(&bits, constants.as_ref())?; + assert_eq!(lookup_result.value()?, constants[2]); + assert!(cs.is_satisfied().unwrap()); + + let f = F::from(1u128 << 64); + let f_bits = ark_ff::BitIteratorLE::new(&[0u64, 1u64]).collect::>(); + let fv = AF::new_witness(ark_relations::ns!(cs, "alloc u128"), || Ok(f))?; + assert_eq!(fv.to_bits_le()?.value().unwrap()[..128], f_bits[..128]); + assert!(cs.is_satisfied().unwrap()); + + let r_native: F = UniformRand::rand(&mut test_rng()); + + let r = AF::new_witness(ark_relations::ns!(cs, "r_native"), || Ok(r_native)).unwrap(); + let _ = r.to_non_unique_bits_le()?; + assert!(cs.is_satisfied().unwrap()); + let _ = r.to_bits_le()?; + assert!(cs.is_satisfied().unwrap()); + + let bytes = r.to_non_unique_bytes()?; + assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); + assert!(cs.is_satisfied().unwrap()); + let bytes = r.to_bytes()?; + assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); + assert!(cs.is_satisfied().unwrap()); + + let ab_false = &a + (AF::from(Boolean::Constant(false)) * b_native); + assert_eq!(ab_false.value()?, a_native); + let ab_true = &a + (AF::from(Boolean::Constant(true)) * b_native); + assert_eq!(ab_true.value()?, a_native + &b_native); + + if !cs.is_satisfied().unwrap() { + panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + } + assert!(cs.is_satisfied().unwrap()); + Ok(()) + } + + pub fn frobenius_tests(maxpower: usize) -> Result<(), SynthesisError> + where + F: Field, + ConstraintF: Field, + AF: FieldVar, + for<'a> &'a AF: FieldOpsBounds<'a, F, AF>, + { + let cs = ConstraintSystem::::new_ref(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + for i in 0..=maxpower { + let mut a = F::rand(&mut rng); + let mut a_gadget = AF::new_witness(ark_relations::ns!(cs, "a"), || Ok(a))?; + a_gadget.frobenius_map_in_place(i)?; + a.frobenius_map(i); + + assert_eq!(a_gadget.value()?, a); + } + + assert!(cs.is_satisfied().unwrap()); + Ok(()) + } +} + +pub mod curves { + use ark_ec::{ + short_weierstrass_jacobian::GroupProjective as SWProjective, + twisted_edwards_extended::GroupProjective as TEProjective, AffineCurve, ProjectiveCurve, + }; + use ark_ff::{test_rng, Field, PrimeField}; + use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; + use ark_std::vec::Vec; + + use ark_r1cs_std::prelude::*; + + pub fn group_test() -> Result<(), SynthesisError> + where + C: ProjectiveCurve, + ConstraintF: Field, + GG: CurveVar, + for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a_native = C::rand(&mut rng); + let b_native = C::rand(&mut rng); + let a = GG::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native)).unwrap(); + let b = GG::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native)).unwrap(); + + let zero = GG::zero(); + assert_eq!(zero.value()?, zero.value()?); + + // a == a + assert_eq!(a.value()?, a.value()?); + // a + 0 = a + assert_eq!((&a + &zero).value()?, a.value()?); + // a - 0 = a + assert_eq!((&a - &zero).value()?, a.value()?); + // a - a = 0 + assert_eq!((&a - &a).value()?, zero.value()?); + // a + b = b + a + let a_b = &a + &b; + let b_a = &b + &a; + assert_eq!(a_b.value()?, b_a.value()?); + a_b.enforce_equal(&b_a)?; + assert!(cs.is_satisfied().unwrap()); + + // (a + b) + a = a + (b + a) + let ab_a = &a_b + &a; + let a_ba = &a + &b_a; + assert_eq!(ab_a.value()?, a_ba.value()?); + ab_a.enforce_equal(&a_ba)?; + assert!(cs.is_satisfied().unwrap()); + + // a.double() = a + a + let a_a = &a + &a; + let mut a2 = a.clone(); + a2.double_in_place()?; + a2.enforce_equal(&a_a)?; + assert_eq!(a2.value()?, a_native.double()); + assert_eq!(a_a.value()?, a_native.double()); + assert_eq!(a2.value()?, a_a.value()?); + assert!(cs.is_satisfied().unwrap()); + + // b.double() = b + b + let mut b2 = b.clone(); + b2.double_in_place()?; + let b_b = &b + &b; + b2.enforce_equal(&b_b)?; + assert!(cs.is_satisfied().unwrap()); + assert_eq!(b2.value()?, b_b.value()?); + + let _ = a.to_bytes()?; + assert!(cs.is_satisfied().unwrap()); + let _ = a.to_non_unique_bytes()?; + assert!(cs.is_satisfied().unwrap()); + + let _ = b.to_bytes()?; + let _ = b.to_non_unique_bytes()?; + if !cs.is_satisfied().unwrap() { + panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + } + assert!(cs.is_satisfied().unwrap()); + Ok(()) + } + + pub fn sw_test() -> Result<(), SynthesisError> + where + P: ark_ec::SWModelParameters, + GG: CurveVar, ::BasePrimeField>, + for<'a> &'a GG: GroupOpsBounds<'a, SWProjective

, GG>, + { + use ark_ec::group::Group; + use ark_ff::{BitIteratorLE, UniformRand}; + use ark_r1cs_std::prelude::*; + + group_test::, _, GG>()?; + + let mut rng = test_rng(); + + let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); + + let a = SWProjective::

::rand(&mut rng); + let b = SWProjective::

::rand(&mut rng); + let a_affine = a.into_affine(); + let b_affine = b.into_affine(); + + let ns = ark_relations::ns!(cs, "allocating variables"); + let mut gadget_a = GG::new_witness(cs.clone(), || Ok(a))?; + let gadget_b = GG::new_witness(cs.clone(), || Ok(b))?; + drop(ns); + assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); + assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); + assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); + assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); + assert_eq!(cs.which_is_unsatisfied().unwrap(), None); + + // Check addition + let ab = a + &b; + let ab_affine = ab.into_affine(); + let gadget_ab = &gadget_a + &gadget_b; + let gadget_ba = &gadget_b + &gadget_a; + gadget_ba.enforce_equal(&gadget_ab)?; + + let ab_val = gadget_ab.value()?.into_affine(); + assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); + assert!(cs.is_satisfied().unwrap()); + + // Check doubling + let aa = Group::double(&a); + let aa_affine = aa.into_affine(); + gadget_a.double_in_place()?; + let aa_val = gadget_a.value()?.into_affine(); + assert_eq!( + aa_val, aa_affine, + "Gadget and native values are unequal after double." + ); + assert!(cs.is_satisfied().unwrap()); + + // Check mul_bits + let scalar = P::ScalarField::rand(&mut rng); + let native_result = aa.into_affine().mul(scalar); + let native_result = native_result.into_affine(); + + let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); + let input: Vec> = + Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); + let result = gadget_a.scalar_mul_le(input.iter())?; + let result_val = result.value()?.into_affine(); + assert_eq!( + result_val, native_result, + "gadget & native values are diff. after scalar mul" + ); + assert!(cs.is_satisfied().unwrap()); + + if !cs.is_satisfied().unwrap() { + panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + } + + assert!(cs.is_satisfied().unwrap()); + Ok(()) + } + + pub fn te_test() -> Result<(), SynthesisError> + where + P: ark_ec::TEModelParameters, + GG: CurveVar, ::BasePrimeField>, + for<'a> &'a GG: GroupOpsBounds<'a, TEProjective

, GG>, + { + use ark_ec::group::Group; + use ark_ff::{BitIteratorLE, UniformRand}; + + group_test::, _, GG>()?; + + let mut rng = test_rng(); + + let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); + + let a = TEProjective::

::rand(&mut rng); + let b = TEProjective::

::rand(&mut rng); + let a_affine = a.into_affine(); + let b_affine = b.into_affine(); + + let ns = ark_relations::ns!(cs, "allocating variables"); + let mut gadget_a = GG::new_witness(cs.clone(), || Ok(a))?; + let gadget_b = GG::new_witness(cs.clone(), || Ok(b))?; + drop(ns); + + assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); + assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); + assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); + assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); + assert_eq!(cs.which_is_unsatisfied()?, None); + + // Check addition + let ab = a + &b; + let ab_affine = ab.into_affine(); + let gadget_ab = &gadget_a + &gadget_b; + let gadget_ba = &gadget_b + &gadget_a; + gadget_ba.enforce_equal(&gadget_ab)?; + + let ab_val = gadget_ab.value()?.into_affine(); + assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); + assert!(cs.is_satisfied().unwrap()); + + // Check doubling + let aa = Group::double(&a); + let aa_affine = aa.into_affine(); + gadget_a.double_in_place()?; + let aa_val = gadget_a.value()?.into_affine(); + assert_eq!( + aa_val, aa_affine, + "Gadget and native values are unequal after double." + ); + assert!(cs.is_satisfied().unwrap()); + + // Check mul_bits + let scalar = P::ScalarField::rand(&mut rng); + let native_result = AffineCurve::mul(&aa.into_affine(), scalar); + let native_result = native_result.into_affine(); + + let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); + let input: Vec> = + Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); + let result = gadget_a.scalar_mul_le(input.iter())?; + let result_val = result.value()?.into_affine(); + assert_eq!( + result_val, native_result, + "gadget & native values are diff. after scalar mul" + ); + assert!(cs.is_satisfied().unwrap()); + + if !cs.is_satisfied().unwrap() { + panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + } + + assert!(cs.is_satisfied().unwrap()); + Ok(()) + } +} + +pub mod pairing { + use ark_ec::{PairingEngine, ProjectiveCurve}; + use ark_ff::{test_rng, BitIteratorLE, Field, PrimeField, UniformRand}; + use ark_r1cs_std::prelude::*; + use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; + use ark_std::vec::Vec; + + #[allow(dead_code)] + pub fn bilinearity_test>() -> Result<(), SynthesisError> + where + for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1Projective, P::G1Var>, + for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>, + for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>, + { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a = E::G1Projective::rand(&mut rng); + let b = E::G2Projective::rand(&mut rng); + let s = E::Fr::rand(&mut rng); + + let mut sa = a; + sa *= s; + let mut sb = b; + sb *= s; + + let a_g = P::G1Var::new_witness(cs.clone(), || Ok(a.into_affine()))?; + let b_g = P::G2Var::new_witness(cs.clone(), || Ok(b.into_affine()))?; + let sa_g = P::G1Var::new_witness(cs.clone(), || Ok(sa.into_affine()))?; + let sb_g = P::G2Var::new_witness(cs.clone(), || Ok(sb.into_affine()))?; + + let mut _preparation_num_constraints = cs.num_constraints(); + let a_prep_g = P::prepare_g1(&a_g)?; + let b_prep_g = P::prepare_g2(&b_g)?; + _preparation_num_constraints = cs.num_constraints() - _preparation_num_constraints; + + let sa_prep_g = P::prepare_g1(&sa_g)?; + let sb_prep_g = P::prepare_g2(&sb_g)?; + + let (ans1_g, ans1_n) = { + let _ml_constraints = cs.num_constraints(); + let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?; + let _fe_constraints = cs.num_constraints(); + let ans_g = P::final_exponentiation(&ml_g)?; + let ans_n = E::pairing(sa, b); + (ans_g, ans_n) + }; + + let (ans2_g, ans2_n) = { + let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?; + let ans_n = E::pairing(a, sb); + (ans_g, ans_n) + }; + + let (ans3_g, ans3_n) = { + let s_iter = BitIteratorLE::without_trailing_zeros(s.into_repr()) + .map(Boolean::constant) + .collect::>(); + + let mut ans_g = P::pairing(a_prep_g, b_prep_g)?; + let mut ans_n = E::pairing(a, b); + ans_n = ans_n.pow(s.into_repr()); + ans_g = ans_g.pow_le(&s_iter)?; + + (ans_g, ans_n) + }; + + ans1_g.enforce_equal(&ans2_g)?; + ans2_g.enforce_equal(&ans3_g)?; + + assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1"); + assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2"); + assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3"); + + assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native"); + assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native"); + assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3"); + assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2"); + assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3"); + + if !cs.is_satisfied().unwrap() { + panic!("Unsatisfied: {:?}", cs.which_is_unsatisfied()); + } + + assert!(cs.is_satisfied().unwrap(), "cs is not satisfied"); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/ed_on_bls12_377/Cargo.toml b/ed_on_bls12_377/Cargo.toml index 2aeecb8..cda3f33 100644 --- a/ed_on_bls12_377/Cargo.toml +++ b/ed_on_bls12_377/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-bls12-377 = { path = "../bls12_377", default-features = false, features = [ "scalar_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ] +r1cs = [ "ark-r1cs-std" ] diff --git a/ed_on_bls12_377/src/constraints/curves.rs b/ed_on_bls12_377/src/constraints/curves.rs new file mode 100644 index 0000000..4b15106 --- /dev/null +++ b/ed_on_bls12_377/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use crate::*; +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + +use crate::constraints::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::().unwrap(); +} diff --git a/ed_on_bls12_377/src/constraints/fields.rs b/ed_on_bls12_377/src/constraints/fields.rs new file mode 100644 index 0000000..f25fa33 --- /dev/null +++ b/ed_on_bls12_377/src/constraints/fields.rs @@ -0,0 +1,10 @@ +use crate::fq::Fq; +use ark_r1cs_std::fields::fp::FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_bls12_377/src/constraints/mod.rs b/ed_on_bls12_377/src/constraints/mod.rs new file mode 100644 index 0000000..e463b74 --- /dev/null +++ b/ed_on_bls12_377/src/constraints/mod.rs @@ -0,0 +1,107 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_bls12_377`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_bls12_377::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_bls12_377::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_bls12_377/src/lib.rs b/ed_on_bls12_377/src/lib.rs index 204896a..0559442 100644 --- a/ed_on_bls12_377/src/lib.rs +++ b/ed_on_bls12_377/src/lib.rs @@ -22,6 +22,8 @@ //! * a = -1 //! * d = 3021 +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/ed_on_bls12_381/Cargo.toml b/ed_on_bls12_381/Cargo.toml index 647076c..2bdddd4 100644 --- a/ed_on_bls12_381/Cargo.toml +++ b/ed_on_bls12_381/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-bls12-381 = { path = "../bls12_381", default-features = false, features = [ "scalar_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-381/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/ed_on_bls12_381/src/constraints/curves.rs b/ed_on_bls12_381/src/constraints/curves.rs new file mode 100644 index 0000000..9c9f783 --- /dev/null +++ b/ed_on_bls12_381/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use crate::*; +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + +use crate::constraints::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::<_, EdwardsVar>().unwrap(); +} diff --git a/ed_on_bls12_381/src/constraints/fields.rs b/ed_on_bls12_381/src/constraints/fields.rs new file mode 100644 index 0000000..3f81d7a --- /dev/null +++ b/ed_on_bls12_381/src/constraints/fields.rs @@ -0,0 +1,9 @@ +use ark_r1cs_std::fields::fp::FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_bls12_381/src/constraints/mod.rs b/ed_on_bls12_381/src/constraints/mod.rs new file mode 100644 index 0000000..bfbb5db --- /dev/null +++ b/ed_on_bls12_381/src/constraints/mod.rs @@ -0,0 +1,107 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_bls12_381`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_bls12_381::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_bls12_381::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_bls12_381/src/lib.rs b/ed_on_bls12_381/src/lib.rs index a7346e1..3b429ba 100644 --- a/ed_on_bls12_381/src/lib.rs +++ b/ed_on_bls12_381/src/lib.rs @@ -22,6 +22,8 @@ //! * a = -1 //! * d = -(10240/10241) +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/ed_on_bn254/Cargo.toml b/ed_on_bn254/Cargo.toml index eb321db..80166e8 100644 --- a/ed_on_bn254/Cargo.toml +++ b/ed_on_bn254/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-bn254 = { path = "../bn254", default-features = false, features = [ "scalar_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bn254/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/ed_on_bn254/src/constraints/curves.rs b/ed_on_bn254/src/constraints/curves.rs new file mode 100644 index 0000000..9c9f783 --- /dev/null +++ b/ed_on_bn254/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use crate::*; +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + +use crate::constraints::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::<_, EdwardsVar>().unwrap(); +} diff --git a/ed_on_bn254/src/constraints/fields.rs b/ed_on_bn254/src/constraints/fields.rs new file mode 100644 index 0000000..3f81d7a --- /dev/null +++ b/ed_on_bn254/src/constraints/fields.rs @@ -0,0 +1,9 @@ +use ark_r1cs_std::fields::fp::FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_bn254/src/constraints/mod.rs b/ed_on_bn254/src/constraints/mod.rs new file mode 100644 index 0000000..f5fd9a7 --- /dev/null +++ b/ed_on_bn254/src/constraints/mod.rs @@ -0,0 +1,107 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_bn254`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_bn254::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_bn254::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_bn254/src/lib.rs b/ed_on_bn254/src/lib.rs index b7dca55..37f5a3f 100644 --- a/ed_on_bn254/src/lib.rs +++ b/ed_on_bn254/src/lib.rs @@ -22,6 +22,8 @@ //! * d = 168696/168700 mod q //! = 9706598848417545097372247223557719406784115219466060233080913168975159366771 +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/ed_on_bw6_761/Cargo.toml b/ed_on_bw6_761/Cargo.toml index 6e81fef..55ee1a3 100644 --- a/ed_on_bw6_761/Cargo.toml +++ b/ed_on_bw6_761/Cargo.toml @@ -15,6 +15,12 @@ edition = "2018" [dependencies] ark-ed-on-cp6-782 = { path = "../ed_on_cp6_782", default-features = false } +[dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false } +ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } + [features] default = [] std = [ "ark-ed-on-cp6-782/std" ] +r1cs = [ "ark-ed-on-cp6-782/r1cs" ] \ No newline at end of file diff --git a/ed_on_bw6_761/src/constraints/mod.rs b/ed_on_bw6_761/src/constraints/mod.rs new file mode 100644 index 0000000..f892b8e --- /dev/null +++ b/ed_on_bw6_761/src/constraints/mod.rs @@ -0,0 +1,103 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_bw6_761`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_bw6_761::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_bw6_761::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +pub use ark_ed_on_cp6_782::constraints::*; diff --git a/ed_on_bw6_761/src/lib.rs b/ed_on_bw6_761/src/lib.rs index 9eb58dc..12941f6 100644 --- a/ed_on_bw6_761/src/lib.rs +++ b/ed_on_bw6_761/src/lib.rs @@ -16,3 +16,6 @@ //! * d = 79743 pub use ark_ed_on_cp6_782::*; + +#[cfg(feature = "r1cs")] +pub mod constraints; diff --git a/ed_on_cp6_782/Cargo.toml b/ed_on_cp6_782/Cargo.toml index 5e1942a..31addac 100644 --- a/ed_on_cp6_782/Cargo.toml +++ b/ed_on_cp6_782/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-bls12-377 = { path = "../bls12_377", default-features = false, features = [ "base_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/ed_on_cp6_782/src/constraints/curves.rs b/ed_on_cp6_782/src/constraints/curves.rs new file mode 100644 index 0000000..4b15106 --- /dev/null +++ b/ed_on_cp6_782/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use crate::*; +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + +use crate::constraints::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::().unwrap(); +} diff --git a/ed_on_cp6_782/src/constraints/fields.rs b/ed_on_cp6_782/src/constraints/fields.rs new file mode 100644 index 0000000..f25fa33 --- /dev/null +++ b/ed_on_cp6_782/src/constraints/fields.rs @@ -0,0 +1,10 @@ +use crate::fq::Fq; +use ark_r1cs_std::fields::fp::FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_cp6_782/src/constraints/mod.rs b/ed_on_cp6_782/src/constraints/mod.rs new file mode 100644 index 0000000..29a555b --- /dev/null +++ b/ed_on_cp6_782/src/constraints/mod.rs @@ -0,0 +1,108 @@ +#![allow(unreachable_pub)] +//! This module implements the R1CS equivalent of `ark_ed_on_cp6_782`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_cp6_782::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_cp6_782::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_cp6_782/src/lib.rs b/ed_on_cp6_782/src/lib.rs index c6e69c9..ec0935c 100644 --- a/ed_on_cp6_782/src/lib.rs +++ b/ed_on_cp6_782/src/lib.rs @@ -21,6 +21,8 @@ //! * a = -1 //! * d = 79743 +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/ed_on_mnt4_298/Cargo.toml b/ed_on_mnt4_298/Cargo.toml index c6673cd..8628f58 100644 --- a/ed_on_mnt4_298/Cargo.toml +++ b/ed_on_mnt4_298/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-mnt4-298 = { path = "../mnt4_298", default-features = false, features = [ "scalar_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-mnt4-298/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/ed_on_mnt4_298/src/constraints/curves.rs b/ed_on_mnt4_298/src/constraints/curves.rs new file mode 100644 index 0000000..3ceded4 --- /dev/null +++ b/ed_on_mnt4_298/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use crate::*; +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + +use crate::constraints::fields::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::().unwrap(); +} diff --git a/ed_on_mnt4_298/src/constraints/fields.rs b/ed_on_mnt4_298/src/constraints/fields.rs new file mode 100644 index 0000000..f25fa33 --- /dev/null +++ b/ed_on_mnt4_298/src/constraints/fields.rs @@ -0,0 +1,10 @@ +use crate::fq::Fq; +use ark_r1cs_std::fields::fp::FpVar; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_mnt4_298/src/constraints/mod.rs b/ed_on_mnt4_298/src/constraints/mod.rs new file mode 100644 index 0000000..dbafb8b --- /dev/null +++ b/ed_on_mnt4_298/src/constraints/mod.rs @@ -0,0 +1,107 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_mnt4_298`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_mnt4_298::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_mnt4_298::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_mnt4_298/src/lib.rs b/ed_on_mnt4_298/src/lib.rs index 8ded9b4..8fabdf0 100644 --- a/ed_on_mnt4_298/src/lib.rs +++ b/ed_on_mnt4_298/src/lib.rs @@ -21,6 +21,8 @@ //! * a = -1 //! * d = 4212 mod q +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/ed_on_mnt4_753/Cargo.toml b/ed_on_mnt4_753/Cargo.toml index 213a09e..79fb079 100644 --- a/ed_on_mnt4_753/Cargo.toml +++ b/ed_on_mnt4_753/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-mnt4-753 = { path = "../mnt4_753", default-features = false, features = [ "scalar_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-mnt4-753/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/ed_on_mnt4_753/src/constraints/curves.rs b/ed_on_mnt4_753/src/constraints/curves.rs new file mode 100644 index 0000000..fa6fcdd --- /dev/null +++ b/ed_on_mnt4_753/src/constraints/curves.rs @@ -0,0 +1,12 @@ +use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; +use crate::*; + +use crate::constraints::fields::FqVar; + +/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. +pub type EdwardsVar = AffineVar; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::().unwrap(); +} diff --git a/ed_on_mnt4_753/src/constraints/fields.rs b/ed_on_mnt4_753/src/constraints/fields.rs new file mode 100644 index 0000000..681e08e --- /dev/null +++ b/ed_on_mnt4_753/src/constraints/fields.rs @@ -0,0 +1,10 @@ +use ark_r1cs_std::fields::fp::FpVar; +use crate::fq::Fq; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed_on_mnt4_753/src/constraints/mod.rs b/ed_on_mnt4_753/src/constraints/mod.rs new file mode 100644 index 0000000..c221a6f --- /dev/null +++ b/ed_on_mnt4_753/src/constraints/mod.rs @@ -0,0 +1,107 @@ +//! This module implements the R1CS equivalent of `ark_ed_on_mnt4_753`. +//! +//! It implements field variables for `crate::Fq`, +//! and group variables for `crate::GroupProjective`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_ed_on_mnt4_753::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `EdwardsVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_ed_on_mnt4_753::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Edwards` elements. +//! let a_native = EdwardsProjective::rand(&mut rng); +//! let b_native = EdwardsProjective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = EdwardsVar::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = EdwardsVar::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = EdwardsVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `Edwards`. +//! let zero = EdwardsVar::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; diff --git a/ed_on_mnt4_753/src/lib.rs b/ed_on_mnt4_753/src/lib.rs index 505987d..34f8bdd 100644 --- a/ed_on_mnt4_753/src/lib.rs +++ b/ed_on_mnt4_753/src/lib.rs @@ -23,6 +23,8 @@ mod curves; mod fields; +#[cfg(feature = "r1cs")] +pub mod constraints; pub use curves::*; pub use fields::*; diff --git a/mnt4_298/Cargo.toml b/mnt4_298/Cargo.toml index 5d3f510..3900153 100644 --- a/mnt4_298/Cargo.toml +++ b/mnt4_298/Cargo.toml @@ -16,10 +16,13 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" @@ -30,3 +33,4 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ] curve = [ "scalar_field", "base_field" ] scalar_field = [] base_field = [] +r1cs = [ "base_field", "ark-r1cs-std" ] \ No newline at end of file diff --git a/mnt4_298/src/constraints/curves.rs b/mnt4_298/src/constraints/curves.rs new file mode 100644 index 0000000..4640116 --- /dev/null +++ b/mnt4_298/src/constraints/curves.rs @@ -0,0 +1,29 @@ +use crate::Parameters; +use ark_r1cs_std::groups::mnt4; + +/// An element of G1 in the MNT4-298 bilinear group. +pub type G1Var = mnt4::G1Var; +/// An element of G2 in the MNT4-298 bilinear group. +pub type G2Var = mnt4::G2Var; + +/// Represents the cached precomputation that can be performed on a G1 element +/// which enables speeding up pairing computation. +pub type G1PreparedVar = mnt4::G1PreparedVar; +/// Represents the cached precomputation that can be performed on a G2 element +/// which enables speeding up pairing computation. +pub type G2PreparedVar = mnt4::G2PreparedVar; + +#[test] +fn test() { + use ark_ec::models::mnt4::MNT4Parameters; + ark_curve_constraint_tests::curves::sw_test::< + ::G1Parameters, + G1Var, + >() + .unwrap(); + ark_curve_constraint_tests::curves::sw_test::< + ::G2Parameters, + G2Var, + >() + .unwrap(); +} diff --git a/mnt4_298/src/constraints/fields.rs b/mnt4_298/src/constraints/fields.rs new file mode 100644 index 0000000..32f2946 --- /dev/null +++ b/mnt4_298/src/constraints/fields.rs @@ -0,0 +1,26 @@ +use crate::{Fq, Fq2Parameters, Fq4Parameters}; + +use ark_r1cs_std::fields::{fp::FpVar, fp2::Fp2Var, fp4::Fp4Var}; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; +/// A variable that is the R1CS equivalent of `crate::Fq2`. +pub type Fq2Var = Fp2Var; +/// A variable that is the R1CS equivalent of `crate::Fq4`. +pub type Fq4Var = Fp4Var; + +#[test] +fn mnt4_298_field_gadgets_test() { + use super::*; + use crate::{Fq, Fq2, Fq4}; + use ark_curve_constraint_tests::fields::*; + + field_test::<_, _, FqVar>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq2Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq4Var>().unwrap(); + frobenius_tests::(13).unwrap(); +} diff --git a/mnt4_298/src/constraints/mod.rs b/mnt4_298/src/constraints/mod.rs new file mode 100644 index 0000000..81f8d16 --- /dev/null +++ b/mnt4_298/src/constraints/mod.rs @@ -0,0 +1,163 @@ +//! This module implements the R1CS equivalent of `ark_mnt4_298`. +//! +//! It implements field variables for `crate::{Fq, Fq2, Fq4}`, +//! group variables for `crate::{G1, G2}`, and implements constraint +//! generation for computing `MNT4_298::pairing`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_mnt4_298::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `G1Var` and `G2Var`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt4_298::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `G1` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G1Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G1Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G1Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `G1`. +//! let zero = G1Var::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! Finally, one can check pairing computations as well: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_ec::PairingEngine; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt4_298::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate random `G1` and `G2` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G2Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G2Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G2Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let pairing_result_native = MNT4_298::pairing(a_native, b_native); +//! +//! // Prepare `a` and `b` for pairing. +//! let a_prep = constraints::PairingVar::prepare_g1(&a)?; +//! let b_prep = constraints::PairingVar::prepare_g2(&b)?; +//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!(pairing_result.value()?, pairing_result_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; +//! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?; +//! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?; +//! println!("Done here 3"); +//! +//! pairing_result.enforce_equal(&pairing_result_const)?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod fields; +pub use fields::*; + +#[cfg(feature = "curve")] +mod curves; +#[cfg(feature = "curve")] +mod pairing; + +#[cfg(feature = "curve")] +pub use curves::*; +#[cfg(feature = "curve")] +pub use pairing::*; diff --git a/mnt4_298/src/constraints/pairing.rs b/mnt4_298/src/constraints/pairing.rs new file mode 100644 index 0000000..7941ad0 --- /dev/null +++ b/mnt4_298/src/constraints/pairing.rs @@ -0,0 +1,10 @@ +use crate::Parameters; + +/// Specifies the constraints for computing a pairing in the MNT4-298 bilinear group. +pub type PairingVar = ark_r1cs_std::pairing::mnt4::PairingVar; + +#[test] +fn test() { + use crate::MNT4_298; + ark_curve_constraint_tests::pairing::bilinearity_test::().unwrap() +} diff --git a/mnt4_298/src/lib.rs b/mnt4_298/src/lib.rs index 1847b0a..0be2cfc 100644 --- a/mnt4_298/src/lib.rs +++ b/mnt4_298/src/lib.rs @@ -33,6 +33,9 @@ mod curves; #[cfg(any(feature = "scalar_field", feature = "base_field"))] mod fields; +#[cfg(feature = "r1cs")] +pub mod constraints; + #[cfg(feature = "curve")] pub use curves::*; #[cfg(any(feature = "scalar_field", feature = "base_field"))] diff --git a/mnt4_753/Cargo.toml b/mnt4_753/Cargo.toml index d025205..13993bc 100644 --- a/mnt4_753/Cargo.toml +++ b/mnt4_753/Cargo.toml @@ -16,10 +16,13 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" @@ -30,3 +33,4 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ] curve = [ "scalar_field", "base_field" ] scalar_field = [] base_field = [] +r1cs = [ "base_field", "ark-r1cs-std" ] \ No newline at end of file diff --git a/mnt4_753/src/constraints/curves.rs b/mnt4_753/src/constraints/curves.rs new file mode 100644 index 0000000..febfeed --- /dev/null +++ b/mnt4_753/src/constraints/curves.rs @@ -0,0 +1,29 @@ +use crate::Parameters; +use ark_r1cs_std::groups::mnt4; + +/// An element of G1 in the MNT4-753 bilinear group. +pub type G1Var = mnt4::G1Var; +/// An element of G2 in the MNT4-753 bilinear group. +pub type G2Var = mnt4::G2Var; + +/// Represents the cached precomputation that can be performed on a G1 element +/// which enables speeding up pairing computation. +pub type G1PreparedVar = mnt4::G1PreparedVar; +/// Represents the cached precomputation that can be performed on a G2 element +/// which enables speeding up pairing computation. +pub type G2PreparedVar = mnt4::G2PreparedVar; + +#[test] +fn test() { + use ark_ec::models::mnt4::MNT4Parameters; + ark_curve_constraint_tests::curves::sw_test::< + ::G1Parameters, + G1Var, + >() + .unwrap(); + ark_curve_constraint_tests::curves::sw_test::< + ::G2Parameters, + G2Var, + >() + .unwrap(); +} diff --git a/mnt4_753/src/constraints/fields.rs b/mnt4_753/src/constraints/fields.rs new file mode 100644 index 0000000..d99ed86 --- /dev/null +++ b/mnt4_753/src/constraints/fields.rs @@ -0,0 +1,26 @@ +use crate::{Fq, Fq2Parameters, Fq4Parameters}; + +use ark_r1cs_std::fields::{fp::FpVar, fp2::Fp2Var, fp4::Fp4Var}; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; +/// A variable that is the R1CS equivalent of `crate::Fq2`. +pub type Fq2Var = Fp2Var; +/// A variable that is the R1CS equivalent of `crate::Fq4`. +pub type Fq4Var = Fp4Var; + +#[test] +fn mnt4_753_field_gadgets_test() { + use super::*; + use crate::{Fq, Fq2, Fq4}; + use ark_curve_constraint_tests::fields::*; + + field_test::<_, _, FqVar>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq2Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq4Var>().unwrap(); + frobenius_tests::(13).unwrap(); +} diff --git a/mnt4_753/src/constraints/mod.rs b/mnt4_753/src/constraints/mod.rs new file mode 100644 index 0000000..e84643f --- /dev/null +++ b/mnt4_753/src/constraints/mod.rs @@ -0,0 +1,163 @@ +//! This module implements the R1CS equivalent of `ark_mnt4_753`. +//! +//! It implements field variables for `crate::{Fq, Fq2, Fq4}`, +//! group variables for `crate::{G1, G2}`, and implements constraint +//! generation for computing `MNT4_753::pairing`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_mnt4_753::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `G1Var` and `G2Var`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt4_753::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `G1` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G1Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G1Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G1Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `G1`. +//! let zero = G1Var::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! Finally, one can check pairing computations as well: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_ec::PairingEngine; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt4_753::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate random `G1` and `G2` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G2Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G2Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G2Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let pairing_result_native = MNT4_753::pairing(a_native, b_native); +//! +//! // Prepare `a` and `b` for pairing. +//! let a_prep = constraints::PairingVar::prepare_g1(&a)?; +//! let b_prep = constraints::PairingVar::prepare_g2(&b)?; +//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!(pairing_result.value()?, pairing_result_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; +//! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?; +//! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?; +//! println!("Done here 3"); +//! +//! pairing_result.enforce_equal(&pairing_result_const)?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod fields; +pub use fields::*; + +#[cfg(feature = "curve")] +mod curves; +#[cfg(feature = "curve")] +mod pairing; + +#[cfg(feature = "curve")] +pub use curves::*; +#[cfg(feature = "curve")] +pub use pairing::*; diff --git a/mnt4_753/src/constraints/pairing.rs b/mnt4_753/src/constraints/pairing.rs new file mode 100644 index 0000000..3e00df4 --- /dev/null +++ b/mnt4_753/src/constraints/pairing.rs @@ -0,0 +1,10 @@ +use crate::Parameters; + +/// Specifies the constraints for computing a pairing in the MNT4-753 bilinear group. +pub type PairingVar = ark_r1cs_std::pairing::mnt4::PairingVar; + +#[test] +fn test() { + use crate::MNT4_753; + ark_curve_constraint_tests::pairing::bilinearity_test::().unwrap() +} diff --git a/mnt4_753/src/lib.rs b/mnt4_753/src/lib.rs index 75cfffc..4ecc23d 100644 --- a/mnt4_753/src/lib.rs +++ b/mnt4_753/src/lib.rs @@ -27,6 +27,8 @@ //! * B = Fq2(0, b * NON_RESIDUE) //! * NON_RESIDUE = 13 is the quadratic non-residue used to construct the extension field Fq2 +#[cfg(feature = "r1cs")] +pub mod constraints; #[cfg(feature = "curve")] mod curves; #[cfg(any(feature = "scalar_field", feature = "base_field"))] diff --git a/mnt6_298/Cargo.toml b/mnt6_298/Cargo.toml index 7d3af93..d8ad611 100644 --- a/mnt6_298/Cargo.toml +++ b/mnt6_298/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-mnt4-298 = { path = "../mnt4_298", default-features = false, features = [ "scalar_field", "base_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ] +r1cs = [ "ark-r1cs-std" ] \ No newline at end of file diff --git a/mnt6_298/src/constraints/curves.rs b/mnt6_298/src/constraints/curves.rs new file mode 100644 index 0000000..069ee9e --- /dev/null +++ b/mnt6_298/src/constraints/curves.rs @@ -0,0 +1,29 @@ +use crate::Parameters; +use ark_r1cs_std::groups::mnt6; + +/// An element of G1 in the MNT6-298 bilinear group. +pub type G1Var = mnt6::G1Var; +/// An element of G2 in the MNT6-298 bilinear group. +pub type G2Var = mnt6::G2Var; + +/// Represents the cached precomputation that can be performed on a G1 element +/// which enables speeding up pairing computation. +pub type G1PreparedVar = mnt6::G1PreparedVar; +/// Represents the cached precomputation that can be performed on a G2 element +/// which enables speeding up pairing computation. +pub type G2PreparedVar = mnt6::G2PreparedVar; + +#[test] +fn test() { + use ark_ec::models::mnt6::MNT6Parameters; + ark_curve_constraint_tests::curves::sw_test::< + ::G1Parameters, + G1Var, + >() + .unwrap(); + ark_curve_constraint_tests::curves::sw_test::< + ::G2Parameters, + G2Var, + >() + .unwrap(); +} diff --git a/mnt6_298/src/constraints/fields.rs b/mnt6_298/src/constraints/fields.rs new file mode 100644 index 0000000..045db64 --- /dev/null +++ b/mnt6_298/src/constraints/fields.rs @@ -0,0 +1,26 @@ +use crate::{Fq, Fq3Parameters, Fq6Parameters}; + +use ark_r1cs_std::fields::{fp::FpVar, fp3::Fp3Var, fp6_2over3::Fp6Var}; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; +/// A variable that is the R1CS equivalent of `crate::Fq3`. +pub type Fq3Var = Fp3Var; +/// A variable that is the R1CS equivalent of `crate::Fq6`. +pub type Fq6Var = Fp6Var; + +#[test] +fn mnt6_298_field_gadgets_test() { + use super::*; + use crate::{Fq, Fq3, Fq6}; + use ark_curve_constraint_tests::fields::*; + + field_test::<_, _, FqVar>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq3Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq6Var>().unwrap(); + frobenius_tests::(13).unwrap(); +} diff --git a/mnt6_298/src/constraints/mod.rs b/mnt6_298/src/constraints/mod.rs new file mode 100644 index 0000000..e4f3ad1 --- /dev/null +++ b/mnt6_298/src/constraints/mod.rs @@ -0,0 +1,158 @@ +//! This module implements the R1CS equivalent of `ark_mnt6_298`. +//! +//! It implements field variables for `crate::{Fq, Fq3, Fq6}`, +//! group variables for `crate::{G1, G2}`, and implements constraint +//! generation for computing `MNT6_298::pairing`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_mnt6_298::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `G1Var` and `G2Var`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt6_298::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `G1` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G1Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G1Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G1Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `G1`. +//! let zero = G1Var::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! Finally, one can check pairing computations as well: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_ec::PairingEngine; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt6_298::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate random `G1` and `G2` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G2Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G2Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G2Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let pairing_result_native = MNT6_298::pairing(a_native, b_native); +//! +//! // Prepare `a` and `b` for pairing. +//! let a_prep = constraints::PairingVar::prepare_g1(&a)?; +//! let b_prep = constraints::PairingVar::prepare_g2(&b)?; +//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!(pairing_result.value()?, pairing_result_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; +//! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?; +//! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?; +//! println!("Done here 3"); +//! +//! pairing_result.enforce_equal(&pairing_result_const)?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; +mod pairing; + +pub use curves::*; +pub use fields::*; +pub use pairing::*; diff --git a/mnt6_298/src/constraints/pairing.rs b/mnt6_298/src/constraints/pairing.rs new file mode 100644 index 0000000..14641be --- /dev/null +++ b/mnt6_298/src/constraints/pairing.rs @@ -0,0 +1,10 @@ +use crate::Parameters; + +/// Specifies the constraints for computing a pairing in the MNT6-298 bilinear group. +pub type PairingVar = ark_r1cs_std::pairing::mnt6::PairingVar; + +#[test] +fn test() { + use crate::MNT6_298; + ark_curve_constraint_tests::pairing::bilinearity_test::().unwrap() +} diff --git a/mnt6_298/src/lib.rs b/mnt6_298/src/lib.rs index 8c5c53e..3bd742e 100644 --- a/mnt6_298/src/lib.rs +++ b/mnt6_298/src/lib.rs @@ -28,6 +28,8 @@ //! * B = Fq2(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 5 is the cubic non-residue used to construct the field extension Fq3 +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields; diff --git a/mnt6_753/Cargo.toml b/mnt6_753/Cargo.toml index 6b7d02e..54d309c 100644 --- a/mnt6_753/Cargo.toml +++ b/mnt6_753/Cargo.toml @@ -16,14 +16,18 @@ edition = "2018" ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true } ark-mnt4-753 = { path = "../mnt4_753", default-features = false, features = [ "scalar_field", "base_field" ] } [dev-dependencies] +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false } ark-curve-tests = { path = "../curve-tests", default-features = false } +ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false } rand = { version = "0.7", default-features = false } rand_xorshift = "0.2" [features] default = [] std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ] +r1cs = ["ark-r1cs-std"] \ No newline at end of file diff --git a/mnt6_753/src/constraints/curves.rs b/mnt6_753/src/constraints/curves.rs new file mode 100644 index 0000000..e747fd2 --- /dev/null +++ b/mnt6_753/src/constraints/curves.rs @@ -0,0 +1,29 @@ +use crate::Parameters; +use ark_r1cs_std::groups::mnt6; + +/// An element of G1 in the MNT6-753 bilinear group. +pub type G1Var = mnt6::G1Var; +/// An element of G2 in the MNT6-753 bilinear group. +pub type G2Var = mnt6::G2Var; + +/// Represents the cached precomputation that can be performed on a G1 element +/// which enables speeding up pairing computation. +pub type G1PreparedVar = mnt6::G1PreparedVar; +/// Represents the cached precomputation that can be performed on a G2 element +/// which enables speeding up pairing computation. +pub type G2PreparedVar = mnt6::G2PreparedVar; + +#[test] +fn test() { + use ark_ec::models::mnt6::MNT6Parameters; + ark_curve_constraint_tests::curves::sw_test::< + ::G1Parameters, + G1Var, + >() + .unwrap(); + ark_curve_constraint_tests::curves::sw_test::< + ::G2Parameters, + G2Var, + >() + .unwrap(); +} diff --git a/mnt6_753/src/constraints/fields.rs b/mnt6_753/src/constraints/fields.rs new file mode 100644 index 0000000..de156ee --- /dev/null +++ b/mnt6_753/src/constraints/fields.rs @@ -0,0 +1,26 @@ +use crate::{Fq, Fq3Parameters, Fq6Parameters}; + +use ark_r1cs_std::fields::{fp::FpVar, fp3::Fp3Var, fp6_2over3::Fp6Var}; + +/// A variable that is the R1CS equivalent of `crate::Fq`. +pub type FqVar = FpVar; +/// A variable that is the R1CS equivalent of `crate::Fq3`. +pub type Fq3Var = Fp3Var; +/// A variable that is the R1CS equivalent of `crate::Fq6`. +pub type Fq6Var = Fp6Var; + +#[test] +fn mnt6_753_field_gadgets_test() { + use super::*; + use crate::{Fq, Fq3, Fq6}; + use ark_curve_constraint_tests::fields::*; + + field_test::<_, _, FqVar>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq3Var>().unwrap(); + frobenius_tests::(13).unwrap(); + + field_test::<_, _, Fq6Var>().unwrap(); + frobenius_tests::(13).unwrap(); +} diff --git a/mnt6_753/src/constraints/mod.rs b/mnt6_753/src/constraints/mod.rs new file mode 100644 index 0000000..c3d6179 --- /dev/null +++ b/mnt6_753/src/constraints/mod.rs @@ -0,0 +1,158 @@ +//! This module implements the R1CS equivalent of `ark_mnt6_753`. +//! +//! It implements field variables for `crate::{Fq, Fq3, Fq6}`, +//! group variables for `crate::{G1, G2}`, and implements constraint +//! generation for computing `MNT6_753::pairing`. +//! +//! The field underlying these constraints is `crate::Fq`. +//! +//! # Examples +//! +//! One can perform standard algebraic operations on `FqVar`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! use ark_ff::UniformRand; +//! use ark_relations::r1cs::*; +//! use ark_r1cs_std::prelude::*; +//! use ark_mnt6_753::{*, constraints::*}; +//! +//! let cs = ConstraintSystem::::new_ref(); +//! // This rng is just for test purposes; do not use it +//! // in real applications. +//! let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `Fq` elements. +//! let a_native = Fq::rand(&mut rng); +//! let b_native = Fq::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = FqVar::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; +//! let b = FqVar::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = FqVar::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = FqVar::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let one = FqVar::one(); +//! let zero = FqVar::zero(); +//! +//! // Sanity check one + one = two +//! let two = &one + &one + &zero; +//! two.enforce_equal(&one.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that the value of &a * &b is correct. +//! assert_eq!((&a * &b).value()?, a_native * &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! One can also perform standard algebraic operations on `G1Var` and `G2Var`: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt6_753::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate some random `G1` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G1Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G1Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G1Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! // This returns the identity of `G1`. +//! let zero = G1Var::zero(); +//! +//! // Sanity check one + one = two +//! let two_a = &a + &a + &zero; +//! two_a.enforce_equal(&a.double()?)?; +//! +//! assert!(cs.is_satisfied()?); +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!((&a + &b).value()?, a_native + &b_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! (&a + &b).enforce_equal(&(&a_const + &b_const))?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` +//! +//! Finally, one can check pairing computations as well: +//! +//! ``` +//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { +//! # use ark_ff::UniformRand; +//! # use ark_ec::PairingEngine; +//! # use ark_relations::r1cs::*; +//! # use ark_r1cs_std::prelude::*; +//! # use ark_mnt6_753::{*, constraints::*}; +//! +//! # let cs = ConstraintSystem::::new_ref(); +//! # let mut rng = ark_ff::test_rng(); +//! +//! // Generate random `G1` and `G2` elements. +//! let a_native = G1Projective::rand(&mut rng); +//! let b_native = G2Projective::rand(&mut rng); +//! +//! // Allocate `a_native` and `b_native` as witness variables in `cs`. +//! let a = G1Var::new_witness(ark_relations::ns!(cs, "a"), || Ok(a_native))?; +//! let b = G2Var::new_witness(ark_relations::ns!(cs, "b"), || Ok(b_native))?; +//! +//! // Allocate `a_native` and `b_native` as constants in `cs`. This does not add any +//! // constraints or variables. +//! let a_const = G1Var::new_constant(ark_relations::ns!(cs, "a_as_constant"), a_native)?; +//! let b_const = G2Var::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; +//! +//! let pairing_result_native = MNT6_753::pairing(a_native, b_native); +//! +//! // Prepare `a` and `b` for pairing. +//! let a_prep = constraints::PairingVar::prepare_g1(&a)?; +//! let b_prep = constraints::PairingVar::prepare_g2(&b)?; +//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?; +//! +//! // Check that the value of &a + &b is correct. +//! assert_eq!(pairing_result.value()?, pairing_result_native); +//! +//! // Check that operations on variables and constants are equivalent. +//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?; +//! let b_prep_const = constraints::PairingVar::prepare_g2(&b_const)?; +//! let pairing_result_const = constraints::PairingVar::pairing(a_prep_const, b_prep_const)?; +//! println!("Done here 3"); +//! +//! pairing_result.enforce_equal(&pairing_result_const)?; +//! assert!(cs.is_satisfied()?); +//! # Ok(()) +//! # } +//! ``` + +mod curves; +mod fields; +mod pairing; + +pub use curves::*; +pub use fields::*; +pub use pairing::*; diff --git a/mnt6_753/src/constraints/pairing.rs b/mnt6_753/src/constraints/pairing.rs new file mode 100644 index 0000000..8979aec --- /dev/null +++ b/mnt6_753/src/constraints/pairing.rs @@ -0,0 +1,10 @@ +use crate::Parameters; + +/// Specifies the constraints for computing a pairing in the MNT6-753 bilinear group. +pub type PairingVar = ark_r1cs_std::pairing::mnt6::PairingVar; + +#[test] +fn test() { + use crate::MNT6_753; + ark_curve_constraint_tests::pairing::bilinearity_test::().unwrap() +} diff --git a/mnt6_753/src/lib.rs b/mnt6_753/src/lib.rs index 9eb1609..ab3d55e 100644 --- a/mnt6_753/src/lib.rs +++ b/mnt6_753/src/lib.rs @@ -27,6 +27,8 @@ //! * B = Fq3(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 11 is the cubic non-residue used to construct the extension field Fq3 +#[cfg(feature = "r1cs")] +pub mod constraints; mod curves; mod fields;