diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb306b5..5b7585a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,14 +117,5 @@ jobs: - name: r1cs-std run: | - cd r1cs-std - cargo build -p r1cs-std --no-default-features --target aarch64-unknown-none - cargo check --examples -p r1cs-std --no-default-features --target aarch64-unknown-none - cd .. - - - name: crypto-primitives - run: | - cd crypto-primitives - cargo build -p crypto-primitives --no-default-features --target aarch64-unknown-none - cargo check --examples -p crypto-primitives --no-default-features --target aarch64-unknown-none - cd .. + cargo build --no-default-features --target aarch64-unknown-none + cargo check --examples --no-default-features --target aarch64-unknown-none diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 39f2ca6..0000000 --- a/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -Sean Bowe -Alessandro Chiesa -Matthew Green -Ian Miers -Pratyush Mishra -Howard Wu diff --git a/Cargo.toml b/Cargo.toml index 1feea1c..518b6d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,30 +1,35 @@ -[workspace] +[package] +name = "ark-r1cs-std" +version = "0.1.0" +authors = [ "arkworks contributors" ] +description = "A standard library for constraint system gadgets" +homepage = "https://arworks.rs" +repository = "https://github.com/arkworks/r1cs-gadgets" +documentation = "https://docs.rs/ark-r1cs-std/" +keywords = ["zero knowledge", "cryptography", "zkSNARK", "SNARK", "r1cs"] +categories = ["cryptography"] +include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +license = "MIT/Apache-2.0" +edition = "2018" -members = [ - "cp-benches", - "crypto-primitives", - "r1cs-std", -] +[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-std = { git = "https://github.com/arkworks-rs/utils", default-features = false } +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false } -[profile.release] -opt-level = 3 -lto = "thin" -incremental = true +derivative = { version = "2", features = ["use_core"] } +tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } -[profile.bench] -opt-level = 3 -debug = false -rpath = false -lto = "thin" -incremental = true -debug-assertions = false +[build-dependencies] +rustc_version = "0.2" -[profile.dev] -opt-level = 0 +[dev-dependencies] +rand = { version = "0.7", default-features = false } +rand_xorshift = "0.2" +ark-test-curves = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = ["bls12_381_scalar_field"] } -[profile.test] -opt-level = 3 -lto = "thin" -incremental = true -debug-assertions = true -debug = true +[features] +default = ["std"] +std = [ "ark-ff/std", "ark-relations/std", "ark-std/std" ] +parallel = [ "std", "ark-ff/parallel" ] diff --git a/README.md b/README.md index 5ce72e3..9312c85 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,18 @@ -

ZEXE (Zero knowledge EXEcution)

+

ark-r1cs-std

- - - - - + + + +

-___ZEXE___ (pronounced */zeksÄ“/*) is a Rust library for decentralized private computation. +The arkworks ecosystem consist of Rust libraries for designing and working with __zero knowledge succinct non-interactive arguments (zkSNARKs)__. This repository contains efficient implementations of constraint "gadgets" that enable checking common computations inside SNARKs, such as bit operations, finite field arithmetic, elliptic curve arithmetic, and pairings. - -This library was initially developed as part of the paper *"[ZEXE: Enabling Decentralized Private Computation][zexe]"*, and it is released under the MIT License and the Apache v2 License (see [License](#license)). +This library is released under the MIT License and the Apache v2 License (see [License](#license)). **WARNING:** This is an academic proof-of-concept prototype, and in particular has not received careful code review. This implementation is NOT ready for production use. -## Overview - -This library implements a ledger-based system that enables users to execute offline computations and subsequently produce publicly-verifiable transactions that attest to the correctness of these offline executions. The transactions contain *zero-knowledge succinct arguments* (zkSNARKs) attesting to the correctness of the offline computations, and provide strong notions of privacy and succinctness. - -- **Privacy** - transactions reveal no information about the offline computation. -- **Succinctness** - transactions can be validated in time that is independent of the offline computation. -- **Application isolation** - malicious applications cannot affect the execution of honest applications. -- **Application interaction** - applications can safely communicate with each other. - -Informally, the library provides the ability to create transactions that run arbitrary (Turing-complete) scripts on hidden data stored on the ledger. In more detail, the library implements a cryptographic primitive known as *decentralized private computation* (DPC) schemes, which are described in detail in the [ZEXE paper][zexe]. - -## Directory structure - -This repository contains several Rust crates that implement the different building blocks of ZEXE. The high-level structure of the repository is as follows. - -* [`algebra-core`](algebra-core): Rust crate that provides generic arithmetic for finite fields and elliptic curves -* [`algebra`](algebra): Rust crate that provides concrete instantiations of some finite fields and elliptic curves -* [`crypto-primitives`](crypto-primitives): Rust crate that implements some useful cryptographic primitives (and constraints for them) -* [`dpc`](dpc): Rust crate that implements DPC schemes (the main cryptographic primitive in this repository) -* [`ff-fft`](ff-fft): Rust crate that provides efficient finite field polynomial arithmetic based on finite field FFTs -* [`r1cs-core`](r1cs-core): Rust crate that defines core interfaces for a Rank-1 Constraint System (R1CS) -* [`r1cs-std`](r1cs-std): Rust crate that provides various gadgets used to construct R1CS -* [`gm17`](gm17): Rust crate that implements the zkSNARK of [Groth and Maller][GM17] -* [`groth16`](groth16): Rust crate that implements the zkSNARK of [Groth][Groth16] - - -In addition, there is a [`bench-utils`](bench-utils) crate which contains infrastructure for benchmarking. This crate includes macros for timing code segments and is used for profiling the building blocks of ZEXE. - -[GM17]: https://ia.cr/2017/540 -[Groth16]: https://ia.cr/2016/260 - - ## Build guide The library compiles on the `stable` toolchain of the Rust compiler. To install the latest version of Rust, first install `rustup` by following the instructions [here](https://rustup.rs/), or via your platform's package manager. Once `rustup` is installed, install the Rust toolchain by invoking: @@ -56,8 +22,7 @@ rustup install stable After that, use `cargo`, the standard Rust build tool, to build the library: ```bash -git clone https://github.com/scipr-lab/zexe.git -cd zexe/dpc +git clone https://github.com/arkworks-rs/r1cs-std.git cargo build --release ``` @@ -66,44 +31,14 @@ This library comes with unit tests for each of the provided crates. Run the test cargo test ``` -This library comes with benchmarks for the following crates: - -- [`algebra`](algebra) -- [`dpc`](dpc) - -These benchmarks require the nightly Rust toolchain; to install this, run `rustup install nightly`. Then, to run benchmarks, run the following command: -```bash -cargo +nightly bench -``` - -Compiling with `adcxq`, `adoxq` and `mulxq` instructions can lead to a 30-70% speedup. These are available on most `x86_64` platforms (Broadwell onwards for Intel and Ryzen onwards for AMD). Run the following command: -```bash -RUSTFLAGS="-C target-feature=+bmi2,+adx" cargo +nightly test/build/bench --features asm -``` -Tip: If optimising for performance, your mileage may vary with passing `--emit=asm` to `RUSTFLAGS`. - -To bench `algebra-benches` with greater accuracy, especially for functions with execution times on the order of nanoseconds, use the `n_fold` feature to run selected functions 1000x per iteration. To run with multiple features, make sure to double quote the features. -```bash -cargo +nightly bench --features "n_fold bls12_381" -``` - - ## License -ZEXE is licensed under either of the following licenses, at your discretion. +This library is licensed under either of the following licenses, at your discretion. * Apache License Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -Unless you explicitly state otherwise, any contribution submitted for inclusion in ZEXE by you shall be dual licensed as above (as defined in the Apache v2 License), without any additional terms or conditions. - -[zexe]: https://ia.cr/2018/962 - -## Reference paper - -[_ZEXE: Enabling Decentralized Private Computation_][zexe] -[Sean Bowe](https://www.github.com/ebfull), Alessandro Chiesa, Matthew Green, Ian Miers, [Pratyush Mishra](https://www.github.com/pratyush), [Howard Wu](https://www.github.com/howardwu) -*IEEE S&P 2020* (*IACR ePrint Report 2018/962*) +Unless you explicitly state otherwise, any contribution submitted for inclusion in this library by you shall be dual licensed as above (as defined in the Apache v2 License), without any additional terms or conditions. ## Acknowledgements @@ -113,4 +48,6 @@ the National Science Foundation; the UC Berkeley Center for Long-Term Cybersecurity; and donations from the Ethereum Foundation, the Interchain Foundation, and Qtum. -Some parts of the finite field arithmetic, elliptic curve arithmetic, FFTs, and multi-threading infrastructure in the `algebra` crate have been adapted from code in the [`ff`](https://github.com/zkcrypto/ff), [`pairing`](https://github.com/zkcrypto/pairing), and [`bellman`](https://github.com/zkcrypto/bellman) crates, developed by [Sean Bowe](https://www.github.com/ebfull) and others from Zcash. +An earlier version of this library was developed as part of the paper *"[ZEXE: Enabling Decentralized Private Computation][zexe]"*. + +[zexe]: https://ia.cr/2018/962 \ No newline at end of file diff --git a/cp-benches/Cargo.toml b/cp-benches/Cargo.toml deleted file mode 100644 index 0c1801e..0000000 --- a/cp-benches/Cargo.toml +++ /dev/null @@ -1,52 +0,0 @@ -[package] -name = "cp-benches" -version = "0.1.1-alpha.0" -authors = [ - "Sean Bowe", - "Alessandro Chiesa", - "Matthew Green", - "Ian Miers", - "Pratyush Mishra", - "Howard Wu" -] -description = "A library of cryptographic primitives that are used by Zexe" -homepage = "https://libzexe.org" -repository = "https://github.com/scipr/zexe" -documentation = "https://docs.rs/crypto-primitives/" -keywords = ["r1cs", "groth16", "gm17", "pedersen", "blake2s"] -categories = ["cryptography"] -include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] -license = "MIT/Apache-2.0" -edition = "2018" - -################################# Dependencies ################################ - -[dev-dependencies] -algebra = { git = "https://github.com/scipr-lab/zexe/", default-features = false, features = [ "ed_on_bls12_377" ] } -blake2 = { version = "0.8", default-features = false } -criterion = "0.3.1" -crypto-primitives = { path = "../crypto-primitives" } -rand = { version = "0.7" } -rand_xorshift = { version = "0.2" } - -################################# Benchmarks ################################## - -[[bench]] -name = "pedersen_crh" -path = "benches/crypto_primitives/crh.rs" -harness = false - -[[bench]] -name = "pedersen_comm" -path = "benches/crypto_primitives/comm.rs" -harness = false - -[[bench]] -name = "blake2s_prf" -path = "benches/crypto_primitives/prf.rs" -harness = false - -[[bench]] -name = "schnorr_sig" -path = "benches/crypto_primitives/signature.rs" -harness = false diff --git a/cp-benches/benches/crypto_primitives/comm.rs b/cp-benches/benches/crypto_primitives/comm.rs deleted file mode 100644 index 759c687..0000000 --- a/cp-benches/benches/crypto_primitives/comm.rs +++ /dev/null @@ -1,53 +0,0 @@ -use rand; - -#[macro_use] -extern crate criterion; - -use algebra::{ed_on_bls12_377::EdwardsProjective as Edwards, UniformRand}; -use criterion::Criterion; -use crypto_primitives::commitment::{pedersen::*, CommitmentScheme}; - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct CommWindow; - -impl Window for CommWindow { - const WINDOW_SIZE: usize = 250; - const NUM_WINDOWS: usize = 8; -} - -fn pedersen_comm_setup(c: &mut Criterion) { - c.bench_function("Pedersen Commitment Setup", move |b| { - b.iter(|| { - let mut rng = &mut rand::thread_rng(); - Commitment::::setup(&mut rng).unwrap() - }) - }); -} - -fn pedersen_comm_eval(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = Commitment::::setup(&mut rng).unwrap(); - let input = vec![5u8; 128]; - c.bench_function("Pedersen Commitment Eval", move |b| { - b.iter(|| { - let rng = &mut rand::thread_rng(); - let commitment_randomness = Randomness::rand(rng); - Commitment::::commit(¶meters, &input, &commitment_randomness) - .unwrap() - }) - }); -} - -criterion_group! { - name = comm_setup; - config = Criterion::default().sample_size(10); - targets = pedersen_comm_setup -} - -criterion_group! { - name = comm_eval; - config = Criterion::default().sample_size(10); - targets = pedersen_comm_eval -} - -criterion_main!(comm_setup, comm_eval); diff --git a/cp-benches/benches/crypto_primitives/crh.rs b/cp-benches/benches/crypto_primitives/crh.rs deleted file mode 100644 index 3157cef..0000000 --- a/cp-benches/benches/crypto_primitives/crh.rs +++ /dev/null @@ -1,48 +0,0 @@ -use rand; - -#[macro_use] -extern crate criterion; - -use algebra::ed_on_bls12_377::EdwardsProjective as Edwards; -use criterion::Criterion; -use crypto_primitives::crh::{pedersen::*, FixedLengthCRH}; - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct HashWindow; - -impl Window for HashWindow { - const WINDOW_SIZE: usize = 250; - const NUM_WINDOWS: usize = 8; -} - -fn pedersen_crh_setup(c: &mut Criterion) { - c.bench_function("Pedersen CRH Setup", move |b| { - b.iter(|| { - let mut rng = &mut rand::thread_rng(); - CRH::::setup(&mut rng).unwrap() - }) - }); -} - -fn pedersen_crh_eval(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = CRH::::setup(&mut rng).unwrap(); - let input = vec![5u8; 128]; - c.bench_function("Pedersen CRH Eval", move |b| { - b.iter(|| CRH::::evaluate(¶meters, &input).unwrap()) - }); -} - -criterion_group! { - name = crh_setup; - config = Criterion::default().sample_size(10); - targets = pedersen_crh_setup -} - -criterion_group! { - name = crh_eval; - config = Criterion::default().sample_size(10); - targets = pedersen_crh_eval -} - -criterion_main!(crh_setup, crh_eval); diff --git a/cp-benches/benches/crypto_primitives/prf.rs b/cp-benches/benches/crypto_primitives/prf.rs deleted file mode 100644 index fc355fd..0000000 --- a/cp-benches/benches/crypto_primitives/prf.rs +++ /dev/null @@ -1,25 +0,0 @@ -use rand; - -#[macro_use] -extern crate criterion; - -use criterion::Criterion; -use crypto_primitives::prf::*; -use rand::Rng; - -fn blake2s_prf_eval(c: &mut Criterion) { - let rng = &mut rand::thread_rng(); - let input: [u8; 32] = rng.gen(); - let seed: [u8; 32] = rng.gen(); - c.bench_function("Blake2s PRF Eval", move |b| { - b.iter(|| Blake2s::evaluate(&seed, &input).unwrap()) - }); -} - -criterion_group! { - name = prf_eval; - config = Criterion::default().sample_size(50); - targets = blake2s_prf_eval -} - -criterion_main!(prf_eval); diff --git a/cp-benches/benches/crypto_primitives/signature.rs b/cp-benches/benches/crypto_primitives/signature.rs deleted file mode 100644 index b53d4bc..0000000 --- a/cp-benches/benches/crypto_primitives/signature.rs +++ /dev/null @@ -1,89 +0,0 @@ -#[macro_use] -extern crate criterion; - -use algebra::ed_on_bls12_377::EdwardsProjective as Edwards; -use blake2::Blake2s; -use criterion::Criterion; -use crypto_primitives::signature::{schnorr::*, SignatureScheme}; -use rand::{self, Rng}; - -type SchnorrEdwards = Schnorr; -fn schnorr_signature_setup(c: &mut Criterion) { - c.bench_function("SchnorrEdwards: Setup", move |b| { - b.iter(|| { - let mut rng = &mut rand::thread_rng(); - SchnorrEdwards::setup(&mut rng).unwrap() - }) - }); -} - -fn schnorr_signature_keygen(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = SchnorrEdwards::setup(&mut rng).unwrap(); - - c.bench_function("SchnorrEdwards: KeyGen", move |b| { - b.iter(|| { - let mut rng = &mut rand::thread_rng(); - SchnorrEdwards::keygen(¶meters, &mut rng).unwrap() - }) - }); -} - -fn schnorr_signature_sign(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = SchnorrEdwards::setup(&mut rng).unwrap(); - let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap(); - let message = [100u8; 128]; - - c.bench_function("SchnorrEdwards: Sign", move |b| { - b.iter(|| { - let mut rng = &mut rand::thread_rng(); - SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap() - }) - }); -} - -fn schnorr_signature_verify(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = SchnorrEdwards::setup(&mut rng).unwrap(); - let (pk, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap(); - let message = [100u8; 128]; - let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap(); - - c.bench_function("SchnorrEdwards: Verify", move |b| { - b.iter(|| SchnorrEdwards::verify(¶meters, &pk, &message, &signature).unwrap()) - }); -} - -fn schnorr_signature_randomize_pk(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = SchnorrEdwards::setup(&mut rng).unwrap(); - let (pk, _) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap(); - let randomness: [u8; 32] = rng.gen(); - - c.bench_function("SchnorrEdwards: Randomize PubKey", move |b| { - b.iter(|| SchnorrEdwards::randomize_public_key(¶meters, &pk, &randomness).unwrap()) - }); -} - -fn schnorr_signature_randomize_signature(c: &mut Criterion) { - let mut rng = &mut rand::thread_rng(); - let parameters = SchnorrEdwards::setup(&mut rng).unwrap(); - let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap(); - let randomness: [u8; 32] = rng.gen(); - let message = [100u8; 128]; - let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap(); - - c.bench_function("SchnorrEdwards: Randomize Signature", move |b| { - b.iter(|| { - SchnorrEdwards::randomize_signature(¶meters, &signature, &randomness).unwrap() - }) - }); -} -criterion_group! { - name = schnorr_sig; - config = Criterion::default().sample_size(20); - targets = schnorr_signature_setup, schnorr_signature_keygen, schnorr_signature_sign, - schnorr_signature_verify, schnorr_signature_randomize_pk, schnorr_signature_randomize_signature -} -criterion_main!(schnorr_sig); diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml deleted file mode 100644 index b8751dd..0000000 --- a/crypto-primitives/Cargo.toml +++ /dev/null @@ -1,52 +0,0 @@ -[package] -name = "crypto-primitives" -version = "0.1.1-alpha.0" -authors = [ - "Sean Bowe", - "Alessandro Chiesa", - "Matthew Green", - "Ian Miers", - "Pratyush Mishra", - "Howard Wu" -] -description = "A library of cryptographic primitives that are used by Zexe" -homepage = "https://libzexe.org" -repository = "https://github.com/scipr/zexe" -documentation = "https://docs.rs/crypto-primitives/" -keywords = ["r1cs", "groth16", "gm17", "pedersen", "blake2s"] -categories = ["cryptography"] -include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] -license = "MIT/Apache-2.0" -edition = "2018" - -################################# Dependencies ################################ - -[dependencies] -algebra-core = { git = "https://github.com/scipr-lab/zexe", default-features = false } -bench-utils = { git = "https://github.com/scipr-lab/zexe" } - -blake2 = { version = "0.8", default-features = false } -digest = "0.8" - -ff-fft = { git = "https://github.com/scipr-lab/zexe", default-features = false } -gm17 = { git = "https://github.com/scipr-lab/zexe", optional = true, default-features = false } -groth16 = { git = "https://github.com/scipr-lab/zexe", optional = true, default-features = false } - -r1cs-core = { git = "https://github.com/scipr-lab/zexe", optional = true, default-features = false } -r1cs-std = { path = "../r1cs-std", optional = true, default-features = false } - -rand = { version = "0.7", default-features = false } -rayon = { version = "1.0", optional = true } -derivative = { version = "2.0", features = ["use_core"] } -tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } - -[features] -default = ["std", "r1cs"] -r1cs = ["r1cs-core", "r1cs-std"] -std = [ "algebra-core/std", "r1cs-core/std", "r1cs-std/std"] -parallel = ["std", "rayon", "gm17/parallel", "groth16/parallel", "ff-fft/parallel"] - -[dev-dependencies] -algebra = { git = "https://github.com/scipr-lab/zexe", default-features = false, features = [ "ed_on_bls12_381", "bls12_377", "mnt4_298", "mnt6_298" ] } -r1cs-std = { path = "../r1cs-std", default-features = false, features = [ "ed_on_bls12_381", "bls12_377", "mnt4_298", "mnt6_298" ] } -rand_xorshift = { version = "0.2" } diff --git a/crypto-primitives/LICENSE-APACHE b/crypto-primitives/LICENSE-APACHE deleted file mode 120000 index 965b606..0000000 --- a/crypto-primitives/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE \ No newline at end of file diff --git a/crypto-primitives/LICENSE-MIT b/crypto-primitives/LICENSE-MIT deleted file mode 120000 index 76219eb..0000000 --- a/crypto-primitives/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT \ No newline at end of file diff --git a/crypto-primitives/src/commitment/blake2s/constraints.rs b/crypto-primitives/src/commitment/blake2s/constraints.rs deleted file mode 100644 index 5ab3725..0000000 --- a/crypto-primitives/src/commitment/blake2s/constraints.rs +++ /dev/null @@ -1,133 +0,0 @@ -use r1cs_core::{Namespace, SynthesisError}; - -use crate::{ - commitment::blake2s, - commitment::CommitmentGadget, - prf::blake2s::constraints::{evaluate_blake2s, OutputVar}, - Vec, -}; -use algebra_core::{Field, PrimeField}; -use r1cs_std::prelude::*; - -use core::borrow::Borrow; - -#[derive(Clone)] -pub struct ParametersVar; - -#[derive(Clone)] -pub struct RandomnessVar(pub Vec>); - -pub struct CommGadget; - -impl CommitmentGadget for CommGadget { - type OutputVar = OutputVar; - type ParametersVar = ParametersVar; - type RandomnessVar = RandomnessVar; - - #[tracing::instrument(target = "r1cs", skip(input, r))] - fn commit( - _: &Self::ParametersVar, - input: &[UInt8], - r: &Self::RandomnessVar, - ) -> Result { - let mut input_bits = Vec::with_capacity(512); - for byte in input.iter().chain(r.0.iter()) { - input_bits.extend_from_slice(&byte.to_bits_le()?); - } - let mut result = Vec::new(); - for int in evaluate_blake2s(&input_bits)?.into_iter() { - let chunk = int.to_bytes()?; - result.extend_from_slice(&chunk); - } - Ok(OutputVar(result)) - } -} - -impl AllocVar<(), ConstraintF> for ParametersVar { - #[tracing::instrument(target = "r1cs", skip(_cs, _f))] - fn new_variable>( - _cs: impl Into>, - _f: impl FnOnce() -> Result, - _mode: AllocationMode, - ) -> Result { - Ok(ParametersVar) - } -} - -impl AllocVar<[u8; 32], ConstraintF> for RandomnessVar { - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let bytes = f().map(|b| *b.borrow()).unwrap_or([0u8; 32]); - match mode { - AllocationMode::Constant => Ok(Self(UInt8::constant_vec(&bytes))), - AllocationMode::Input => UInt8::new_input_vec(cs, &bytes).map(Self), - AllocationMode::Witness => UInt8::new_witness_vec(cs, &bytes).map(Self), - } - } -} - -#[cfg(test)] -mod test { - use crate::{ - commitment::blake2s::{ - constraints::{CommGadget, RandomnessVar}, - Commitment, - }, - commitment::{CommitmentGadget, CommitmentScheme}, - }; - use algebra::{ed_on_bls12_381::Fq as Fr, test_rng}; - use r1cs_core::ConstraintSystem; - use r1cs_std::prelude::*; - use rand::Rng; - - #[test] - fn commitment_gadget_test() { - let cs = ConstraintSystem::::new_ref(); - - let input = [1u8; 32]; - - let rng = &mut test_rng(); - - type TestCOMM = Commitment; - type TestCOMMGadget = CommGadget; - - let mut randomness = [0u8; 32]; - rng.fill(&mut randomness); - - let parameters = (); - let primitive_result = Commitment::commit(¶meters, &input, &randomness).unwrap(); - - let mut input_var = vec![]; - for byte in &input { - input_var.push(UInt8::new_witness(cs.clone(), || Ok(*byte)).unwrap()); - } - - let mut randomness_var = vec![]; - for r_byte in randomness.iter() { - randomness_var.push(UInt8::new_witness(cs.clone(), || Ok(r_byte)).unwrap()); - } - let randomness_var = RandomnessVar(randomness_var); - - let parameters_var = - >::ParametersVar::new_witness( - r1cs_core::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = >::commit( - ¶meters_var, - &input_var, - &randomness_var, - ) - .unwrap(); - - for i in 0..32 { - assert_eq!(primitive_result[i], result_var.0[i].value().unwrap()); - } - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/crypto-primitives/src/commitment/blake2s/mod.rs b/crypto-primitives/src/commitment/blake2s/mod.rs deleted file mode 100644 index 06b5b3c..0000000 --- a/crypto-primitives/src/commitment/blake2s/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -use super::CommitmentScheme; -use crate::Error; -use blake2::Blake2s as b2s; -use digest::Digest; -use rand::Rng; - -pub struct Commitment; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -impl CommitmentScheme for Commitment { - type Parameters = (); - type Randomness = [u8; 32]; - type Output = [u8; 32]; - - fn setup(_: &mut R) -> Result { - Ok(()) - } - - fn commit( - _: &Self::Parameters, - input: &[u8], - r: &Self::Randomness, - ) -> Result { - let mut h = b2s::new(); - h.input(input); - h.input(r.as_ref()); - let mut result = [0u8; 32]; - result.copy_from_slice(&h.result()); - Ok(result) - } -} diff --git a/crypto-primitives/src/commitment/constraints.rs b/crypto-primitives/src/commitment/constraints.rs deleted file mode 100644 index 981f9f9..0000000 --- a/crypto-primitives/src/commitment/constraints.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::commitment::CommitmentScheme; -use algebra_core::Field; -use core::fmt::Debug; -use r1cs_core::SynthesisError; -use r1cs_std::prelude::*; - -pub trait CommitmentGadget { - type OutputVar: EqGadget - + ToBytesGadget - + AllocVar - + R1CSVar - + Clone - + Sized - + Debug; - type ParametersVar: AllocVar + Clone; - type RandomnessVar: AllocVar + Clone; - - fn commit( - parameters: &Self::ParametersVar, - input: &[UInt8], - r: &Self::RandomnessVar, - ) -> Result; -} diff --git a/crypto-primitives/src/commitment/injective_map/constraints.rs b/crypto-primitives/src/commitment/injective_map/constraints.rs deleted file mode 100644 index 9961b68..0000000 --- a/crypto-primitives/src/commitment/injective_map/constraints.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::commitment::{ - injective_map::{InjectiveMap, PedersenCommCompressor}, - pedersen::{ - constraints::{CommGadget, ParametersVar, RandomnessVar}, - Window, - }, -}; - -pub use crate::crh::injective_map::constraints::InjectiveMapGadget; -use algebra_core::{Field, PrimeField, ProjectiveCurve}; -use r1cs_core::SynthesisError; -use r1cs_std::{ - groups::{CurveVar, GroupOpsBounds}, - uint8::UInt8, -}; - -use core::marker::PhantomData; - -type ConstraintF = <::BaseField as Field>::BasePrimeField; - -pub struct CommitmentCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - W: Window, - GG: CurveVar>, - IG: InjectiveMapGadget, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - _compressor: PhantomData, - _compressor_gadget: PhantomData, - _comm: PhantomData>, -} - -impl - crate::commitment::CommitmentGadget, ConstraintF> - for CommitmentCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, - ConstraintF: PrimeField, - IG: InjectiveMapGadget, - W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - type OutputVar = IG::OutputVar; - type ParametersVar = ParametersVar; - type RandomnessVar = RandomnessVar>; - - fn commit( - parameters: &Self::ParametersVar, - input: &[UInt8>], - r: &Self::RandomnessVar, - ) -> Result { - let result = CommGadget::::commit(parameters, input, r)?; - IG::evaluate(&result) - } -} diff --git a/crypto-primitives/src/commitment/injective_map/mod.rs b/crypto-primitives/src/commitment/injective_map/mod.rs deleted file mode 100644 index 8a69b43..0000000 --- a/crypto-primitives/src/commitment/injective_map/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::Error; -use core::marker::PhantomData; -use rand::Rng; - -use super::{pedersen, CommitmentScheme}; -pub use crate::crh::injective_map::InjectiveMap; -use algebra_core::ProjectiveCurve; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub struct PedersenCommCompressor, W: pedersen::Window> { - _group: PhantomData, - _compressor: PhantomData, - _comm: pedersen::Commitment, -} - -impl, W: pedersen::Window> CommitmentScheme - for PedersenCommCompressor -{ - type Output = I::Output; - type Parameters = pedersen::Parameters; - type Randomness = pedersen::Randomness; - - fn setup(rng: &mut R) -> Result { - let time = start_timer!(|| format!("PedersenCompressor::Setup")); - let params = pedersen::Commitment::::setup(rng); - end_timer!(time); - params - } - - fn commit( - parameters: &Self::Parameters, - input: &[u8], - randomness: &Self::Randomness, - ) -> Result { - let eval_time = start_timer!(|| "PedersenCompressor::Eval"); - let result = I::injective_map(&pedersen::Commitment::::commit( - parameters, input, randomness, - )?)?; - end_timer!(eval_time); - Ok(result) - } -} diff --git a/crypto-primitives/src/commitment/mod.rs b/crypto-primitives/src/commitment/mod.rs deleted file mode 100644 index 74af73b..0000000 --- a/crypto-primitives/src/commitment/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -use algebra_core::UniformRand; -use core::{fmt::Debug, hash::Hash}; -use rand::Rng; - -use algebra_core::bytes::ToBytes; - -pub mod blake2s; -pub mod injective_map; -pub mod pedersen; - -#[cfg(feature = "r1cs")] -pub mod constraints; -#[cfg(feature = "r1cs")] -pub use constraints::*; - -use crate::Error; - -pub trait CommitmentScheme { - type Output: ToBytes + Clone + Default + Eq + Hash + Debug; - type Parameters: Clone; - type Randomness: Clone + ToBytes + Default + Eq + UniformRand + Debug; - - fn setup(r: &mut R) -> Result; - - fn commit( - parameters: &Self::Parameters, - input: &[u8], - r: &Self::Randomness, - ) -> Result; -} diff --git a/crypto-primitives/src/commitment/pedersen/constraints.rs b/crypto-primitives/src/commitment/pedersen/constraints.rs deleted file mode 100644 index 874dfbe..0000000 --- a/crypto-primitives/src/commitment/pedersen/constraints.rs +++ /dev/null @@ -1,204 +0,0 @@ -use crate::{ - commitment::pedersen::{Commitment, Parameters, Randomness}, - crh::pedersen::Window, - Vec, -}; -use algebra_core::{ - fields::{Field, PrimeField}, - to_bytes, ProjectiveCurve, Zero, -}; -use r1cs_core::{Namespace, SynthesisError}; - -use core::{borrow::Borrow, marker::PhantomData}; -use r1cs_std::prelude::*; - -type ConstraintF = <::BaseField as Field>::BasePrimeField; - -#[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct ParametersVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - params: Parameters, - #[doc(hidden)] - _group_var: PhantomData, -} - -#[derive(Clone, Debug)] -pub struct RandomnessVar(Vec>); - -pub struct CommGadget>, W: Window> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _curve: PhantomData<*const C>, - #[doc(hidden)] - _group_var: PhantomData<*const GG>, - #[doc(hidden)] - _window: PhantomData<*const W>, -} - -impl crate::commitment::CommitmentGadget, ConstraintF> - for CommGadget -where - C: ProjectiveCurve, - GG: CurveVar>, - W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - ConstraintF: PrimeField, -{ - type OutputVar = GG; - type ParametersVar = ParametersVar; - type RandomnessVar = RandomnessVar>; - - #[tracing::instrument(target = "r1cs", skip(parameters, r))] - fn commit( - parameters: &Self::ParametersVar, - input: &[UInt8>], - r: &Self::RandomnessVar, - ) -> Result { - assert!((input.len() * 8) <= (W::WINDOW_SIZE * W::NUM_WINDOWS)); - - let mut padded_input = input.to_vec(); - // Pad if input length is less than `W::WINDOW_SIZE * W::NUM_WINDOWS`. - if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS { - let current_length = input.len(); - for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) { - padded_input.push(UInt8::constant(0u8)); - } - } - - assert_eq!(padded_input.len() * 8, W::WINDOW_SIZE * W::NUM_WINDOWS); - assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS); - - // Allocate new variable for commitment output. - let input_in_bits: Vec> = padded_input - .iter() - .flat_map(|byte| byte.to_bits_le().unwrap()) - .collect(); - let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE); - let mut result = - GG::precomputed_base_multiscalar_mul_le(¶meters.params.generators, input_in_bits)?; - - // Compute h^r - let rand_bits: Vec<_> = - r.0.iter() - .flat_map(|byte| byte.to_bits_le().unwrap()) - .collect(); - result.precomputed_base_scalar_mul_le( - rand_bits - .iter() - .zip(¶meters.params.randomness_generator), - )?; - - Ok(result) - } -} - -impl AllocVar, ConstraintF> for ParametersVar -where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - fn new_variable>>( - _cs: impl Into>>, - f: impl FnOnce() -> Result, - _mode: AllocationMode, - ) -> Result { - let params = f()?.borrow().clone(); - Ok(ParametersVar { - params, - _group_var: PhantomData, - }) - } -} - -impl AllocVar, F> for RandomnessVar -where - C: ProjectiveCurve, - F: PrimeField, -{ - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let r = to_bytes![&f().map(|b| b.borrow().0).unwrap_or(C::ScalarField::zero())].unwrap(); - match mode { - AllocationMode::Constant => Ok(Self(UInt8::constant_vec(&r))), - AllocationMode::Input => UInt8::new_input_vec(cs, &r).map(Self), - AllocationMode::Witness => UInt8::new_witness_vec(cs, &r).map(Self), - } - } -} - -#[cfg(test)] -mod test { - use algebra::{ - ed_on_bls12_381::{EdwardsProjective as JubJub, Fq, Fr}, - test_rng, UniformRand, - }; - - use crate::{ - commitment::{ - pedersen::{constraints::CommGadget, Commitment, Randomness}, - CommitmentGadget, CommitmentScheme, - }, - crh::pedersen, - }; - use r1cs_core::ConstraintSystem; - use r1cs_std::{ed_on_bls12_381::EdwardsVar, prelude::*}; - - #[test] - fn commitment_gadget_test() { - let cs = ConstraintSystem::::new_ref(); - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl pedersen::Window for Window { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 8; - } - - let input = [1u8; 4]; - - let rng = &mut test_rng(); - - type TestCOMM = Commitment; - type TestCOMMGadget = CommGadget; - - let randomness = Randomness(Fr::rand(rng)); - - let parameters = Commitment::::setup(rng).unwrap(); - let primitive_result = - Commitment::::commit(¶meters, &input, &randomness).unwrap(); - - let mut input_var = vec![]; - for input_byte in input.iter() { - input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); - } - - let randomness_var = - >::RandomnessVar::new_witness( - r1cs_core::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = - >::ParametersVar::new_witness( - r1cs_core::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = - TestCOMMGadget::commit(¶meters_var, &input_var, &randomness_var).unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/crypto-primitives/src/commitment/pedersen/mod.rs b/crypto-primitives/src/commitment/pedersen/mod.rs deleted file mode 100644 index c12d7fc..0000000 --- a/crypto-primitives/src/commitment/pedersen/mod.rs +++ /dev/null @@ -1,125 +0,0 @@ -use crate::{Error, Vec}; -use algebra_core::{ - bytes::ToBytes, - io::{Result as IoResult, Write}, - BitIteratorLE, Field, FpParameters, PrimeField, ProjectiveCurve, ToConstraintField, - UniformRand, -}; - -use core::marker::PhantomData; -use rand::Rng; - -use super::CommitmentScheme; - -pub use crate::crh::pedersen::Window; -use crate::crh::{pedersen, FixedLengthCRH}; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -#[derive(Clone)] -pub struct Parameters { - pub randomness_generator: Vec, - pub generators: Vec>, -} - -pub struct Commitment { - group: PhantomData, - window: PhantomData, -} - -#[derive(Derivative)] -#[derivative(Clone, PartialEq, Debug, Eq, Default)] -pub struct Randomness(pub C::ScalarField); - -impl UniformRand for Randomness { - #[inline] - fn rand(rng: &mut R) -> Self { - Randomness(UniformRand::rand(rng)) - } -} - -impl ToBytes for Randomness { - fn write(&self, writer: W) -> IoResult<()> { - self.0.write(writer) - } -} - -impl CommitmentScheme for Commitment { - type Parameters = Parameters; - type Randomness = Randomness; - type Output = C::Affine; - - fn setup(rng: &mut R) -> Result { - let time = start_timer!(|| format!( - "PedersenCOMM::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> C", - W::NUM_WINDOWS, - W::WINDOW_SIZE, - W::NUM_WINDOWS * W::WINDOW_SIZE - )); - let num_powers = ::Params::MODULUS_BITS as usize; - let randomness_generator = pedersen::CRH::::generator_powers(num_powers, rng); - let generators = pedersen::CRH::::create_generators(rng); - end_timer!(time); - - Ok(Self::Parameters { - randomness_generator, - generators, - }) - } - - fn commit( - parameters: &Self::Parameters, - input: &[u8], - randomness: &Self::Randomness, - ) -> Result { - let commit_time = start_timer!(|| "PedersenCOMM::Commit"); - // If the input is too long, return an error. - if input.len() > W::WINDOW_SIZE * W::NUM_WINDOWS { - panic!("incorrect input length: {:?}", input.len()); - } - // Pad the input to the necessary length. - let mut padded_input = Vec::with_capacity(input.len()); - let mut input = input; - if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS { - let current_length = input.len(); - padded_input.extend_from_slice(input); - for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) { - padded_input.push(0u8); - } - input = padded_input.as_slice(); - } - assert_eq!(parameters.generators.len(), W::NUM_WINDOWS); - - // Invoke Pedersen CRH here, to prevent code duplication. - - let crh_parameters = pedersen::Parameters { - generators: parameters.generators.clone(), - }; - let mut result: C = pedersen::CRH::::evaluate(&crh_parameters, &input)?.into(); - let randomize_time = start_timer!(|| "Randomize"); - - // Compute h^r. - for (bit, power) in BitIteratorLE::new(randomness.0.into_repr()) - .into_iter() - .zip(¶meters.randomness_generator) - { - if bit { - result += power - } - } - end_timer!(randomize_time); - end_timer!(commit_time); - - Ok(result.into()) - } -} - -impl> - ToConstraintField for Parameters -{ - #[inline] - fn to_field_elements(&self) -> Result, Error> { - Ok(Vec::new()) - } -} diff --git a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs deleted file mode 100644 index 7516cd2..0000000 --- a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs +++ /dev/null @@ -1,180 +0,0 @@ -use core::{borrow::Borrow, marker::PhantomData}; - -use crate::{ - crh::{ - bowe_hopwood::{Parameters, CHUNK_SIZE, CRH}, - pedersen::Window, - FixedLengthCRHGadget, - }, - Vec, -}; -use algebra_core::{ - curves::{ModelParameters, TEModelParameters}, - Field, -}; -use r1cs_core::{Namespace, SynthesisError}; -use r1cs_std::{ - alloc::AllocVar, groups::curves::twisted_edwards::AffineVar, prelude::*, uint8::UInt8, -}; - -use r1cs_std::bits::boolean::Boolean; - -type ConstraintF

= <

::BaseField as Field>::BasePrimeField; - -#[derive(Derivative)] -#[derivative(Clone(bound = "P: TEModelParameters, W: Window"))] -pub struct ParametersVar { - params: Parameters

, - #[doc(hidden)] - _window: PhantomData, -} - -pub struct CRHGadget>> -where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, -{ - #[doc(hidden)] - _params: PhantomData

, - #[doc(hidden)] - _base_field: PhantomData, -} - -impl FixedLengthCRHGadget, ConstraintF

> for CRHGadget -where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: FieldVar>, - F: TwoBitLookupGadget, TableConstant = P::BaseField> - + ThreeBitCondNegLookupGadget, TableConstant = P::BaseField>, - P: TEModelParameters, - W: Window, -{ - type OutputVar = AffineVar; - type ParametersVar = ParametersVar; - - #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( - parameters: &Self::ParametersVar, - input: &[UInt8>], - ) -> Result { - // Pad the input if it is not the current length. - let mut input_in_bits: Vec> = input - .iter() - .flat_map(|byte| byte.to_bits_le().unwrap()) - .collect(); - if (input_in_bits.len()) % CHUNK_SIZE != 0 { - let current_length = input_in_bits.len(); - for _ in 0..(CHUNK_SIZE - current_length % CHUNK_SIZE) { - input_in_bits.push(Boolean::constant(false)); - } - } - assert!(input_in_bits.len() % CHUNK_SIZE == 0); - assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS); - for generators in parameters.params.generators.iter() { - assert_eq!(generators.len(), W::WINDOW_SIZE); - } - - // Allocate new variable for the result. - let input_in_bits = input_in_bits - .chunks(W::WINDOW_SIZE * CHUNK_SIZE) - .map(|x| x.chunks(CHUNK_SIZE).collect::>()) - .collect::>(); - let result = AffineVar::precomputed_base_3_bit_signed_digit_scalar_mul( - ¶meters.params.generators, - &input_in_bits, - )?; - - Ok(result) - } -} - -impl AllocVar, ConstraintF

> for ParametersVar -where - P: TEModelParameters, - W: Window, -{ - #[tracing::instrument(target = "r1cs", skip(_cs, f))] - fn new_variable>>( - _cs: impl Into>>, - f: impl FnOnce() -> Result, - _mode: AllocationMode, - ) -> Result { - let params = f()?.borrow().clone(); - Ok(ParametersVar { - params, - _window: PhantomData, - }) - } -} - -#[cfg(test)] -mod test { - use rand::Rng; - - use crate::crh::{ - bowe_hopwood::{constraints::CRHGadget, CRH}, - pedersen::Window as PedersenWindow, - FixedLengthCRH, FixedLengthCRHGadget, - }; - use algebra::{ - ed_on_bls12_381::{EdwardsParameters, Fq as Fr}, - test_rng, ProjectiveCurve, - }; - use r1cs_core::{ConstraintSystem, ConstraintSystemRef}; - use r1cs_std::{alloc::AllocVar, ed_on_bls12_381::FqVar, uint8::UInt8, R1CSVar}; - - type TestCRH = CRH; - type TestCRHGadget = CRHGadget; - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl PedersenWindow for Window { - const WINDOW_SIZE: usize = 63; - const NUM_WINDOWS: usize = 8; - } - - fn generate_input( - cs: ConstraintSystemRef, - rng: &mut R, - ) -> ([u8; 189], Vec>) { - let mut input = [1u8; 189]; - rng.fill_bytes(&mut input); - - let mut input_bytes = vec![]; - for byte in input.iter() { - input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); - } - (input, input_bytes) - } - - #[test] - fn test_native_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (input, input_var) = generate_input(cs.clone(), rng); - println!("number of constraints for input: {}", cs.num_constraints()); - - let parameters = TestCRH::setup(rng).unwrap(); - let primitive_result = TestCRH::evaluate(¶meters, &input).unwrap(); - - let parameters_var = - >::ParametersVar::new_witness( - r1cs_core::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); - println!( - "number of constraints for input + params: {}", - cs.num_constraints() - ); - - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); - - println!("number of constraints total: {}", cs.num_constraints()); - - let primitive_result = primitive_result.into_affine(); - assert_eq!(primitive_result, result_var.value().unwrap().into_affine()); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/crypto-primitives/src/crh/bowe_hopwood/mod.rs b/crypto-primitives/src/crh/bowe_hopwood/mod.rs deleted file mode 100644 index 3d5f5d2..0000000 --- a/crypto-primitives/src/crh/bowe_hopwood/mod.rs +++ /dev/null @@ -1,197 +0,0 @@ -use crate::{Error, Vec}; -use core::{ - fmt::{Debug, Formatter, Result as FmtResult}, - marker::PhantomData, -}; -use rand::Rng; -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -use super::pedersen; -use crate::crh::FixedLengthCRH; -use algebra_core::{ - biginteger::BigInteger, curves::twisted_edwards_extended::GroupProjective as TEProjective, - fields::PrimeField, ProjectiveCurve, TEModelParameters, UniformRand, -}; -use ff_fft::cfg_chunks; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub const CHUNK_SIZE: usize = 3; - -#[derive(Derivative)] -#[derivative(Clone(bound = ""), Default(bound = ""))] -pub struct Parameters { - pub generators: Vec>>, -} - -pub struct CRH { - group: PhantomData

, - window: PhantomData, -} - -impl CRH { - pub fn create_generators(rng: &mut R) -> Vec>> { - let mut generators = Vec::new(); - for _ in 0..W::NUM_WINDOWS { - let mut generators_for_segment = Vec::new(); - let mut base = TEProjective::rand(rng); - for _ in 0..W::WINDOW_SIZE { - generators_for_segment.push(base); - for _ in 0..4 { - base.double_in_place(); - } - } - generators.push(generators_for_segment); - } - generators - } -} - -impl FixedLengthCRH for CRH { - const INPUT_SIZE_BITS: usize = pedersen::CRH::, W>::INPUT_SIZE_BITS; - type Output = TEProjective

; - type Parameters = Parameters

; - - fn setup(rng: &mut R) -> Result { - fn calculate_num_chunks_in_segment() -> usize { - let upper_limit = F::modulus_minus_one_div_two(); - let mut c = 0; - let mut range = F::BigInt::from(2_u64); - while range < upper_limit { - range.muln(4); - c += 1; - } - - c - } - - let maximum_num_chunks_in_segment = calculate_num_chunks_in_segment::(); - if W::WINDOW_SIZE > maximum_num_chunks_in_segment { - return Err(format!( - "Bowe-Hopwood-PedersenCRH hash must have a window size resulting in scalars < (p-1)/2, \ - maximum segment size is {}", - maximum_num_chunks_in_segment - ) - .into()); - } - - let time = start_timer!(|| format!( - "Bowe-Hopwood-PedersenCRH::Setup: {} segments of {} 3-bit chunks; {{0,1}}^{{{}}} -> P", - W::NUM_WINDOWS, - W::WINDOW_SIZE, - W::WINDOW_SIZE * W::NUM_WINDOWS * CHUNK_SIZE - )); - let generators = Self::create_generators(rng); - end_timer!(time); - Ok(Self::Parameters { generators }) - } - - fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result { - let eval_time = start_timer!(|| "BoweHopwoodPedersenCRH::Eval"); - - if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS * CHUNK_SIZE { - panic!( - "incorrect input length {:?} for window params {:?}x{:?}x{}", - input.len(), - W::WINDOW_SIZE, - W::NUM_WINDOWS, - CHUNK_SIZE, - ); - } - - let mut padded_input = Vec::with_capacity(input.len()); - let input = pedersen::bytes_to_bits(input); - // Pad the input if it is not the current length. - padded_input.extend_from_slice(&input); - if input.len() % CHUNK_SIZE != 0 { - let current_length = input.len(); - for _ in 0..(CHUNK_SIZE - current_length % CHUNK_SIZE) { - padded_input.push(false); - } - } - - assert_eq!(padded_input.len() % CHUNK_SIZE, 0); - - assert_eq!( - parameters.generators.len(), - W::NUM_WINDOWS, - "Incorrect pp of size {:?} for window params {:?}x{:?}x{}", - parameters.generators.len(), - W::WINDOW_SIZE, - W::NUM_WINDOWS, - CHUNK_SIZE, - ); - for generators in parameters.generators.iter() { - assert_eq!(generators.len(), W::WINDOW_SIZE); - } - assert_eq!(CHUNK_SIZE, 3); - - // Compute sum of h_i^{sum of - // (1-2*c_{i,j,2})*(1+c_{i,j,0}+2*c_{i,j,1})*2^{4*(j-1)} for all j in segment} - // for all i. Described in section 5.4.1.7 in the Zcash protocol - // specification. - - let result = cfg_chunks!(padded_input, W::WINDOW_SIZE * CHUNK_SIZE) - .zip(¶meters.generators) - .map(|(segment_bits, segment_generators)| { - cfg_chunks!(segment_bits, CHUNK_SIZE) - .zip(segment_generators) - .map(|(chunk_bits, generator)| { - let mut encoded = generator.clone(); - if chunk_bits[0] { - encoded = encoded + generator; - } - if chunk_bits[1] { - encoded += &generator.double(); - } - if chunk_bits[2] { - encoded = -encoded; - } - encoded - }) - .sum::>() - }) - .sum::>(); - - end_timer!(eval_time); - - Ok(result) - } -} - -impl Debug for Parameters

{ - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "Bowe-Hopwood-Pedersen Hash Parameters {{\n")?; - for (i, g) in self.generators.iter().enumerate() { - write!(f, "\t Generator {}: {:?}\n", i, g)?; - } - write!(f, "}}\n") - } -} - -#[cfg(test)] -mod test { - use crate::{ - crh::{bowe_hopwood::CRH, pedersen::Window}, - FixedLengthCRH, - }; - use algebra::{ed_on_bls12_381::EdwardsParameters, test_rng}; - - #[test] - fn test_simple_bh() { - #[derive(Clone)] - struct TestWindow {} - impl Window for TestWindow { - const WINDOW_SIZE: usize = 63; - const NUM_WINDOWS: usize = 8; - } - - let rng = &mut test_rng(); - let params = as FixedLengthCRH>::setup(rng).unwrap(); - let _ = - as FixedLengthCRH>::evaluate(¶ms, &[1, 2, 3]) - .unwrap(); - } -} diff --git a/crypto-primitives/src/crh/constraints.rs b/crypto-primitives/src/crh/constraints.rs deleted file mode 100644 index 16eeba6..0000000 --- a/crypto-primitives/src/crh/constraints.rs +++ /dev/null @@ -1,25 +0,0 @@ -use algebra_core::Field; -use core::fmt::Debug; - -use crate::crh::FixedLengthCRH; -use r1cs_core::SynthesisError; - -use r1cs_std::prelude::*; - -pub trait FixedLengthCRHGadget: Sized { - type OutputVar: EqGadget - + ToBytesGadget - + CondSelectGadget - + AllocVar - + R1CSVar - + Debug - + Clone - + Sized; - - type ParametersVar: AllocVar + Clone; - - fn evaluate( - parameters: &Self::ParametersVar, - input: &[UInt8], - ) -> Result; -} diff --git a/crypto-primitives/src/crh/injective_map/constraints.rs b/crypto-primitives/src/crh/injective_map/constraints.rs deleted file mode 100644 index 88116b0..0000000 --- a/crypto-primitives/src/crh/injective_map/constraints.rs +++ /dev/null @@ -1,98 +0,0 @@ -use core::{fmt::Debug, marker::PhantomData}; - -use crate::crh::{ - injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor}, - pedersen::{constraints as ped_constraints, Window}, - FixedLengthCRHGadget, -}; - -use algebra_core::{ - curves::{ - models::{ModelParameters, TEModelParameters}, - twisted_edwards_extended::GroupProjective as TEProjective, - }, - fields::{Field, PrimeField, SquareRootField}, - ProjectiveCurve, -}; -use r1cs_core::SynthesisError; -use r1cs_std::{ - fields::fp::FpVar, - groups::{curves::twisted_edwards::AffineVar as TEVar, CurveVar}, - prelude::*, -}; - -type ConstraintF = <::BaseField as Field>::BasePrimeField; - -pub trait InjectiveMapGadget< - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, -> where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - type OutputVar: EqGadget> - + ToBytesGadget> - + CondSelectGadget> - + AllocVar> - + R1CSVar, Value = I::Output> - + Debug - + Clone - + Sized; - - fn evaluate(ge: &GG) -> Result; -} - -pub struct TECompressorGadget; - -impl InjectiveMapGadget, TECompressor, TEVar>> - for TECompressorGadget -where - F: PrimeField + SquareRootField, - P: TEModelParameters + ModelParameters, -{ - type OutputVar = FpVar; - - fn evaluate(ge: &TEVar>) -> Result { - Ok(ge.x.clone()) - } -} - -pub struct PedersenCRHCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - W: Window, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, -{ - #[doc(hidden)] - _compressor: PhantomData, - #[doc(hidden)] - _compressor_gadget: PhantomData, - #[doc(hidden)] - _crh: ped_constraints::CRHGadget, -} - -impl FixedLengthCRHGadget, ConstraintF> - for PedersenCRHCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, - W: Window, -{ - type OutputVar = IG::OutputVar; - type ParametersVar = ped_constraints::CRHParametersVar; - - #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( - parameters: &Self::ParametersVar, - input: &[UInt8>], - ) -> Result { - let result = ped_constraints::CRHGadget::::evaluate(parameters, input)?; - IG::evaluate(&result) - } -} diff --git a/crypto-primitives/src/crh/injective_map/mod.rs b/crypto-primitives/src/crh/injective_map/mod.rs deleted file mode 100644 index 51dde7f..0000000 --- a/crypto-primitives/src/crh/injective_map/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::{CryptoError, Error}; -use algebra_core::bytes::ToBytes; -use core::{fmt::Debug, hash::Hash, marker::PhantomData}; -use rand::Rng; - -use super::{pedersen, FixedLengthCRH}; -use algebra_core::curves::{ - models::{ModelParameters, TEModelParameters}, - twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective}, - ProjectiveCurve, -}; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub trait InjectiveMap { - type Output: ToBytes + Clone + Eq + Hash + Default + Debug; - - fn injective_map(ge: &C::Affine) -> Result; -} - -pub struct TECompressor; - -impl InjectiveMap> for TECompressor { - type Output =

::BaseField; - - fn injective_map(ge: &TEAffine

) -> Result { - debug_assert!(ge.is_in_correct_subgroup_assuming_on_curve()); - Ok(ge.x) - } -} - -pub struct PedersenCRHCompressor, W: pedersen::Window> { - _group: PhantomData, - _compressor: PhantomData, - _crh: pedersen::CRH, -} - -impl, W: pedersen::Window> FixedLengthCRH - for PedersenCRHCompressor -{ - const INPUT_SIZE_BITS: usize = pedersen::CRH::::INPUT_SIZE_BITS; - type Output = I::Output; - type Parameters = pedersen::Parameters; - - fn setup(rng: &mut R) -> Result { - let time = start_timer!(|| format!("PedersenCRHCompressor::Setup")); - let params = pedersen::CRH::::setup(rng); - end_timer!(time); - params - } - - fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result { - let eval_time = start_timer!(|| "PedersenCRHCompressor::Eval"); - let result = I::injective_map(&pedersen::CRH::::evaluate(parameters, input)?)?; - end_timer!(eval_time); - Ok(result) - } -} diff --git a/crypto-primitives/src/crh/mod.rs b/crypto-primitives/src/crh/mod.rs deleted file mode 100644 index a560a32..0000000 --- a/crypto-primitives/src/crh/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -use algebra_core::bytes::ToBytes; -use core::hash::Hash; -use rand::Rng; - -pub mod bowe_hopwood; -pub mod injective_map; -pub mod pedersen; - -use crate::Error; - -#[cfg(feature = "r1cs")] -pub mod constraints; -#[cfg(feature = "r1cs")] -pub use constraints::*; - -pub trait FixedLengthCRH { - const INPUT_SIZE_BITS: usize; - - type Output: ToBytes + Clone + Eq + core::fmt::Debug + Hash + Default; - type Parameters: Clone + Default; - - fn setup(r: &mut R) -> Result; - fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result; -} diff --git a/crypto-primitives/src/crh/pedersen/constraints.rs b/crypto-primitives/src/crh/pedersen/constraints.rs deleted file mode 100644 index a76dcde..0000000 --- a/crypto-primitives/src/crh/pedersen/constraints.rs +++ /dev/null @@ -1,152 +0,0 @@ -use crate::{ - crh::{ - pedersen::{Parameters, Window, CRH}, - FixedLengthCRHGadget, - }, - Vec, -}; -use algebra_core::{Field, ProjectiveCurve}; -use r1cs_core::{Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use core::{borrow::Borrow, marker::PhantomData}; - -#[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct CRHParametersVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - params: Parameters, - #[doc(hidden)] - _group_g: PhantomData, -} - -type ConstraintF = <::BaseField as Field>::BasePrimeField; -pub struct CRHGadget>, W: Window> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _group: PhantomData<*const C>, - #[doc(hidden)] - _group_var: PhantomData<*const GG>, - #[doc(hidden)] - _window: PhantomData<*const W>, -} - -impl FixedLengthCRHGadget, ConstraintF> for CRHGadget -where - C: ProjectiveCurve, - GG: CurveVar>, - W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - type OutputVar = GG; - type ParametersVar = CRHParametersVar; - - #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( - parameters: &Self::ParametersVar, - input: &[UInt8>], - ) -> Result { - let mut padded_input = input.to_vec(); - // Pad the input if it is not the current length. - if input.len() * 8 < W::WINDOW_SIZE * W::NUM_WINDOWS { - let current_length = input.len(); - for _ in current_length..(W::WINDOW_SIZE * W::NUM_WINDOWS / 8) { - padded_input.push(UInt8::constant(0u8)); - } - } - assert_eq!(padded_input.len() * 8, W::WINDOW_SIZE * W::NUM_WINDOWS); - assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS); - - // Allocate new variable for the result. - let input_in_bits: Vec> = padded_input - .iter() - .flat_map(|b| b.to_bits_le().unwrap()) - .collect(); - let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE); - let result = - GG::precomputed_base_multiscalar_mul_le(¶meters.params.generators, input_in_bits)?; - Ok(result) - } -} - -impl AllocVar, ConstraintF> for CRHParametersVar -where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[tracing::instrument(target = "r1cs", skip(_cs, f))] - fn new_variable>>( - _cs: impl Into>>, - f: impl FnOnce() -> Result, - _mode: AllocationMode, - ) -> Result { - let params = f()?.borrow().clone(); - Ok(CRHParametersVar { - params, - _group_g: PhantomData, - }) - } -} - -#[cfg(test)] -mod test { - use crate::crh::{pedersen, pedersen::constraints::*, FixedLengthCRH, FixedLengthCRHGadget}; - use algebra::{ - ed_on_bls12_381::{EdwardsProjective as JubJub, Fq as Fr}, - test_rng, - }; - use r1cs_core::{ConstraintSystem, ConstraintSystemRef}; - use r1cs_std::ed_on_bls12_381::EdwardsVar; - use rand::Rng; - - type TestCRH = pedersen::CRH; - type TestCRHGadget = CRHGadget; - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl pedersen::Window for Window { - const WINDOW_SIZE: usize = 128; - const NUM_WINDOWS: usize = 8; - } - - fn generate_input( - cs: ConstraintSystemRef, - rng: &mut R, - ) -> ([u8; 128], Vec>) { - let mut input = [1u8; 128]; - rng.fill_bytes(&mut input); - - let mut input_bytes = vec![]; - for byte in input.iter() { - input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); - } - (input, input_bytes) - } - - #[test] - fn test_native_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (input, input_var) = generate_input(cs.clone(), rng); - - let parameters = TestCRH::setup(rng).unwrap(); - let primitive_result = TestCRH::evaluate(¶meters, &input).unwrap(); - - let parameters_var = - CRHParametersVar::new_constant(r1cs_core::ns!(cs, "CRH Parameters"), ¶meters) - .unwrap(); - - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/crypto-primitives/src/crh/pedersen/mod.rs b/crypto-primitives/src/crh/pedersen/mod.rs deleted file mode 100644 index 22db5dd..0000000 --- a/crypto-primitives/src/crh/pedersen/mod.rs +++ /dev/null @@ -1,152 +0,0 @@ -use crate::{Error, Vec}; -use core::{ - fmt::{Debug, Formatter, Result as FmtResult}, - marker::PhantomData, -}; -use rand::Rng; -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -use crate::crh::FixedLengthCRH; -use algebra_core::{Field, ProjectiveCurve, ToConstraintField}; -use ff_fft::cfg_chunks; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub trait Window: Clone { - const WINDOW_SIZE: usize; - const NUM_WINDOWS: usize; -} - -#[derive(Clone, Default)] -pub struct Parameters { - pub generators: Vec>, -} - -pub struct CRH { - group: PhantomData, - window: PhantomData, -} - -impl CRH { - pub fn create_generators(rng: &mut R) -> Vec> { - let mut generators_powers = Vec::new(); - for _ in 0..W::NUM_WINDOWS { - generators_powers.push(Self::generator_powers(W::WINDOW_SIZE, rng)); - } - generators_powers - } - - pub fn generator_powers(num_powers: usize, rng: &mut R) -> Vec { - let mut cur_gen_powers = Vec::with_capacity(num_powers); - let mut base = C::rand(rng); - for _ in 0..num_powers { - cur_gen_powers.push(base); - base.double_in_place(); - } - cur_gen_powers - } -} - -impl FixedLengthCRH for CRH { - const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS; - type Output = C::Affine; - type Parameters = Parameters; - - fn setup(rng: &mut R) -> Result { - let time = start_timer!(|| format!( - "PedersenCRH::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> C", - W::NUM_WINDOWS, - W::WINDOW_SIZE, - W::NUM_WINDOWS * W::WINDOW_SIZE - )); - let generators = Self::create_generators(rng); - end_timer!(time); - Ok(Self::Parameters { generators }) - } - - fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result { - let eval_time = start_timer!(|| "PedersenCRH::Eval"); - - if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS { - panic!( - "incorrect input length {:?} for window params {:?}✕{:?}", - input.len(), - W::WINDOW_SIZE, - W::NUM_WINDOWS - ); - } - - let mut padded_input = Vec::with_capacity(input.len()); - let mut input = input; - // Pad the input if it is not the current length. - if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS { - let current_length = input.len(); - padded_input.extend_from_slice(input); - for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) { - padded_input.push(0u8); - } - input = padded_input.as_slice(); - } - - assert_eq!( - parameters.generators.len(), - W::NUM_WINDOWS, - "Incorrect pp of size {:?}✕{:?} for window params {:?}✕{:?}", - parameters.generators[0].len(), - parameters.generators.len(), - W::WINDOW_SIZE, - W::NUM_WINDOWS - ); - - // Compute sum of h_i^{m_i} for all i. - let bits = bytes_to_bits(input); - let result = cfg_chunks!(bits, W::WINDOW_SIZE) - .zip(¶meters.generators) - .map(|(bits, generator_powers)| { - let mut encoded = C::zero(); - for (bit, base) in bits.iter().zip(generator_powers.iter()) { - if *bit { - encoded += base; - } - } - encoded - }) - .sum::(); - - end_timer!(eval_time); - - Ok(result.into()) - } -} - -pub fn bytes_to_bits(bytes: &[u8]) -> Vec { - let mut bits = Vec::with_capacity(bytes.len() * 8); - for byte in bytes { - for i in 0..8 { - let bit = (*byte >> i) & 1; - bits.push(bit == 1) - } - } - bits -} - -impl Debug for Parameters { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "Pedersen Hash Parameters {{\n")?; - for (i, g) in self.generators.iter().enumerate() { - write!(f, "\t Generator {}: {:?}\n", i, g)?; - } - write!(f, "}}\n") - } -} - -impl> - ToConstraintField for Parameters -{ - #[inline] - fn to_field_elements(&self) -> Result, Error> { - Ok(Vec::new()) - } -} diff --git a/crypto-primitives/src/lib.rs b/crypto-primitives/src/lib.rs deleted file mode 100644 index a6cee90..0000000 --- a/crypto-primitives/src/lib.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -#[macro_use] -extern crate bench_utils; - -#[macro_use] -extern crate derivative; - -#[macro_use] -extern crate alloc; - -#[cfg(not(feature = "std"))] -pub(crate) use alloc::{borrow::ToOwned, boxed::Box, vec::Vec}; - -#[cfg(feature = "std")] -pub(crate) use std::{borrow::ToOwned, boxed::Box, vec::Vec}; - -pub mod commitment; -pub mod crh; -pub mod merkle_tree; -pub mod nizk; -pub mod prf; -pub mod signature; - -pub use self::{ - commitment::CommitmentScheme, - crh::FixedLengthCRH, - merkle_tree::{MerkleTree, Path}, - nizk::NIZK, - prf::PRF, - signature::SignatureScheme, -}; - -#[cfg(feature = "r1cs")] -#[cfg(feature = "r1cs")] -pub use self::{ - commitment::CommitmentGadget, crh::FixedLengthCRHGadget, merkle_tree::constraints::PathVar, - nizk::NIZKVerifierGadget, prf::PRFGadget, signature::SigRandomizePkGadget, -}; - -pub type Error = Box; - -#[derive(Debug)] -pub enum CryptoError { - IncorrectInputLength(usize), - NotPrimeOrder, -} - -impl core::fmt::Display for CryptoError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let msg = match self { - CryptoError::IncorrectInputLength(len) => format!("input length is wrong: {}", len), - CryptoError::NotPrimeOrder => "element is not prime order".to_owned(), - }; - write!(f, "{}", msg) - } -} - -impl algebra_core::Error for CryptoError {} diff --git a/crypto-primitives/src/merkle_tree/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs deleted file mode 100644 index 0c5bdd3..0000000 --- a/crypto-primitives/src/merkle_tree/constraints.rs +++ /dev/null @@ -1,258 +0,0 @@ -use algebra_core::Field; -use r1cs_core::{Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use crate::{ - crh::{FixedLengthCRH, FixedLengthCRHGadget}, - merkle_tree::*, -}; - -use core::borrow::Borrow; - -pub struct PathVar -where - P: Config, - HGadget: FixedLengthCRHGadget, - ConstraintF: Field, -{ - path: Vec<(HGadget::OutputVar, HGadget::OutputVar)>, -} - -impl PathVar -where - P: Config, - ConstraintF: Field, - CRHGadget: FixedLengthCRHGadget, - >::Value: PartialEq, -{ - #[tracing::instrument(target = "r1cs", skip(self, parameters, root, leaf))] - pub fn check_membership( - &self, - parameters: &CRHGadget::ParametersVar, - root: &CRHGadget::OutputVar, - leaf: impl ToBytesGadget, - ) -> Result, SynthesisError> { - assert_eq!(self.path.len(), P::HEIGHT - 1); - // Check that the hash of the given leaf matches the leaf hash in the membership - // proof. - let leaf_bits = leaf.to_bytes()?; - let leaf_hash = CRHGadget::evaluate(parameters, &leaf_bits)?; - let cs = leaf_hash.cs().or(root.cs()); - - // Check if leaf is one of the bottom-most siblings. - let leaf_is_left = Boolean::new_witness(r1cs_core::ns!(cs, "leaf_is_left"), || { - Ok(leaf_hash.value()?.eq(&self.path[0].0.value()?)) - })?; - - let mut result = - leaf_hash.is_eq(&leaf_is_left.select(&self.path[0].0, &self.path[0].1)?)?; - - // Check levels between leaf level and root. - let mut previous_hash = leaf_hash; - for &(ref left_hash, ref right_hash) in &self.path { - // Check if the previous_hash matches the correct current hash. - let previous_is_left = - Boolean::new_witness(r1cs_core::ns!(cs, "previous_is_left"), || { - Ok(previous_hash.value()?.eq(&left_hash.value()?)) - })?; - - let ns = r1cs_core::ns!(cs, "enforcing that inner hash is correct"); - let equality_cmp = previous_is_left.select(left_hash, right_hash)?; - result = result.and(&previous_hash.is_eq(&equality_cmp)?)?; - drop(ns); - - previous_hash = - hash_inner_node::(parameters, left_hash, right_hash)?; - } - - result.and(&root.is_eq(&previous_hash)?) - } -} - -pub(crate) fn hash_inner_node( - parameters: &HG::ParametersVar, - left_child: &HG::OutputVar, - right_child: &HG::OutputVar, -) -> Result -where - ConstraintF: Field, - H: FixedLengthCRH, - HG: FixedLengthCRHGadget, -{ - let left_bytes = left_child.to_bytes()?; - let right_bytes = right_child.to_bytes()?; - let mut bytes = left_bytes; - bytes.extend_from_slice(&right_bytes); - - HG::evaluate(parameters, &bytes) -} - -impl AllocVar, ConstraintF> for PathVar -where - P: Config, - HGadget: FixedLengthCRHGadget, - ConstraintF: Field, -{ - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - f().and_then(|val| { - let mut path = Vec::new(); - for &(ref l, ref r) in val.borrow().path.iter() { - let l_hash = HGadget::OutputVar::new_variable( - r1cs_core::ns!(cs, "l_child"), - || Ok(l), - mode, - )?; - let r_hash = HGadget::OutputVar::new_variable( - r1cs_core::ns!(cs, "r_child"), - || Ok(r), - mode, - )?; - path.push((l_hash, r_hash)); - } - Ok(PathVar { path }) - }) - } -} - -#[cfg(test)] -mod test { - use crate::{ - crh::{ - pedersen::{self, constraints::CRHGadget}, - FixedLengthCRH, FixedLengthCRHGadget, - }, - merkle_tree::*, - }; - use algebra::ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; - use r1cs_core::ConstraintSystem; - use rand::SeedableRng; - use rand_xorshift::XorShiftRng; - - use super::*; - use r1cs_std::ed_on_bls12_381::EdwardsVar; - - #[derive(Clone)] - pub(super) struct Window4x256; - impl pedersen::Window for Window4x256 { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 256; - } - - type H = pedersen::CRH; - type HG = CRHGadget; - - struct JubJubMerkleTreeParams; - - impl Config for JubJubMerkleTreeParams { - const HEIGHT: usize = 32; - type H = H; - } - - type JubJubMerkleTree = MerkleTree; - - fn generate_merkle_tree(leaves: &[[u8; 30]], use_bad_root: bool) -> () { - let mut rng = XorShiftRng::seed_from_u64(9174123u64); - - let crh_parameters = H::setup(&mut rng).unwrap(); - let tree = JubJubMerkleTree::new(crh_parameters.clone(), leaves).unwrap(); - let root = tree.root(); - let cs = ConstraintSystem::::new_ref(); - for (i, leaf) in leaves.iter().enumerate() { - let proof = tree.generate_proof(i, &leaf).unwrap(); - assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap()); - - // Allocate Merkle Tree Root - let root = >::OutputVar::new_witness( - r1cs_core::ns!(cs, "new_digest"), - || { - if use_bad_root { - Ok(::Output::default()) - } else { - Ok(root) - } - }, - ) - .unwrap(); - - let constraints_from_digest = cs.num_constraints(); - println!("constraints from digest: {}", constraints_from_digest); - - // Allocate Parameters for CRH - let crh_parameters = >::ParametersVar::new_constant( - r1cs_core::ns!(cs, "new_parameter"), - &crh_parameters, - ) - .unwrap(); - - let constraints_from_parameters = cs.num_constraints() - constraints_from_digest; - println!( - "constraints from parameters: {}", - constraints_from_parameters - ); - - // Allocate Leaf - let leaf_g = UInt8::constant_vec(leaf); - - let constraints_from_leaf = - cs.num_constraints() - constraints_from_parameters - constraints_from_digest; - println!("constraints from leaf: {}", constraints_from_leaf); - - // Allocate Merkle Tree Path - let cw = - PathVar::<_, HG, _>::new_witness(r1cs_core::ns!(cs, "new_witness"), || Ok(&proof)) - .unwrap(); - for (i, (l, r)) in cw.path.iter().enumerate() { - assert_eq!(l.value().unwrap(), proof.path[i].0); - assert_eq!(r.value().unwrap(), proof.path[i].1); - } - - let constraints_from_path = cs.num_constraints() - - constraints_from_parameters - - constraints_from_digest - - constraints_from_leaf; - println!("constraints from path: {}", constraints_from_path); - let leaf_g: &[_] = leaf_g.as_slice(); - cw.check_membership(&crh_parameters, &root, &leaf_g) - .unwrap() - .enforce_equal(&Boolean::TRUE) - .unwrap(); - let setup_constraints = constraints_from_leaf - + constraints_from_digest - + constraints_from_parameters - + constraints_from_path; - println!( - "number of constraints: {}", - cs.num_constraints() - setup_constraints - ); - } - - assert!(cs.is_satisfied().unwrap()); - } - - #[test] - fn good_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - let input = [i; 30]; - leaves.push(input); - } - generate_merkle_tree(&leaves, false); - } - - #[should_panic] - #[test] - fn bad_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - let input = [i; 30]; - leaves.push(input); - } - generate_merkle_tree(&leaves, true); - } -} diff --git a/crypto-primitives/src/merkle_tree/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs deleted file mode 100644 index 50e6f60..0000000 --- a/crypto-primitives/src/merkle_tree/mod.rs +++ /dev/null @@ -1,449 +0,0 @@ -use crate::{crh::FixedLengthCRH, Vec}; -use algebra_core::bytes::ToBytes; -use core::fmt; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub trait Config { - const HEIGHT: usize; - type H: FixedLengthCRH; -} - -/// Stores the hashes of a particular path (in order) from leaf to root. -/// Our path `is_left_child()` if the boolean in `path` is true. -#[derive(Derivative)] -#[derivative( - Clone(bound = "P: Config"), - Debug(bound = "P: Config, ::Output: fmt::Debug") -)] -pub struct Path { - pub(crate) path: Vec<( - ::Output, - ::Output, - )>, -} - -pub type Parameters

= <

::H as FixedLengthCRH>::Parameters; -pub type Digest

= <

::H as FixedLengthCRH>::Output; - -impl Default for Path

{ - fn default() -> Self { - let mut path = Vec::with_capacity(P::HEIGHT as usize); - for _i in 1..P::HEIGHT as usize { - path.push(( - ::Output::default(), - ::Output::default(), - )); - } - Self { path } - } -} - -impl Path

{ - pub fn verify( - &self, - parameters: &::Parameters, - root_hash: &::Output, - leaf: &L, - ) -> Result { - if self.path.len() != (P::HEIGHT - 1) as usize { - return Ok(false); - } - // Check that the given leaf matches the leaf in the membership proof. - let mut buffer = [0u8; 128]; - - if !self.path.is_empty() { - let claimed_leaf_hash = hash_leaf::(parameters, leaf, &mut buffer)?; - - // Check if leaf is one of the bottom-most siblings. - if claimed_leaf_hash != self.path[0].0 && claimed_leaf_hash != self.path[0].1 { - return Ok(false); - }; - - let mut prev = claimed_leaf_hash; - // Check levels between leaf level and root. - for &(ref hash, ref sibling_hash) in &self.path { - // Check if the previous hash matches the correct current hash. - if &prev != hash && &prev != sibling_hash { - return Ok(false); - }; - prev = hash_inner_node::(parameters, hash, sibling_hash, &mut buffer)?; - } - - if root_hash != &prev { - return Ok(false); - } - Ok(true) - } else { - Ok(false) - } - } -} - -pub struct MerkleTree { - tree: Vec<::Output>, - padding_tree: Vec<( - ::Output, - ::Output, - )>, - parameters: ::Parameters, - root: Option<::Output>, -} - -impl MerkleTree

{ - pub const HEIGHT: u8 = P::HEIGHT as u8; - - pub fn blank(parameters: ::Parameters) -> Self { - MerkleTree { - tree: Vec::new(), - padding_tree: Vec::new(), - root: None, - parameters, - } - } - - pub fn new( - parameters: ::Parameters, - leaves: &[L], - ) -> Result { - let new_time = start_timer!(|| "MerkleTree::New"); - - let last_level_size = leaves.len().next_power_of_two(); - let tree_size = 2 * last_level_size - 1; - let tree_height = tree_height(tree_size); - assert!(tree_height as u8 <= Self::HEIGHT); - - // Initialize the merkle tree. - let mut tree = Vec::with_capacity(tree_size); - let empty_hash = hash_empty::(¶meters)?; - for _ in 0..tree_size { - tree.push(empty_hash.clone()); - } - - // Compute the starting indices for each level of the tree. - let mut index = 0; - let mut level_indices = Vec::with_capacity(tree_height); - for _ in 0..tree_height { - level_indices.push(index); - index = left_child(index); - } - - // Compute and store the hash values for each leaf. - let last_level_index = level_indices.pop().unwrap_or(0); - let mut buffer = [0u8; 128]; - for (i, leaf) in leaves.iter().enumerate() { - tree[last_level_index + i] = hash_leaf::(¶meters, leaf, &mut buffer)?; - } - - // Compute the hash values for every node in the tree. - let mut upper_bound = last_level_index; - let mut buffer = [0u8; 128]; - level_indices.reverse(); - for &start_index in &level_indices { - // Iterate over the current level. - for current_index in start_index..upper_bound { - let left_index = left_child(current_index); - let right_index = right_child(current_index); - - // Compute Hash(left || right). - tree[current_index] = hash_inner_node::( - ¶meters, - &tree[left_index], - &tree[right_index], - &mut buffer, - )?; - } - upper_bound = start_index; - } - // Finished computing actual tree. - // Now, we compute the dummy nodes until we hit our HEIGHT goal. - let mut cur_height = tree_height; - let mut padding_tree = Vec::new(); - let mut cur_hash = tree[0].clone(); - let root_hash = if cur_height < Self::HEIGHT as usize { - while cur_height < (Self::HEIGHT - 1) as usize { - cur_hash = - hash_inner_node::(¶meters, &cur_hash, &empty_hash, &mut buffer)?; - padding_tree.push((cur_hash.clone(), empty_hash.clone())); - cur_height += 1; - } - hash_inner_node::(¶meters, &cur_hash, &empty_hash, &mut buffer)? - } else { - cur_hash - }; - end_timer!(new_time); - - Ok(MerkleTree { - tree, - padding_tree, - parameters, - root: Some(root_hash), - }) - } - - #[inline] - pub fn root(&self) -> ::Output { - self.root.clone().unwrap() - } - - pub fn generate_proof( - &self, - index: usize, - leaf: &L, - ) -> Result, crate::Error> { - let prove_time = start_timer!(|| "MerkleTree::GenProof"); - let mut path = Vec::new(); - - let mut buffer = [0u8; 128]; - let leaf_hash = hash_leaf::(&self.parameters, leaf, &mut buffer)?; - let tree_height = tree_height(self.tree.len()); - let tree_index = convert_index_to_last_level(index, tree_height); - let empty_hash = hash_empty::(&self.parameters)?; - - // Check that the given index corresponds to the correct leaf. - if leaf_hash != self.tree[tree_index] { - return Err(Error::IncorrectLeafIndex(tree_index).into()); - } - - // Iterate from the leaf up to the root, storing all intermediate hash values. - let mut current_node = tree_index; - while !is_root(current_node) { - let sibling_node = sibling(current_node).unwrap(); - let (curr_hash, sibling_hash) = ( - self.tree[current_node].clone(), - self.tree[sibling_node].clone(), - ); - if is_left_child(current_node) { - path.push((curr_hash, sibling_hash)); - } else { - path.push((sibling_hash, curr_hash)); - } - current_node = parent(current_node).unwrap(); - } - - // Store the root node. Set boolean as true for consistency with digest - // location. - assert!(path.len() < Self::HEIGHT as usize); - if path.len() != (Self::HEIGHT - 1) as usize { - path.push((self.tree[0].clone(), empty_hash)); - for &(ref hash, ref sibling_hash) in &self.padding_tree { - path.push((hash.clone(), sibling_hash.clone())); - } - } - end_timer!(prove_time); - if path.len() != (Self::HEIGHT - 1) as usize { - return Err(Error::IncorrectPathLength(path.len()).into()); - } else { - Ok(Path { path }) - } - } -} - -#[derive(Debug)] -pub enum Error { - IncorrectLeafIndex(usize), - IncorrectPathLength(usize), -} - -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let msg = match self { - Error::IncorrectLeafIndex(index) => format!("incorrect leaf index: {}", index), - Error::IncorrectPathLength(len) => format!("incorrect path length: {}", len), - }; - write!(f, "{}", msg) - } -} - -impl algebra_core::Error for Error {} - -/// Returns the height of the tree, given the size of the tree. -#[inline] -fn tree_height(tree_size: usize) -> usize { - if tree_size == 1 { - return 1; - } - - algebra_core::log2(tree_size) as usize -} - -/// Returns true iff the index represents the root. -#[inline] -fn is_root(index: usize) -> bool { - index == 0 -} - -/// Returns the index of the left child, given an index. -#[inline] -fn left_child(index: usize) -> usize { - 2 * index + 1 -} - -/// Returns the index of the right child, given an index. -#[inline] -fn right_child(index: usize) -> usize { - 2 * index + 2 -} - -/// Returns the index of the sibling, given an index. -#[inline] -fn sibling(index: usize) -> Option { - if index == 0 { - None - } else if is_left_child(index) { - Some(index + 1) - } else { - Some(index - 1) - } -} - -/// Returns true iff the given index represents a left child. -#[inline] -fn is_left_child(index: usize) -> bool { - index % 2 == 1 -} - -/// Returns the index of the parent, given an index. -#[inline] -fn parent(index: usize) -> Option { - if index > 0 { - Some((index - 1) >> 1) - } else { - None - } -} - -#[inline] -fn convert_index_to_last_level(index: usize, tree_height: usize) -> usize { - index + (1 << (tree_height - 1)) - 1 -} - -/// Returns the output hash, given a left and right hash value. -pub(crate) fn hash_inner_node( - parameters: &H::Parameters, - left: &H::Output, - right: &H::Output, - buffer: &mut [u8], -) -> Result { - let bytes = algebra_core::to_bytes![left]? - .into_iter() - .chain(algebra_core::to_bytes![right]?); - buffer.iter_mut().zip(bytes).for_each(|(b, l_b)| *b = l_b); - H::evaluate(parameters, &buffer[..(H::INPUT_SIZE_BITS / 8)]) -} - -/// Returns the hash of a leaf. -pub(crate) fn hash_leaf( - parameters: &H::Parameters, - leaf: &L, - buffer: &mut [u8], -) -> Result { - buffer - .iter_mut() - .zip(&algebra_core::to_bytes![leaf]?) - .for_each(|(b, l_b)| *b = *l_b); - H::evaluate(parameters, &buffer[..(H::INPUT_SIZE_BITS / 8)]) -} - -pub(crate) fn hash_empty( - parameters: &H::Parameters, -) -> Result { - let empty_buffer = vec![0u8; H::INPUT_SIZE_BITS / 8]; - H::evaluate(parameters, &empty_buffer) -} - -#[cfg(test)] -mod test { - use crate::{ - crh::{pedersen, *}, - merkle_tree::*, - }; - use algebra::{ed_on_bls12_381::EdwardsProjective as JubJub, Zero}; - use rand::SeedableRng; - use rand_xorshift::XorShiftRng; - - #[derive(Clone)] - pub(super) struct Window4x256; - impl pedersen::Window for Window4x256 { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 256; - } - - type H = pedersen::CRH; - - struct JubJubMerkleTreeParams; - - impl Config for JubJubMerkleTreeParams { - const HEIGHT: usize = 8; - type H = H; - } - type JubJubMerkleTree = MerkleTree; - - fn generate_merkle_tree(leaves: &[L]) -> () { - let mut rng = XorShiftRng::seed_from_u64(9174123u64); - - let crh_parameters = H::setup(&mut rng).unwrap(); - let tree = JubJubMerkleTree::new(crh_parameters.clone(), &leaves).unwrap(); - let root = tree.root(); - for (i, leaf) in leaves.iter().enumerate() { - let proof = tree.generate_proof(i, &leaf).unwrap(); - assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap()); - } - } - - #[test] - fn good_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - leaves.push([i, i, i, i, i, i, i, i]); - } - generate_merkle_tree(&leaves); - let mut leaves = Vec::new(); - for i in 0..100u8 { - leaves.push([i, i, i, i, i, i, i, i]); - } - generate_merkle_tree(&leaves); - } - - #[test] - fn no_dummy_nodes_test() { - let mut leaves = Vec::new(); - for i in 0..(1u8 << JubJubMerkleTree::HEIGHT - 1) { - leaves.push([i, i, i, i, i, i, i, i]); - } - generate_merkle_tree(&leaves); - } - - #[test] - fn single_leaf_test() { - generate_merkle_tree(&[[1u8; 8]]); - } - - fn bad_merkle_tree_verify(leaves: &[L]) -> () { - let mut rng = XorShiftRng::seed_from_u64(13423423u64); - - let crh_parameters = H::setup(&mut rng).unwrap(); - let tree = JubJubMerkleTree::new(crh_parameters.clone(), &leaves).unwrap(); - let root = JubJub::zero().into(); - for (i, leaf) in leaves.iter().enumerate() { - let proof = tree.generate_proof(i, &leaf).unwrap(); - assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap()); - } - } - - #[should_panic] - #[test] - fn bad_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - leaves.push([i, i, i, i, i, i, i, i]); - } - generate_merkle_tree(&leaves); - let mut leaves = Vec::new(); - for i in 0..100u8 { - leaves.push([i, i, i, i, i, i, i, i]); - } - bad_merkle_tree_verify(&leaves); - } -} diff --git a/crypto-primitives/src/nizk/constraints.rs b/crypto-primitives/src/nizk/constraints.rs deleted file mode 100644 index 037106e..0000000 --- a/crypto-primitives/src/nizk/constraints.rs +++ /dev/null @@ -1,51 +0,0 @@ -use algebra_core::Field; -use core::borrow::Borrow; -use r1cs_core::{Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use crate::nizk::NIZK; - -pub trait NIZKVerifierGadget { - type PreparedVerificationKeyVar; - type VerificationKeyVar: AllocVar - + ToBytesGadget; - type ProofVar: AllocVar; - - /// Optionally allocates `N::Proof` in `cs` without performing - /// subgroup checks. - /// - /// The default implementation doesn't omit these checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_proof_unchecked>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - Self::ProofVar::new_variable(cs, f, mode) - } - - /// Optionally allocates `N::VerificationParameters` in `cs` - /// without performing subgroup checks. - /// - /// The default implementation doesn't omit these checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_verification_key_unchecked>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - Self::VerificationKeyVar::new_variable(cs, f, mode) - } - - fn verify<'a, T: 'a + ToBitsGadget + ?Sized>( - verification_key: &Self::VerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError>; - - fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( - prepared_verification_key: &Self::PreparedVerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError>; -} diff --git a/crypto-primitives/src/nizk/gm17/constraints.rs b/crypto-primitives/src/nizk/gm17/constraints.rs deleted file mode 100644 index 2a9346d..0000000 --- a/crypto-primitives/src/nizk/gm17/constraints.rs +++ /dev/null @@ -1,797 +0,0 @@ -use crate::{ - nizk::{gm17::Gm17, NIZKVerifierGadget}, - Vec, -}; -use algebra_core::{AffineCurve, PairingEngine, ToConstraintField}; -use r1cs_core::{ConstraintSynthesizer, Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use core::{borrow::Borrow, marker::PhantomData}; -use gm17::{PreparedVerifyingKey, Proof, VerifyingKey}; - -#[derive(Derivative)] -#[derivative(Clone(bound = "P::G1Var: Clone, P::G2Var: Clone"))] -pub struct ProofVar> { - pub a: P::G1Var, - pub b: P::G2Var, - pub c: P::G1Var, -} - -#[derive(Derivative)] -#[derivative( - Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ - P::G2PreparedVar: Clone, ") -)] -pub struct VerifyingKeyVar> { - pub h_g2: P::G2Var, - pub g_alpha_g1: P::G1Var, - pub h_beta_g2: P::G2Var, - pub g_gamma_g1: P::G1Var, - pub h_gamma_g2: P::G2Var, - pub query: Vec, -} - -impl> VerifyingKeyVar { - #[tracing::instrument(target = "r1cs", skip(self))] - pub fn prepare(&self) -> Result, SynthesisError> { - let g_alpha_pc = P::prepare_g1(&self.g_alpha_g1)?; - let h_beta_pc = P::prepare_g2(&self.h_beta_g2)?; - let g_gamma_pc = P::prepare_g1(&self.g_gamma_g1)?; - let h_gamma_pc = P::prepare_g2(&self.h_gamma_g2)?; - let h_pc = P::prepare_g2(&self.h_g2)?; - Ok(PreparedVerifyingKeyVar { - g_alpha: self.g_alpha_g1.clone(), - h_beta: self.h_beta_g2.clone(), - g_alpha_pc, - h_beta_pc, - g_gamma_pc, - h_gamma_pc, - h_pc, - query: self.query.clone(), - }) - } -} - -#[derive(Derivative)] -#[derivative( - Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ - P::G2PreparedVar: Clone, ") -)] -pub struct PreparedVerifyingKeyVar> { - pub g_alpha: P::G1Var, - pub h_beta: P::G2Var, - pub g_alpha_pc: P::G1PreparedVar, - pub h_beta_pc: P::G2PreparedVar, - pub g_gamma_pc: P::G1PreparedVar, - pub h_gamma_pc: P::G2PreparedVar, - pub h_pc: P::G2PreparedVar, - pub query: Vec, -} - -pub struct Gm17VerifierGadget -where - E: PairingEngine, - P: PairingVar, -{ - _pairing_engine: PhantomData, - _pairing_gadget: PhantomData

, -} - -impl NIZKVerifierGadget, E::Fq> for Gm17VerifierGadget -where - E: PairingEngine, - C: ConstraintSynthesizer, - V: ToConstraintField, - P: PairingVar, -{ - type PreparedVerificationKeyVar = PreparedVerifyingKeyVar; - type VerificationKeyVar = VerifyingKeyVar; - type ProofVar = ProofVar; - - /// Allocates `N::Proof` in `cs` without performing - /// subgroup checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_proof_unchecked>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - f().and_then(|proof| { - let proof = proof.borrow(); - let a = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.a"), - || Ok(proof.a.into_projective()), - mode, - )?; - let b = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.b"), - || Ok(proof.b.into_projective()), - mode, - )?; - let c = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.c"), - || Ok(proof.c.into_projective()), - mode, - )?; - Ok(ProofVar { a, b, c }) - }) - } - - /// Allocates `N::Proof` in `cs` without performing - /// subgroup checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_verification_key_unchecked>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - f().and_then(|vk| { - let vk = vk.borrow(); - let g_alpha_g1 = P::G1Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "g_alpha"), - || Ok(vk.g_alpha_g1.into_projective()), - mode, - )?; - let h_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "h"), - || Ok(vk.h_g2.into_projective()), - mode, - )?; - let h_beta_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "h_beta"), - || Ok(vk.h_beta_g2.into_projective()), - mode, - )?; - let g_gamma_g1 = P::G1Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "g_gamma"), - || Ok(vk.g_gamma_g1.into_projective()), - mode, - )?; - let h_gamma_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "h_gamma"), - || Ok(vk.h_gamma_g2.into_projective()), - mode, - )?; - - let query = vk - .query - .iter() - .map(|g| { - P::G1Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "g"), - || Ok(g.into_projective()), - mode, - ) - }) - .collect::, _>>()?; - Ok(VerifyingKeyVar { - g_alpha_g1, - h_g2, - h_beta_g2, - g_gamma_g1, - h_gamma_g2, - query, - }) - }) - } - - #[tracing::instrument(target = "r1cs", skip(vk, input, proof))] - fn verify<'a, T: 'a + ToBitsGadget + ?Sized>( - vk: &Self::VerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError> { - let pvk = vk.prepare()?; - , E::Fq>>::verify_prepared(&pvk, input, proof) - } - - #[tracing::instrument(target = "r1cs", skip(pvk, input, proof))] - fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( - pvk: &Self::PreparedVerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError> { - let pvk = pvk.clone(); - // e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) * - // e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i] - let g_psi = { - let mut g_psi = pvk.query[0].clone(); - let mut input_len = 1; - let mut input = input.into_iter(); - for (input, b) in input.by_ref().zip(pvk.query.iter().skip(1)) { - let input_bits = input.to_bits_le()?; - g_psi += b.scalar_mul_le(input_bits.iter())?; - input_len += 1; - } - // Check that the input and the query in the verification are of the - // same length. - assert!(input_len == pvk.query.len() && input.next().is_none()); - g_psi - }; - - let mut test1_a_g_alpha = proof.a.clone(); - test1_a_g_alpha += pvk.g_alpha.clone(); - let mut test1_b_h_beta = proof.b.clone(); - test1_b_h_beta += pvk.h_beta.clone(); - - let test1_exp = { - test1_a_g_alpha = test1_a_g_alpha.negate()?; - let test1_a_g_alpha_prep = P::prepare_g1(&test1_a_g_alpha)?; - let test1_b_h_beta_prep = P::prepare_g2(&test1_b_h_beta)?; - - let g_psi_prep = P::prepare_g1(&g_psi)?; - - let c_prep = P::prepare_g1(&proof.c)?; - - P::miller_loop( - &[ - test1_a_g_alpha_prep, - g_psi_prep, - c_prep, - pvk.g_alpha_pc.clone(), - ], - &[ - test1_b_h_beta_prep, - pvk.h_gamma_pc.clone(), - pvk.h_pc.clone(), - pvk.h_beta_pc.clone(), - ], - )? - }; - - let test1 = P::final_exponentiation(&test1_exp).unwrap(); - - // e(A, H^{gamma}) = e(G^{gamma}, B) - let test2_exp = { - let a_prep = P::prepare_g1(&proof.a)?; - // pvk.h_gamma_pc - //&pvk.g_gamma_pc - let proof_b = proof.b.negate()?; - let b_prep = P::prepare_g2(&proof_b)?; - P::miller_loop(&[a_prep, pvk.g_gamma_pc.clone()], &[pvk.h_gamma_pc, b_prep])? - }; - let test2 = P::final_exponentiation(&test2_exp)?; - - let one = P::GTVar::one(); - test1.is_eq(&one)?.and(&test2.is_eq(&one)?) - } -} - -impl AllocVar, E::Fq> for PreparedVerifyingKeyVar -where - E: PairingEngine, - P: PairingVar, - P::G1PreparedVar: AllocVar, - P::G2PreparedVar: AllocVar, -{ - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|pvk| { - let pvk = pvk.borrow(); - let g_alpha = - P::G1Var::new_variable(r1cs_core::ns!(cs, "g_alpha"), || Ok(pvk.g_alpha), mode)?; - let h_beta = - P::G2Var::new_variable(r1cs_core::ns!(cs, "h_beta"), || Ok(pvk.h_beta), mode)?; - let g_alpha_pc = P::G1PreparedVar::new_variable( - r1cs_core::ns!(cs, "g_alpha_pc"), - || Ok(pvk.g_alpha.into()), - mode, - )?; - let h_beta_pc = P::G2PreparedVar::new_variable( - r1cs_core::ns!(cs, "h_beta_pc"), - || Ok(pvk.h_beta.into()), - mode, - )?; - let g_gamma_pc = P::G1PreparedVar::new_variable( - r1cs_core::ns!(cs, "g_gamma_pc"), - || Ok(&pvk.g_gamma_pc), - mode, - )?; - let h_gamma_pc = P::G2PreparedVar::new_variable( - r1cs_core::ns!(cs, "h_gamma_pc"), - || Ok(&pvk.h_gamma_pc), - mode, - )?; - let h_pc = - P::G2PreparedVar::new_variable(r1cs_core::ns!(cs, "h_pc"), || Ok(&pvk.h_pc), mode)?; - let query = - Vec::new_variable(r1cs_core::ns!(cs, "query"), || Ok(pvk.query.clone()), mode)?; - - Ok(Self { - g_alpha, - h_beta, - g_alpha_pc, - h_beta_pc, - g_gamma_pc, - h_gamma_pc, - h_pc, - query, - }) - }) - } -} - -impl AllocVar, E::Fq> for VerifyingKeyVar -where - E: PairingEngine, - - P: PairingVar, -{ - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|vk| { - let vk = vk.borrow(); - let g_alpha_g1 = - P::G1Var::new_variable(r1cs_core::ns!(cs, "g_alpha"), || Ok(vk.g_alpha_g1), mode)?; - let h_g2 = P::G2Var::new_variable(r1cs_core::ns!(cs, "h"), || Ok(vk.h_g2), mode)?; - let h_beta_g2 = - P::G2Var::new_variable(r1cs_core::ns!(cs, "h_beta"), || Ok(vk.h_beta_g2), mode)?; - let g_gamma_g1 = - P::G1Var::new_variable(r1cs_core::ns!(cs, "g_gamma"), || Ok(&vk.g_gamma_g1), mode)?; - let h_gamma_g2 = - P::G2Var::new_variable(r1cs_core::ns!(cs, "h_gamma"), || Ok(&vk.h_gamma_g2), mode)?; - let query = - Vec::new_variable(r1cs_core::ns!(cs, "query"), || Ok(vk.query.clone()), mode)?; - Ok(Self { - h_g2, - g_alpha_g1, - h_beta_g2, - g_gamma_g1, - h_gamma_g2, - query, - }) - }) - } -} - -impl AllocVar, E::Fq> for ProofVar -where - E: PairingEngine, - - P: PairingVar, -{ - #[inline] - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|proof| { - let Proof { a, b, c } = proof.borrow().clone(); - let a = P::G1Var::new_variable(cs.clone(), || Ok(a), mode)?; - let b = P::G2Var::new_variable(cs.clone(), || Ok(b), mode)?; - let c = P::G1Var::new_variable(r1cs_core::ns!(cs, "c"), || Ok(c), mode)?; - Ok(Self { a, b, c }) - }) - } -} - -impl ToBytesGadget for VerifyingKeyVar -where - E: PairingEngine, - - P: PairingVar, -{ - #[inline] - fn to_bytes(&self) -> Result>, SynthesisError> { - let mut bytes = Vec::new(); - bytes.extend_from_slice(&self.h_g2.to_bytes()?); - bytes.extend_from_slice(&self.g_alpha_g1.to_bytes()?); - bytes.extend_from_slice(&self.h_beta_g2.to_bytes()?); - bytes.extend_from_slice(&self.g_gamma_g1.to_bytes()?); - bytes.extend_from_slice(&self.h_gamma_g2.to_bytes()?); - for q in &self.query { - bytes.extend_from_slice(&q.to_bytes()?); - } - Ok(bytes) - } -} - -#[cfg(test)] -mod test { - use gm17::*; - use r1cs_core::{ - lc, ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError, - }; - - use super::*; - use algebra::{ - bls12_377::{Bls12_377, Fq, Fr}, - test_rng, BitIteratorLE, Field, PrimeField, - }; - use r1cs_std::{bls12_377::PairingVar as Bls12_377PairingVar, boolean::Boolean, Assignment}; - use rand::Rng; - - type TestProofSystem = Gm17, Fr>; - type TestVerifierGadget = Gm17VerifierGadget; - type TestProofVar = ProofVar; - type TestVkVar = VerifyingKeyVar; - - struct Bench { - inputs: Vec>, - num_constraints: usize, - } - - impl ConstraintSynthesizer for Bench { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - assert!(self.inputs.len() >= 2); - assert!(self.num_constraints >= self.inputs.len()); - - let mut variables: Vec<_> = Vec::with_capacity(self.inputs.len()); - for input in self.inputs { - let input_var = cs.new_input_variable(|| input.get())?; - variables.push((input, input_var)); - } - - for i in 0..self.num_constraints { - let new_entry = { - let (input_1_val, input_1_var) = variables[i]; - let (input_2_val, input_2_var) = variables[i + 1]; - let result_val = input_1_val - .and_then(|input_1| input_2_val.map(|input_2| input_1 * &input_2)); - let result_var = cs.new_witness_variable(|| { - result_val.ok_or(SynthesisError::AssignmentMissing) - })?; - cs.enforce_constraint( - lc!() + input_1_var, - lc!() + input_2_var, - lc!() + result_var, - ) - .unwrap(); - (result_val, result_var) - }; - variables.push(new_entry); - } - Ok(()) - } - } - - #[test] - fn gm17_verifier_test() { - let num_inputs = 100; - let num_constraints = num_inputs; - let rng = &mut test_rng(); - let mut inputs: Vec> = Vec::with_capacity(num_inputs); - for _ in 0..num_inputs { - inputs.push(Some(rng.gen())); - } - let params = { - let c = Bench:: { - inputs: vec![None; num_inputs], - num_constraints, - }; - - generate_random_parameters(c, rng).unwrap() - }; - - { - let proof = { - // Create an instance of our circuit (with the - // witness) - let c = Bench { - inputs: inputs.clone(), - num_constraints, - }; - // Create a gm17 proof with our parameters. - create_random_proof(c, ¶ms, rng).unwrap() - }; - - // assert!(!verify_proof(&pvk, &proof, &[a]).unwrap()); - let cs = ConstraintSystem::::new_ref(); - - let inputs: Vec<_> = inputs.into_iter().map(|input| input.unwrap()).collect(); - let mut input_gadgets = Vec::new(); - - { - for input in inputs.into_iter() { - let input_bits: Vec<_> = BitIteratorLE::new(input.into_repr()).collect(); - let input_bits = - Vec::>::new_input(r1cs_core::ns!(cs, "Input"), || { - Ok(input_bits) - }) - .unwrap(); - input_gadgets.push(input_bits); - } - } - - let vk_gadget = - TestVkVar::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk)).unwrap(); - let proof_gadget = - TestProofVar::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - println!("Time to verify!\n\n\n\n"); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - ) - .unwrap() - .enforce_equal(&Boolean::TRUE) - .unwrap(); - - if !cs.is_satisfied().unwrap() { - println!("========================================================="); - println!("Unsatisfied constraints:"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - println!("========================================================="); - } - - // cs.print_named_objects(); - assert!(cs.is_satisfied().unwrap()); - } - } -} - -#[cfg(test)] -mod test_recursive { - use gm17::*; - use r1cs_core::{ - lc, ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError, - }; - - use super::*; - use algebra::{ - fields::{FftParameters, FpParameters}, - mnt4_298::{Fq as MNT4Fq, FqParameters as MNT4FqParameters, Fr as MNT4Fr, MNT4_298}, - mnt6_298::{Fq as MNT6Fq, FqParameters as MNT6FqParameters, Fr as MNT6Fr, MNT6_298}, - test_rng, BigInteger, Field, PrimeField, - }; - use r1cs_std::{ - fields::fp::FpVar, mnt4_298::PairingVar as MNT4_298PairingVar, - mnt6_298::PairingVar as MNT6_298PairingVar, uint8::UInt8, Assignment, - }; - use rand::Rng; - - type TestProofSystem1 = Gm17, MNT6Fr>; - type TestVerifierGadget1 = Gm17VerifierGadget; - type TestProofVar1 = ProofVar; - type TestVkVar1 = VerifyingKeyVar; - - type TestProofSystem2 = Gm17; - type TestVerifierGadget2 = Gm17VerifierGadget; - type TestProofVar2 = ProofVar; - type TestVkVar2 = VerifyingKeyVar; - - #[derive(Clone)] - struct Bench { - inputs: Vec>, - num_constraints: usize, - } - - impl ConstraintSynthesizer for Bench { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - assert!(self.inputs.len() >= 2); - assert!(self.num_constraints >= self.inputs.len()); - - let mut variables: Vec<_> = Vec::with_capacity(self.inputs.len()); - for input in self.inputs { - let input_var = cs.new_input_variable(|| input.get())?; - variables.push((input, input_var)); - } - - for i in 0..self.num_constraints { - let new_entry = { - let (input_1_val, input_1_var) = variables[i]; - let (input_2_val, input_2_var) = variables[i + 1]; - let result_val = input_1_val - .and_then(|input_1| input_2_val.map(|input_2| input_1 * &input_2)); - let result_var = cs.new_witness_variable(|| { - result_val.ok_or(SynthesisError::AssignmentMissing) - })?; - cs.enforce_constraint( - lc!() + input_1_var, - lc!() + input_2_var, - lc!() + result_var, - ) - .unwrap(); - (result_val, result_var) - }; - variables.push(new_entry); - } - Ok(()) - } - } - - struct Wrapper { - inputs: Vec>, - params: Parameters, - proof: Proof, - } - - impl ConstraintSynthesizer for Wrapper { - fn generate_constraints( - self, - cs: ConstraintSystemRef, - ) -> Result<(), SynthesisError> { - let params = self.params; - let proof = self.proof; - let inputs: Vec<_> = self - .inputs - .into_iter() - .map(|input| input.unwrap()) - .collect(); - let input_gadgets; - - { - // Chain all input values in one large byte array. - let input_bytes = inputs - .clone() - .into_iter() - .flat_map(|input| { - input - .into_repr() - .as_ref() - .iter() - .flat_map(|l| l.to_le_bytes().to_vec()) - .collect::>() - }) - .collect::>(); - - // Allocate this byte array as input packed into field elements. - let input_bytes = - UInt8::new_input_vec(r1cs_core::ns!(cs, "Input"), &input_bytes[..])?; - // 40 byte - let element_size = ::BigInt::NUM_LIMBS * 8; - input_gadgets = input_bytes - .chunks(element_size) - .map(|chunk| { - chunk - .iter() - .flat_map(|byte| byte.to_bits_le().unwrap()) - .collect::>() - }) - .collect::>(); - } - - let vk_gadget = TestVkVar1::new_witness(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk))?; - let proof_gadget = - TestProofVar1::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - )? - .enforce_equal(&Boolean::TRUE)?; - Ok(()) - } - } - - #[test] - fn gm17_recursive_verifier_test() { - let num_inputs = 5; - let num_constraints = num_inputs; - let rng = &mut test_rng(); - let mut inputs: Vec> = Vec::with_capacity(num_inputs); - for _ in 0..num_inputs { - inputs.push(Some(rng.gen())); - } - - // Generate inner params and proof. - let inner_params = { - let c = Bench:: { - inputs: vec![None; num_inputs], - num_constraints, - }; - - generate_random_parameters(c, rng).unwrap() - }; - - let inner_proof = { - // Create an instance of our circuit (with the - // witness) - let c = Bench { - inputs: inputs.clone(), - num_constraints, - }; - // Create a gm17 proof with our parameters. - create_random_proof(c, &inner_params, rng).unwrap() - }; - - // Generate outer params and proof. - let params = { - let c = Wrapper { - inputs: inputs.clone(), - params: inner_params.clone(), - proof: inner_proof.clone(), - }; - - generate_random_parameters(c, rng).unwrap() - }; - - { - let proof = { - // Create an instance of our circuit (with the - // witness) - let c = Wrapper { - inputs: inputs.clone(), - params: inner_params.clone(), - proof: inner_proof.clone(), - }; - // Create a gm17 proof with our parameters. - create_random_proof(c, ¶ms, rng).unwrap() - }; - - let cs = ConstraintSystem::::new_ref(); - - let inputs: Vec<_> = inputs.into_iter().map(|input| input.unwrap()).collect(); - let mut input_gadgets = Vec::new(); - - { - let bigint_size = ::BigInt::NUM_LIMBS * 64; - let mut input_bits = Vec::new(); - for input in inputs.into_iter() { - let input_gadget = - FpVar::new_input(r1cs_core::ns!(cs, "Input"), || Ok(input)).unwrap(); - let mut fp_bits = input_gadget.to_bits_le().unwrap(); - - // Use 320 bits per element. - for _ in fp_bits.len()..bigint_size { - fp_bits.push(Boolean::constant(false)); - } - input_bits.extend_from_slice(&fp_bits); - } - - // Pack input bits into field elements of the underlying circuit. - let max_size = 8 * (::CAPACITY / 8) as usize; - let max_size = max_size as usize; - let bigint_size = ::BigInt::NUM_LIMBS * 64; - for chunk in input_bits.chunks(max_size) { - let mut chunk = chunk.to_vec(); - let len = chunk.len(); - for _ in len..bigint_size { - chunk.push(Boolean::constant(false)); - } - input_gadgets.push(chunk); - } - // assert!(!verify_proof(&pvk, &proof, &[a]).unwrap()); - } - - let vk_gadget = - TestVkVar2::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk)).unwrap(); - let proof_gadget = - TestProofVar2::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - println!("Time to verify!\n\n\n\n"); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - ) - .unwrap() - .enforce_equal(&Boolean::TRUE) - .unwrap(); - if !cs.is_satisfied().unwrap() { - println!("========================================================="); - println!("Unsatisfied constraints:"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - println!("========================================================="); - } - - // cs.print_named_objects(); - assert!(cs.is_satisfied().unwrap()); - } - } -} diff --git a/crypto-primitives/src/nizk/gm17/mod.rs b/crypto-primitives/src/nizk/gm17/mod.rs deleted file mode 100644 index 290add9..0000000 --- a/crypto-primitives/src/nizk/gm17/mod.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::Error; -use algebra_core::PairingEngine; -use gm17::{ - create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, - Parameters, PreparedVerifyingKey, Proof, VerifyingKey, -}; -use r1cs_core::ConstraintSynthesizer; -use rand::Rng; - -use algebra_core::ToConstraintField; -use core::marker::PhantomData; - -use super::NIZK; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -/// Note: V should serialize its contents to `Vec` in the same order as -/// during the constraint generation. -pub struct Gm17< - E: PairingEngine, - C: ConstraintSynthesizer, - V: ToConstraintField + ?Sized, -> { - #[doc(hidden)] - _engine: PhantomData, - #[doc(hidden)] - _circuit: PhantomData, - #[doc(hidden)] - _verifier_input: PhantomData, -} - -impl, V: ToConstraintField + ?Sized> NIZK - for Gm17 -{ - type Circuit = C; - type AssignedCircuit = C; - type VerifierInput = V; - type ProvingParameters = Parameters; - type VerificationParameters = VerifyingKey; - type PreparedVerificationParameters = PreparedVerifyingKey; - type Proof = Proof; - - fn setup( - circuit: Self::Circuit, - rng: &mut R, - ) -> Result< - ( - Self::ProvingParameters, - Self::PreparedVerificationParameters, - ), - Error, - > { - let nizk_time = start_timer!(|| "{Groth-Maller 2017}::Setup"); - let pp = generate_random_parameters::(circuit, rng)?; - let vk = prepare_verifying_key(&pp.vk); - end_timer!(nizk_time); - Ok((pp, vk)) - } - - fn prove( - pp: &Self::ProvingParameters, - input_and_witness: Self::AssignedCircuit, - rng: &mut R, - ) -> Result { - let proof_time = start_timer!(|| "{Groth-Maller 2017}::Prove"); - let result = create_random_proof::(input_and_witness, pp, rng)?; - end_timer!(proof_time); - Ok(result) - } - - fn verify( - vk: &Self::PreparedVerificationParameters, - input: &Self::VerifierInput, - proof: &Self::Proof, - ) -> Result { - let verify_time = start_timer!(|| "{Groth-Maller 2017}::Verify"); - let conversion_time = start_timer!(|| "Convert input to E::Fr"); - let input = input.to_field_elements()?; - end_timer!(conversion_time); - let verification = start_timer!(|| format!("Verify proof w/ input len: {}", input.len())); - let result = verify_proof(&vk, proof, &input)?; - end_timer!(verification); - end_timer!(verify_time); - Ok(result) - } -} diff --git a/crypto-primitives/src/nizk/groth16/constraints.rs b/crypto-primitives/src/nizk/groth16/constraints.rs deleted file mode 100644 index 24e9677..0000000 --- a/crypto-primitives/src/nizk/groth16/constraints.rs +++ /dev/null @@ -1,746 +0,0 @@ -use crate::{ - nizk::{groth16::Groth16, NIZKVerifierGadget}, - Vec, -}; -use algebra_core::{AffineCurve, PairingEngine, ToConstraintField}; -use r1cs_core::{ConstraintSynthesizer, Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use core::{borrow::Borrow, marker::PhantomData}; -use groth16::{PreparedVerifyingKey, Proof, VerifyingKey}; - -#[derive(Derivative)] -#[derivative(Clone(bound = "P::G1Var: Clone, P::G2Var: Clone"))] -pub struct ProofVar> { - pub a: P::G1Var, - pub b: P::G2Var, - pub c: P::G1Var, -} - -#[derive(Derivative)] -#[derivative( - Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ - P::G2PreparedVar: Clone, ") -)] -pub struct VerifyingKeyVar> { - pub alpha_g1: P::G1Var, - pub beta_g2: P::G2Var, - pub gamma_g2: P::G2Var, - pub delta_g2: P::G2Var, - pub gamma_abc_g1: Vec, -} - -impl> VerifyingKeyVar { - pub fn prepare(&self) -> Result, SynthesisError> { - let alpha_g1_pc = P::prepare_g1(&self.alpha_g1)?; - let beta_g2_pc = P::prepare_g2(&self.beta_g2)?; - - let alpha_g1_beta_g2 = P::pairing(alpha_g1_pc, beta_g2_pc)?; - let gamma_g2_neg_pc = P::prepare_g2(&self.gamma_g2.negate()?)?; - let delta_g2_neg_pc = P::prepare_g2(&self.delta_g2.negate()?)?; - - Ok(PreparedVerifyingKeyVar { - alpha_g1_beta_g2, - gamma_g2_neg_pc, - delta_g2_neg_pc, - gamma_abc_g1: self.gamma_abc_g1.clone(), - }) - } -} - -#[derive(Derivative)] -#[derivative( - Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ - P::G2PreparedVar: Clone, ") -)] -pub struct PreparedVerifyingKeyVar> { - pub alpha_g1_beta_g2: P::GTVar, - pub gamma_g2_neg_pc: P::G2PreparedVar, - pub delta_g2_neg_pc: P::G2PreparedVar, - pub gamma_abc_g1: Vec, -} - -pub struct Groth16VerifierGadget -where - E: PairingEngine, - - P: PairingVar, -{ - _pairing_engine: PhantomData, - _pairing_gadget: PhantomData

, -} - -impl NIZKVerifierGadget, E::Fq> for Groth16VerifierGadget -where - E: PairingEngine, - C: ConstraintSynthesizer, - V: ToConstraintField, - P: PairingVar, -{ - type PreparedVerificationKeyVar = PreparedVerifyingKeyVar; - type VerificationKeyVar = VerifyingKeyVar; - type ProofVar = ProofVar; - - /// Allocates `N::Proof` in `cs` without performing - /// subgroup checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_proof_unchecked>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - f().and_then(|proof| { - let proof = proof.borrow(); - let a = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.a"), - || Ok(proof.a.into_projective()), - mode, - )?; - let b = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.b"), - || Ok(proof.b.into_projective()), - mode, - )?; - let c = CurveVar::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Proof.c"), - || Ok(proof.c.into_projective()), - mode, - )?; - Ok(ProofVar { a, b, c }) - }) - } - - /// Allocates `N::Proof` in `cs` without performing - /// subgroup checks. - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_verification_key_unchecked>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - f().and_then(|vk| { - let vk = vk.borrow(); - let alpha_g1 = P::G1Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "alpha_g1"), - || Ok(vk.alpha_g1.into_projective()), - mode, - )?; - let beta_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "beta_g2"), - || Ok(vk.beta_g2.into_projective()), - mode, - )?; - let gamma_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "gamma_g2"), - || Ok(vk.gamma_g2.into_projective()), - mode, - )?; - let delta_g2 = P::G2Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "delta_g2"), - || Ok(vk.delta_g2.into_projective()), - mode, - )?; - - let gamma_abc_g1 = vk - .gamma_abc_g1 - .iter() - .map(|g| { - P::G1Var::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "g"), - || Ok(g.into_projective()), - mode, - ) - }) - .collect::, _>>()?; - Ok(VerifyingKeyVar { - alpha_g1, - beta_g2, - gamma_g2, - delta_g2, - gamma_abc_g1, - }) - }) - } - - #[tracing::instrument(target = "r1cs", skip(vk, input, proof))] - fn verify<'a, T: 'a + ToBitsGadget + ?Sized>( - vk: &Self::VerificationKeyVar, - input: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError> { - let pvk = vk.prepare()?; - , E::Fq>>::verify_prepared(&pvk, input, proof) - } - - #[tracing::instrument(target = "r1cs", skip(pvk, public_inputs, proof))] - fn verify_prepared<'a, T: 'a + ToBitsGadget + ?Sized>( - pvk: &Self::PreparedVerificationKeyVar, - public_inputs: impl IntoIterator, - proof: &Self::ProofVar, - ) -> Result, SynthesisError> { - let pvk = pvk.clone(); - - let g_ic = { - let mut g_ic: P::G1Var = pvk.gamma_abc_g1[0].clone(); - let mut input_len = 1; - let mut public_inputs = public_inputs.into_iter(); - for (input, b) in public_inputs.by_ref().zip(pvk.gamma_abc_g1.iter().skip(1)) { - let encoded_input_i: P::G1Var = b.scalar_mul_le(input.to_bits_le()?.iter())?; - g_ic += encoded_input_i; - input_len += 1; - } - // Check that the input and the query in the verification are of the - // same length. - assert!(input_len == pvk.gamma_abc_g1.len() && public_inputs.next().is_none()); - g_ic - }; - - let test_exp = { - let proof_a_prep = P::prepare_g1(&proof.a)?; - let proof_b_prep = P::prepare_g2(&proof.b)?; - let proof_c_prep = P::prepare_g1(&proof.c)?; - - let g_ic_prep = P::prepare_g1(&g_ic)?; - - P::miller_loop( - &[proof_a_prep, g_ic_prep, proof_c_prep], - &[ - proof_b_prep, - pvk.gamma_g2_neg_pc.clone(), - pvk.delta_g2_neg_pc.clone(), - ], - )? - }; - - let test = P::final_exponentiation(&test_exp)?; - test.is_eq(&pvk.alpha_g1_beta_g2) - } -} - -impl AllocVar, E::Fq> for PreparedVerifyingKeyVar -where - E: PairingEngine, - P: PairingVar, -{ - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|pvk| { - let pvk = pvk.borrow(); - let alpha_g1_beta_g2 = P::GTVar::new_variable( - r1cs_core::ns!(cs, "alpha_g1_beta_g2"), - || Ok(pvk.alpha_g1_beta_g2), - mode, - )?; - - let gamma_g2_neg_pc = P::G2PreparedVar::new_variable( - r1cs_core::ns!(cs, "gamma_g2_neg_pc"), - || Ok(pvk.gamma_g2_neg_pc.clone()), - mode, - )?; - - let delta_g2_neg_pc = P::G2PreparedVar::new_variable( - r1cs_core::ns!(cs, "delta_g2_neg_pc"), - || Ok(pvk.delta_g2_neg_pc.clone()), - mode, - )?; - - let gamma_abc_g1 = Vec::new_variable( - r1cs_core::ns!(cs, "gamma_abc_g1"), - || Ok(pvk.gamma_abc_g1.clone()), - mode, - )?; - - Ok(Self { - alpha_g1_beta_g2, - gamma_g2_neg_pc, - delta_g2_neg_pc, - gamma_abc_g1, - }) - }) - } -} - -impl AllocVar, E::Fq> for VerifyingKeyVar -where - E: PairingEngine, - - P: PairingVar, -{ - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|vk| { - let VerifyingKey { - alpha_g1, - beta_g2, - gamma_g2, - delta_g2, - gamma_abc_g1, - } = vk.borrow().clone(); - let alpha_g1 = - P::G1Var::new_variable(r1cs_core::ns!(cs, "alpha_g1"), || Ok(alpha_g1), mode)?; - let beta_g2 = - P::G2Var::new_variable(r1cs_core::ns!(cs, "beta_g2"), || Ok(beta_g2), mode)?; - let gamma_g2 = - P::G2Var::new_variable(r1cs_core::ns!(cs, "gamma_g2"), || Ok(gamma_g2), mode)?; - let delta_g2 = - P::G2Var::new_variable(r1cs_core::ns!(cs, "delta_g2"), || Ok(delta_g2), mode)?; - - let gamma_abc_g1 = Vec::new_variable(cs.clone(), || Ok(gamma_abc_g1), mode)?; - Ok(Self { - alpha_g1, - beta_g2, - gamma_g2, - delta_g2, - gamma_abc_g1, - }) - }) - } -} - -impl AllocVar, E::Fq> for ProofVar -where - E: PairingEngine, - P: PairingVar, -{ - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let ns = cs.into(); - let cs = ns.cs(); - - f().and_then(|proof| { - let Proof { a, b, c } = proof.borrow().clone(); - let a = P::G1Var::new_variable(r1cs_core::ns!(cs, "a"), || Ok(a), mode)?; - let b = P::G2Var::new_variable(r1cs_core::ns!(cs, "b"), || Ok(b), mode)?; - let c = P::G1Var::new_variable(r1cs_core::ns!(cs, "c"), || Ok(c), mode)?; - Ok(Self { a, b, c }) - }) - } -} - -impl ToBytesGadget for VerifyingKeyVar -where - E: PairingEngine, - P: PairingVar, -{ - #[inline] - #[tracing::instrument(target = "r1cs", skip(self))] - fn to_bytes(&self) -> Result>, SynthesisError> { - let mut bytes = Vec::new(); - bytes.extend_from_slice(&self.alpha_g1.to_bytes()?); - bytes.extend_from_slice(&self.beta_g2.to_bytes()?); - bytes.extend_from_slice(&self.gamma_g2.to_bytes()?); - bytes.extend_from_slice(&self.delta_g2.to_bytes()?); - for g in &self.gamma_abc_g1 { - bytes.extend_from_slice(&g.to_bytes()?); - } - Ok(bytes) - } -} - -#[cfg(test)] -mod test { - use groth16::*; - use r1cs_core::{ - lc, ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError, - }; - - use super::*; - use algebra::{ - bls12_377::{Bls12_377, Fq, Fr}, - test_rng, BitIteratorLE, Field, PrimeField, - }; - use r1cs_std::{bls12_377::PairingVar as Bls12_377PairingVar, boolean::Boolean, Assignment}; - use rand::Rng; - - type TestProofSystem = Groth16, Fr>; - type TestVerifierGadget = Groth16VerifierGadget; - type TestProofVar = ProofVar; - type TestVkVar = VerifyingKeyVar; - - struct Bench { - inputs: Vec>, - num_constraints: usize, - } - - impl ConstraintSynthesizer for Bench { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - assert!(self.inputs.len() >= 2); - assert!(self.num_constraints >= self.inputs.len()); - - let mut variables: Vec<_> = Vec::with_capacity(self.inputs.len()); - for input in self.inputs { - let input_var = cs.new_input_variable(|| input.get())?; - variables.push((input, input_var)); - } - - for i in 0..self.num_constraints { - let new_entry = { - let (input_1_val, input_1_var) = variables[i]; - let (input_2_val, input_2_var) = variables[i + 1]; - let result_val = input_1_val - .and_then(|input_1| input_2_val.map(|input_2| input_1 * &input_2)); - let result_var = cs.new_witness_variable(|| { - result_val.ok_or(SynthesisError::AssignmentMissing) - })?; - cs.enforce_constraint( - lc!() + input_1_var, - lc!() + input_2_var, - lc!() + result_var, - ) - .unwrap(); - (result_val, result_var) - }; - variables.push(new_entry); - } - Ok(()) - } - } - - #[test] - fn groth16_verifier_test() { - let num_inputs = 100; - let num_constraints = num_inputs; - let rng = &mut test_rng(); - let mut inputs: Vec> = Vec::with_capacity(num_inputs); - for _ in 0..num_inputs { - inputs.push(Some(rng.gen())); - } - let params = { - let c = Bench:: { - inputs: vec![None; num_inputs], - num_constraints, - }; - - generate_random_parameters(c, rng).unwrap() - }; - - { - let proof = { - // Create an instance of our circuit (with the - // witness) - let c = Bench { - inputs: inputs.clone(), - num_constraints, - }; - // Create a groth16 proof with our parameters. - create_random_proof(c, ¶ms, rng).unwrap() - }; - - // assert!(!verify_proof(&pvk, &proof, &[a]).unwrap()); - let cs = ConstraintSystem::::new_ref(); - - let inputs: Vec<_> = inputs.into_iter().map(|input| input.unwrap()).collect(); - let mut input_gadgets = Vec::new(); - - { - for input in inputs.into_iter() { - let input_bits = BitIteratorLE::new(input.into_repr()).collect::>(); - - let input_bits = - Vec::>::new_input(r1cs_core::ns!(cs, "Input"), || { - Ok(input_bits) - }) - .unwrap(); - input_gadgets.push(input_bits); - } - } - - let vk_gadget = - TestVkVar::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk)).unwrap(); - let proof_gadget = - TestProofVar::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - println!("Time to verify!\n\n\n\n"); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - ) - .unwrap() - .enforce_equal(&Boolean::TRUE) - .unwrap(); - if !cs.is_satisfied().unwrap() { - println!("========================================================="); - println!("Unsatisfied constraints:"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - println!("========================================================="); - } - - // cs.print_named_objects(); - assert!(cs.is_satisfied().unwrap()); - } - } -} - -#[cfg(test)] -mod test_recursive { - use groth16::*; - use r1cs_core::{ - lc, ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError, - }; - - use super::*; - use algebra::{ - fields::{FftParameters, FpParameters}, - mnt4_298::{Fq as MNT4Fq, FqParameters as MNT4FqParameters, Fr as MNT4Fr, MNT4_298}, - mnt6_298::{Fq as MNT6Fq, FqParameters as MNT6FqParameters, Fr as MNT6Fr, MNT6_298}, - test_rng, BigInteger, Field, PrimeField, - }; - use r1cs_std::{ - fields::fp::FpVar, mnt4_298::PairingVar as MNT4_298PairingVar, - mnt6_298::PairingVar as MNT6_298PairingVar, uint8::UInt8, Assignment, - }; - use rand::Rng; - - type TestProofSystem1 = Groth16, MNT6Fr>; - type TestVerifierGadget1 = Groth16VerifierGadget; - type TestProofVar1 = ProofVar; - type TestVkVar1 = VerifyingKeyVar; - - type TestProofSystem2 = Groth16; - type TestVerifierGadget2 = Groth16VerifierGadget; - type TestProofVar2 = ProofVar; - type TestVkVar2 = VerifyingKeyVar; - - #[derive(Clone)] - struct Bench { - inputs: Vec>, - num_constraints: usize, - } - - impl ConstraintSynthesizer for Bench { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - assert!(self.inputs.len() >= 2); - assert!(self.num_constraints >= self.inputs.len()); - - let mut variables: Vec<_> = Vec::with_capacity(self.inputs.len()); - for input in self.inputs { - let input_var = cs.new_input_variable(|| input.get())?; - variables.push((input, input_var)); - } - - for i in 0..self.num_constraints { - let new_entry = { - let (input_1_val, input_1_var) = variables[i]; - let (input_2_val, input_2_var) = variables[i + 1]; - let result_val = input_1_val - .and_then(|input_1| input_2_val.map(|input_2| input_1 * &input_2)); - let result_var = cs.new_witness_variable(|| { - result_val.ok_or(SynthesisError::AssignmentMissing) - })?; - cs.enforce_constraint( - lc!() + input_1_var, - lc!() + input_2_var, - lc!() + result_var, - ) - .unwrap(); - (result_val, result_var) - }; - variables.push(new_entry); - } - Ok(()) - } - } - - struct Wrapper { - inputs: Vec>, - params: Parameters, - proof: Proof, - } - - impl ConstraintSynthesizer for Wrapper { - fn generate_constraints( - self, - cs: ConstraintSystemRef, - ) -> Result<(), SynthesisError> { - let params = self.params; - let proof = self.proof; - let inputs: Vec<_> = self - .inputs - .into_iter() - .map(|input| input.unwrap()) - .collect(); - let input_gadgets; - - { - // Chain all input values in one large byte array. - let input_bytes = inputs - .clone() - .into_iter() - .flat_map(|input| { - input - .into_repr() - .as_ref() - .iter() - .flat_map(|l| l.to_le_bytes().to_vec()) - .collect::>() - }) - .collect::>(); - - // Allocate this byte array as input packed into field elements. - let input_bytes = - UInt8::new_input_vec(r1cs_core::ns!(cs, "Input"), &input_bytes[..])?; - // 40 byte - let element_size = ::BigInt::NUM_LIMBS * 8; - input_gadgets = input_bytes - .chunks(element_size) - .map(|chunk| { - chunk - .iter() - .flat_map(|byte| byte.to_bits_le().unwrap()) - .collect::>() - }) - .collect::>(); - } - - let vk_gadget = TestVkVar1::new_witness(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk))?; - let proof_gadget = - TestProofVar1::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - )? - .enforce_equal(&Boolean::TRUE)?; - Ok(()) - } - } - - #[test] - fn groth16_recursive_verifier_test() { - let num_inputs = 5; - let num_constraints = num_inputs; - let rng = &mut test_rng(); - let mut inputs: Vec> = Vec::with_capacity(num_inputs); - for _ in 0..num_inputs { - inputs.push(Some(rng.gen())); - } - - // Generate inner params and proof. - let inner_params = { - let c = Bench:: { - inputs: vec![None; num_inputs], - num_constraints, - }; - - generate_random_parameters(c, rng).unwrap() - }; - - let inner_proof = { - // Create an instance of our circuit (with the - // witness) - let c = Bench { - inputs: inputs.clone(), - num_constraints, - }; - // Create a groth16 proof with our parameters. - create_random_proof(c, &inner_params, rng).unwrap() - }; - - // Generate outer params and proof. - let params = { - let c = Wrapper { - inputs: inputs.clone(), - params: inner_params.clone(), - proof: inner_proof.clone(), - }; - - generate_random_parameters(c, rng).unwrap() - }; - - { - let proof = { - // Create an instance of our circuit (with the - // witness) - let c = Wrapper { - inputs: inputs.clone(), - params: inner_params.clone(), - proof: inner_proof.clone(), - }; - // Create a groth16 proof with our parameters. - create_random_proof(c, ¶ms, rng).unwrap() - }; - - let cs = ConstraintSystem::::new_ref(); - - let inputs: Vec<_> = inputs.into_iter().map(|input| input.unwrap()).collect(); - let mut input_gadgets = Vec::new(); - - { - let bigint_size = ::BigInt::NUM_LIMBS * 64; - let mut input_bits = Vec::new(); - for input in inputs.into_iter() { - let input_gadget = - FpVar::new_input(r1cs_core::ns!(cs, "Input"), || Ok(input)).unwrap(); - let mut fp_bits = input_gadget.to_bits_le().unwrap(); - - // Use 320 bits per element. - for _ in fp_bits.len()..bigint_size { - fp_bits.push(Boolean::constant(false)); - } - input_bits.extend_from_slice(&fp_bits); - } - - // Pack input bits into field elements of the underlying circuit. - let max_size = 8 * (::CAPACITY / 8) as usize; - let max_size = max_size as usize; - let bigint_size = ::BigInt::NUM_LIMBS * 64; - for chunk in input_bits.chunks(max_size) { - let mut chunk = chunk.to_vec(); - let len = chunk.len(); - for _ in len..bigint_size { - chunk.push(Boolean::constant(false)); - } - input_gadgets.push(chunk); - } - // assert!(!verify_proof(&pvk, &proof, &[a]).unwrap()); - } - - let vk_gadget = - TestVkVar2::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(¶ms.vk)).unwrap(); - let proof_gadget = - TestProofVar2::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone())) - .unwrap(); - println!("Time to verify!\n\n\n\n"); - >::verify( - &vk_gadget, - &input_gadgets, - &proof_gadget, - ) - .unwrap() - .enforce_equal(&Boolean::TRUE) - .unwrap(); - if !cs.is_satisfied().unwrap() { - println!("========================================================="); - println!("Unsatisfied constraints:"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - println!("========================================================="); - } - - assert!(cs.is_satisfied().unwrap()); - } - } -} diff --git a/crypto-primitives/src/nizk/groth16/mod.rs b/crypto-primitives/src/nizk/groth16/mod.rs deleted file mode 100644 index c4d6f05..0000000 --- a/crypto-primitives/src/nizk/groth16/mod.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::Error; -use algebra_core::PairingEngine; -use groth16::{ - create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, - Parameters, PreparedVerifyingKey, Proof, VerifyingKey, -}; -use r1cs_core::ConstraintSynthesizer; -use rand::Rng; - -use algebra_core::ToConstraintField; -use core::marker::PhantomData; - -use super::NIZK; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -/// Note: V should serialize its contents to `Vec` in the same order as -/// during the constraint generation. -pub struct Groth16< - E: PairingEngine, - C: ConstraintSynthesizer, - V: ToConstraintField + ?Sized, -> { - #[doc(hidden)] - _engine: PhantomData, - #[doc(hidden)] - _circuit: PhantomData, - #[doc(hidden)] - _verifier_input: PhantomData, -} - -impl, V: ToConstraintField + ?Sized> NIZK - for Groth16 -{ - type Circuit = C; - type AssignedCircuit = C; - type VerifierInput = V; - type ProvingParameters = Parameters; - type VerificationParameters = VerifyingKey; - type PreparedVerificationParameters = PreparedVerifyingKey; - type Proof = Proof; - - fn setup( - circuit: Self::Circuit, - rng: &mut R, - ) -> Result< - ( - Self::ProvingParameters, - Self::PreparedVerificationParameters, - ), - Error, - > { - let nizk_time = start_timer!(|| "{Groth 2016}::Setup"); - let pp = generate_random_parameters::(circuit, rng)?; - let vk = prepare_verifying_key(&pp.vk); - end_timer!(nizk_time); - Ok((pp, vk)) - } - - fn prove( - pp: &Self::ProvingParameters, - input_and_witness: Self::AssignedCircuit, - rng: &mut R, - ) -> Result { - let proof_time = start_timer!(|| "{Groth 2016}::Prove"); - let result = create_random_proof::(input_and_witness, pp, rng)?; - end_timer!(proof_time); - Ok(result) - } - - fn verify( - vk: &Self::PreparedVerificationParameters, - input: &Self::VerifierInput, - proof: &Self::Proof, - ) -> Result { - let verify_time = start_timer!(|| "{Groth 2016}::Verify"); - let conversion_time = start_timer!(|| "Convert input to E::Fr"); - let input = input.to_field_elements()?; - end_timer!(conversion_time); - let verification = start_timer!(|| format!("Verify proof w/ input len: {}", input.len())); - let result = verify_proof(&vk, proof, &input)?; - end_timer!(verification); - end_timer!(verify_time); - Ok(result) - } -} diff --git a/crypto-primitives/src/nizk/mod.rs b/crypto-primitives/src/nizk/mod.rs deleted file mode 100644 index a409fc4..0000000 --- a/crypto-primitives/src/nizk/mod.rs +++ /dev/null @@ -1,115 +0,0 @@ -use algebra_core::bytes::ToBytes; -use rand::Rng; - -#[cfg(feature = "gm17")] -pub mod gm17; -#[cfg(feature = "gm17")] -pub use self::gm17::Gm17; - -#[cfg(feature = "groth16")] -pub mod groth16; -#[cfg(feature = "groth16")] -pub use self::groth16::Groth16; - -#[cfg(feature = "r1cs")] -pub mod constraints; -#[cfg(feature = "r1cs")] -pub use constraints::*; - -use crate::Error; - -pub trait NIZK { - type Circuit; - type AssignedCircuit; - type VerifierInput: ?Sized; - type ProvingParameters: Clone; - type VerificationParameters: Clone + Default + From; - type PreparedVerificationParameters: Clone + Default + From; - type Proof: ToBytes + Clone + Default; - - fn setup( - circuit: Self::Circuit, - rng: &mut R, - ) -> Result< - ( - Self::ProvingParameters, - Self::PreparedVerificationParameters, - ), - Error, - >; - - fn prove( - parameter: &Self::ProvingParameters, - input_and_witness: Self::AssignedCircuit, - rng: &mut R, - ) -> Result; - - fn verify( - verifier_key: &Self::PreparedVerificationParameters, - input: &Self::VerifierInput, - proof: &Self::Proof, - ) -> Result; -} - -#[cfg(all(feature = "gm17", test))] -mod test { - use algebra::test_rng; - use core::ops::AddAssign; - - #[test] - fn test_gm17() { - use crate::nizk::{gm17::Gm17, NIZK}; - use algebra::{ - bls12_377::{Bls12_377, Fr}, - One, - }; - use r1cs_core::{lc, ConstraintSynthesizer, ConstraintSystemRef, SynthesisError, Variable}; - - #[derive(Copy, Clone)] - struct R1CSCircuit { - x: Option, - sum: Option, - w: Option, - } - - impl R1CSCircuit { - pub(super) fn new(x: Fr, sum: Fr, w: Fr) -> Self { - Self { - x: Some(x), - sum: Some(sum), - w: Some(w), - } - } - } - - impl ConstraintSynthesizer for R1CSCircuit { - fn generate_constraints( - self, - cs: ConstraintSystemRef, - ) -> Result<(), SynthesisError> { - let input = cs.new_input_variable(|| Ok(self.x.unwrap()))?; - let sum = cs.new_input_variable(|| Ok(self.sum.unwrap()))?; - let witness = cs.new_witness_variable(|| Ok(self.w.unwrap()))?; - - cs.enforce_constraint(lc!() + sum, lc!() + Variable::One, lc!() + input + witness)?; - Ok(()) - } - } - - let mut sum = Fr::one(); - sum.add_assign(&Fr::one()); - let circuit = R1CSCircuit::new(Fr::one(), sum, Fr::one()); - - let rng = &mut test_rng(); - - let parameters = Gm17::::setup(circuit, rng).unwrap(); - - let proof = - Gm17::::prove(¶meters.0, circuit, rng).unwrap(); - - let result = - Gm17::::verify(¶meters.1, &[Fr::one(), sum], &proof) - .unwrap(); - assert!(result); - } -} diff --git a/crypto-primitives/src/prf/blake2s/constraints.rs b/crypto-primitives/src/prf/blake2s/constraints.rs deleted file mode 100644 index ce07bd2..0000000 --- a/crypto-primitives/src/prf/blake2s/constraints.rs +++ /dev/null @@ -1,537 +0,0 @@ -use algebra_core::PrimeField; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; - -use crate::{prf::PRFGadget, Vec}; -use r1cs_std::prelude::*; - -use core::borrow::Borrow; - -// 2.1. Parameters -// The following table summarizes various parameters and their ranges: -// | BLAKE2b | BLAKE2s | -// --------------+------------------+------------------+ -// Bits in word | w = 64 | w = 32 | -// Rounds in F | r = 12 | r = 10 | -// Block bytes | bb = 128 | bb = 64 | -// Hash bytes | 1 <= nn <= 64 | 1 <= nn <= 32 | -// Key bytes | 0 <= kk <= 64 | 0 <= kk <= 32 | -// Input bytes | 0 <= ll < 2**128 | 0 <= ll < 2**64 | -// --------------+------------------+------------------+ -// G Rotation | (R1, R2, R3, R4) | (R1, R2, R3, R4) | -// constants = | (32, 24, 16, 63) | (16, 12, 8, 7) | -// --------------+------------------+------------------+ -// - -const R1: usize = 16; -const R2: usize = 12; -const R3: usize = 8; -const R4: usize = 7; - -// Round | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -// ----------+-------------------------------------------------+ -// SIGMA[0] | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -// SIGMA[1] | 14 10 4 8 9 15 13 6 1 12 0 2 11 7 5 3 | -// SIGMA[2] | 11 8 12 0 5 2 15 13 10 14 3 6 7 1 9 4 | -// SIGMA[3] | 7 9 3 1 13 12 11 14 2 6 5 10 4 0 15 8 | -// SIGMA[4] | 9 0 5 7 2 4 10 15 14 1 11 12 6 8 3 13 | -// SIGMA[5] | 2 12 6 10 0 11 8 3 4 13 7 5 15 14 1 9 | -// SIGMA[6] | 12 5 1 15 14 13 4 10 0 7 6 3 9 2 8 11 | -// SIGMA[7] | 13 11 7 14 12 1 3 9 5 0 15 4 8 6 2 10 | -// SIGMA[8] | 6 15 14 9 11 3 0 8 12 2 13 7 1 4 10 5 | -// SIGMA[9] | 10 2 8 4 7 6 1 5 15 11 9 14 3 12 13 0 | -// ----------+-------------------------------------------------+ -// - -const SIGMA: [[usize; 16]; 10] = [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], -]; - -// 3.1. Mixing Function G -// The G primitive function mixes two input words, "x" and "y", into -// four words indexed by "a", "b", "c", and "d" in the working vector -// v[0..15]. The full modified vector is returned. The rotation -// constants (R1, R2, R3, R4) are given in Section 2.1. -// FUNCTION G( v[0..15], a, b, c, d, x, y ) -// | -// | v[a] := (v[a] + v[b] + x) mod 2**w -// | v[d] := (v[d] ^ v[a]) >>> R1 -// | v[c] := (v[c] + v[d]) mod 2**w -// | v[b] := (v[b] ^ v[c]) >>> R2 -// | v[a] := (v[a] + v[b] + y) mod 2**w -// | v[d] := (v[d] ^ v[a]) >>> R3 -// | v[c] := (v[c] + v[d]) mod 2**w -// | v[b] := (v[b] ^ v[c]) >>> R4 -// | -// | RETURN v[0..15] -// | -// END FUNCTION. -// - -fn mixing_g( - v: &mut [UInt32], - a: usize, - b: usize, - c: usize, - d: usize, - x: &UInt32, - y: &UInt32, -) -> Result<(), SynthesisError> { - v[a] = UInt32::addmany(&[v[a].clone(), v[b].clone(), x.clone()])?; - v[d] = v[d].xor(&v[a])?.rotr(R1); - v[c] = UInt32::addmany(&[v[c].clone(), v[d].clone()])?; - v[b] = v[b].xor(&v[c])?.rotr(R2); - v[a] = UInt32::addmany(&[v[a].clone(), v[b].clone(), y.clone()])?; - v[d] = v[d].xor(&v[a])?.rotr(R3); - v[c] = UInt32::addmany(&[v[c].clone(), v[d].clone()])?; - v[b] = v[b].xor(&v[c])?.rotr(R4); - - Ok(()) -} - -// 3.2. Compression Function F -// Compression function F takes as an argument the state vector "h", -// message block vector "m" (last block is padded with zeros to full -// block size, if required), 2w-bit offset counter "t", and final block -// indicator flag "f". Local vector v[0..15] is used in processing. F -// returns a new state vector. The number of rounds, "r", is 12 for -// BLAKE2b and 10 for BLAKE2s. Rounds are numbered from 0 to r - 1. -// FUNCTION F( h[0..7], m[0..15], t, f ) -// | -// | // Initialize local work vector v[0..15] -// | v[0..7] := h[0..7] // First half from state. -// | v[8..15] := IV[0..7] // Second half from IV. -// | -// | v[12] := v[12] ^ (t mod 2**w) // Low word of the offset. -// | v[13] := v[13] ^ (t >> w) // High word. -// | -// | IF f = TRUE THEN // last block flag? -// | | v[14] := v[14] ^ 0xFF..FF // Invert all bits. -// | END IF. -// | -// | // Cryptographic mixing -// | FOR i = 0 TO r - 1 DO // Ten or twelve rounds. -// | | -// | | // Message word selection permutation for this round. -// | | s[0..15] := SIGMA[i mod 10][0..15] -// | | -// | | v := G( v, 0, 4, 8, 12, m[s[ 0]], m[s[ 1]] ) -// | | v := G( v, 1, 5, 9, 13, m[s[ 2]], m[s[ 3]] ) -// | | v := G( v, 2, 6, 10, 14, m[s[ 4]], m[s[ 5]] ) -// | | v := G( v, 3, 7, 11, 15, m[s[ 6]], m[s[ 7]] ) -// | | -// | | v := G( v, 0, 5, 10, 15, m[s[ 8]], m[s[ 9]] ) -// | | v := G( v, 1, 6, 11, 12, m[s[10]], m[s[11]] ) -// | | v := G( v, 2, 7, 8, 13, m[s[12]], m[s[13]] ) -// | | v := G( v, 3, 4, 9, 14, m[s[14]], m[s[15]] ) -// | | -// | END FOR -// | -// | FOR i = 0 TO 7 DO // XOR the two halves. -// | | h[i] := h[i] ^ v[i] ^ v[i + 8] -// | END FOR. -// | -// | RETURN h[0..7] // New state. -// | -// END FUNCTION. -// - -fn blake2s_compression( - h: &mut [UInt32], - m: &[UInt32], - t: u64, - f: bool, -) -> Result<(), SynthesisError> { - assert_eq!(h.len(), 8); - assert_eq!(m.len(), 16); - - // static const uint32_t blake2s_iv[8] = - // { - // 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - // 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 - // }; - // - - let mut v = Vec::with_capacity(16); - v.extend_from_slice(h); - v.push(UInt32::constant(0x6A09E667)); - v.push(UInt32::constant(0xBB67AE85)); - v.push(UInt32::constant(0x3C6EF372)); - v.push(UInt32::constant(0xA54FF53A)); - v.push(UInt32::constant(0x510E527F)); - v.push(UInt32::constant(0x9B05688C)); - v.push(UInt32::constant(0x1F83D9AB)); - v.push(UInt32::constant(0x5BE0CD19)); - - assert_eq!(v.len(), 16); - - v[12] = v[12].xor(&UInt32::constant(t as u32))?; - v[13] = v[13].xor(&UInt32::constant((t >> 32) as u32))?; - - if f { - v[14] = v[14].xor(&UInt32::constant(u32::max_value()))?; - } - - for i in 0..10 { - let s = SIGMA[i % 10]; - - mixing_g(&mut v, 0, 4, 8, 12, &m[s[0]], &m[s[1]])?; - mixing_g(&mut v, 1, 5, 9, 13, &m[s[2]], &m[s[3]])?; - mixing_g(&mut v, 2, 6, 10, 14, &m[s[4]], &m[s[5]])?; - mixing_g(&mut v, 3, 7, 11, 15, &m[s[6]], &m[s[7]])?; - mixing_g(&mut v, 0, 5, 10, 15, &m[s[8]], &m[s[9]])?; - mixing_g(&mut v, 1, 6, 11, 12, &m[s[10]], &m[s[11]])?; - mixing_g(&mut v, 2, 7, 8, 13, &m[s[12]], &m[s[13]])?; - mixing_g(&mut v, 3, 4, 9, 14, &m[s[14]], &m[s[15]])?; - } - - for i in 0..8 { - h[i] = h[i].xor(&v[i])?; - h[i] = h[i].xor(&v[i + 8])?; - } - - Ok(()) -} - -// FUNCTION BLAKE2( d[0..dd-1], ll, kk, nn ) -// | -// | h[0..7] := IV[0..7] // Initialization Vector. -// | -// | // Parameter block p[0] -// | h[0] := h[0] ^ 0x01010000 ^ (kk << 8) ^ nn -// | -// | // Process padded key and data blocks -// | IF dd > 1 THEN -// | | FOR i = 0 TO dd - 2 DO -// | | | h := F( h, d[i], (i + 1) * bb, FALSE ) -// | | END FOR. -// | END IF. -// | -// | // Final block. -// | IF kk = 0 THEN -// | | h := F( h, d[dd - 1], ll, TRUE ) -// | ELSE -// | | h := F( h, d[dd - 1], ll + bb, TRUE ) -// | END IF. -// | -// | RETURN first "nn" bytes from little-endian word array h[]. -// | -// END FUNCTION. -// - -pub fn evaluate_blake2s( - input: &[Boolean], -) -> Result>, SynthesisError> { - assert!(input.len() % 8 == 0); - let mut parameters = [0; 8]; - parameters[0] = 0x01010000 ^ 32; - evaluate_blake2s_with_parameters(input, ¶meters) -} - -pub fn evaluate_blake2s_with_parameters( - input: &[Boolean], - parameters: &[u32; 8], -) -> Result>, SynthesisError> { - assert!(input.len() % 8 == 0); - - let mut h = Vec::with_capacity(8); - h.push(UInt32::constant(0x6A09E667).xor(&UInt32::constant(parameters[0]))?); - h.push(UInt32::constant(0xBB67AE85).xor(&UInt32::constant(parameters[1]))?); - h.push(UInt32::constant(0x3C6EF372).xor(&UInt32::constant(parameters[2]))?); - h.push(UInt32::constant(0xA54FF53A).xor(&UInt32::constant(parameters[3]))?); - h.push(UInt32::constant(0x510E527F).xor(&UInt32::constant(parameters[4]))?); - h.push(UInt32::constant(0x9B05688C).xor(&UInt32::constant(parameters[5]))?); - h.push(UInt32::constant(0x1F83D9AB).xor(&UInt32::constant(parameters[6]))?); - h.push(UInt32::constant(0x5BE0CD19).xor(&UInt32::constant(parameters[7]))?); - - let mut blocks: Vec>> = vec![]; - - for block in input.chunks(512) { - let mut this_block = Vec::with_capacity(16); - for word in block.chunks(32) { - let mut tmp = word.to_vec(); - while tmp.len() < 32 { - tmp.push(Boolean::constant(false)); - } - this_block.push(UInt32::from_bits_le(&tmp)); - } - while this_block.len() < 16 { - this_block.push(UInt32::constant(0)); - } - blocks.push(this_block); - } - - if blocks.is_empty() { - blocks.push((0..16).map(|_| UInt32::constant(0)).collect()); - } - - for (i, block) in blocks[0..blocks.len() - 1].iter().enumerate() { - blake2s_compression(&mut h, block, ((i as u64) + 1) * 64, false)?; - } - - blake2s_compression( - &mut h, - &blocks[blocks.len() - 1], - (input.len() / 8) as u64, - true, - )?; - - Ok(h) -} - -use crate::prf::Blake2s; - -pub struct Blake2sGadget; -#[derive(Clone, Debug)] -pub struct OutputVar(pub Vec>); - -impl EqGadget for OutputVar { - #[tracing::instrument(target = "r1cs")] - fn is_eq(&self, other: &Self) -> Result, SynthesisError> { - self.0.is_eq(&other.0) - } - - /// If `should_enforce == true`, enforce that `self` and `other` are equal; else, - /// enforce a vacuously true statement. - #[tracing::instrument(target = "r1cs")] - fn conditional_enforce_equal( - &self, - other: &Self, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError> { - self.0.conditional_enforce_equal(&other.0, should_enforce) - } - - /// If `should_enforce == true`, enforce that `self` and `other` are not equal; else, - /// enforce a vacuously true statement. - #[tracing::instrument(target = "r1cs")] - fn conditional_enforce_not_equal( - &self, - other: &Self, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError> { - self.0 - .as_slice() - .conditional_enforce_not_equal(other.0.as_slice(), should_enforce) - } -} - -impl ToBytesGadget for OutputVar { - #[inline] - fn to_bytes(&self) -> Result>, SynthesisError> { - Ok(self.0.clone()) - } -} - -impl AllocVar<[u8; 32], ConstraintF> for OutputVar { - #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_variable>( - cs: impl Into>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let bytes = f().map(|b| *b.borrow()).unwrap_or([0u8; 32]); - match mode { - AllocationMode::Constant => Ok(Self(UInt8::constant_vec(&bytes))), - AllocationMode::Input => UInt8::new_input_vec(cs, &bytes).map(Self), - AllocationMode::Witness => UInt8::new_witness_vec(cs, &bytes).map(Self), - } - } -} - -impl R1CSVar for OutputVar { - type Value = [u8; 32]; - - fn cs(&self) -> ConstraintSystemRef { - self.0.cs() - } - - fn value(&self) -> Result { - let mut value = [0u8; 32]; - for (val_i, self_i) in value.iter_mut().zip(&self.0) { - *val_i = self_i.value()?; - } - Ok(value) - } -} - -impl PRFGadget for Blake2sGadget { - type OutputVar = OutputVar; - - #[tracing::instrument(target = "r1cs", skip(cs))] - fn new_seed(cs: impl Into>, seed: &[u8; 32]) -> Vec> { - let ns = cs.into(); - let cs = ns.cs(); - UInt8::new_witness_vec(r1cs_core::ns!(cs, "New Blake2s seed"), seed).unwrap() - } - - #[tracing::instrument(target = "r1cs", skip(seed, input))] - fn evaluate(seed: &[UInt8], input: &[UInt8]) -> Result { - assert_eq!(seed.len(), 32); - let input: Vec<_> = seed - .iter() - .chain(input) - .flat_map(|b| b.to_bits_le().unwrap()) - .collect(); - let result: Vec<_> = evaluate_blake2s(&input)? - .into_iter() - .flat_map(|int| int.to_bytes().unwrap()) - .collect(); - Ok(OutputVar(result)) - } -} - -#[cfg(test)] -mod test { - use algebra::ed_on_bls12_381::Fq as Fr; - use rand::{Rng, SeedableRng}; - use rand_xorshift::XorShiftRng; - - use crate::prf::blake2s::{constraints::evaluate_blake2s, Blake2s as B2SPRF}; - use blake2::VarBlake2s; - use r1cs_core::ConstraintSystem; - - use super::Blake2sGadget; - use r1cs_std::prelude::*; - - #[test] - fn test_blake2s_constraints() { - let cs = ConstraintSystem::::new_ref(); - let input_bits: Vec<_> = (0..512) - .map(|_| Boolean::new_witness(r1cs_core::ns!(cs, "input bit"), || Ok(true)).unwrap()) - .collect(); - evaluate_blake2s(&input_bits).unwrap(); - assert!(cs.is_satisfied().unwrap()); - assert_eq!(cs.num_constraints(), 21792); - } - - #[test] - fn test_blake2s_prf() { - use crate::prf::{PRFGadget, PRF}; - use rand::Rng; - - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let cs = ConstraintSystem::::new_ref(); - - let mut seed = [0u8; 32]; - rng.fill(&mut seed); - - let mut input = [0u8; 32]; - rng.fill(&mut input); - - let seed_var = Blake2sGadget::new_seed(cs.clone(), &seed); - let input_var = - UInt8::new_witness_vec(r1cs_core::ns!(cs, "declare_input"), &input).unwrap(); - let out = B2SPRF::evaluate(&seed, &input).unwrap(); - let actual_out_var = >::OutputVar::new_witness( - r1cs_core::ns!(cs, "declare_output"), - || Ok(out), - ) - .unwrap(); - - let output_var = Blake2sGadget::evaluate(&seed_var, &input_var).unwrap(); - output_var.enforce_equal(&actual_out_var).unwrap(); - - if !cs.is_satisfied().unwrap() { - println!( - "which is unsatisfied: {:?}", - cs.which_is_unsatisfied().unwrap() - ); - } - assert!(cs.is_satisfied().unwrap()); - } - - #[test] - fn test_blake2s_precomp_constraints() { - // Test that 512 fixed leading bits (constants) - // doesn't result in more constraints. - - let cs = ConstraintSystem::::new_ref(); - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let input_bits: Vec<_> = (0..512) - .map(|_| Boolean::constant(rng.gen())) - .chain((0..512).map(|_| { - Boolean::new_witness(r1cs_core::ns!(cs, "input bit"), || Ok(true)).unwrap() - })) - .collect(); - evaluate_blake2s(&input_bits).unwrap(); - assert!(cs.is_satisfied().unwrap()); - assert_eq!(cs.num_constraints(), 21792); - } - - #[test] - fn test_blake2s_constant_constraints() { - let cs = ConstraintSystem::::new_ref(); - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let input_bits: Vec<_> = (0..512) - .map(|_| Boolean::::constant(rng.gen())) - .collect(); - evaluate_blake2s(&input_bits).unwrap(); - assert_eq!(cs.num_constraints(), 0); - } - - #[test] - fn test_blake2s() { - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { - use digest::*; - let mut h = VarBlake2s::new_keyed(&[], 32); - - let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); - - h.input(&data); - - let mut hash_result = Vec::with_capacity(h.output_size()); - h.variable_result(|res| hash_result.extend_from_slice(res)); - - let cs = ConstraintSystem::::new_ref(); - - let mut input_bits = vec![]; - - for input_byte in data.into_iter() { - for bit_i in 0..8 { - let cs = r1cs_core::ns!(cs, "input bit"); - - input_bits.push( - Boolean::new_witness(cs, || Ok((input_byte >> bit_i) & 1u8 == 1u8)) - .unwrap(), - ); - } - } - - let r = evaluate_blake2s(&input_bits).unwrap(); - - assert!(cs.is_satisfied().unwrap()); - - let mut s = hash_result - .iter() - .flat_map(|&byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8)); - - for chunk in r { - for b in chunk.to_bits_le() { - match b { - Boolean::Is(b) => { - assert!(s.next().unwrap() == b.value().unwrap()); - } - Boolean::Not(b) => { - assert!(s.next().unwrap() != b.value().unwrap()); - } - Boolean::Constant(b) => { - assert!(input_len == 0); - assert!(s.next().unwrap() == b); - } - } - } - } - } - } -} diff --git a/crypto-primitives/src/prf/blake2s/mod.rs b/crypto-primitives/src/prf/blake2s/mod.rs deleted file mode 100644 index c1ce030..0000000 --- a/crypto-primitives/src/prf/blake2s/mod.rs +++ /dev/null @@ -1,92 +0,0 @@ -use alloc::vec::Vec; -use blake2::{Blake2s as B2s, VarBlake2s}; -use digest::Digest; - -use super::PRF; -use crate::CryptoError; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -#[derive(Clone)] -pub struct Blake2s; - -impl PRF for Blake2s { - type Input = [u8; 32]; - type Output = [u8; 32]; - type Seed = [u8; 32]; - - fn evaluate(seed: &Self::Seed, input: &Self::Input) -> Result { - let eval_time = start_timer!(|| "Blake2s::Eval"); - let mut h = B2s::new(); - h.input(seed.as_ref()); - h.input(input.as_ref()); - let mut result = [0u8; 32]; - result.copy_from_slice(&h.result()); - end_timer!(eval_time); - Ok(result) - } -} - -#[derive(Clone)] -pub struct Blake2sWithParameterBlock { - pub digest_length: u8, - pub key_length: u8, - pub fan_out: u8, - pub depth: u8, - pub leaf_length: u32, - pub node_offset: u32, - pub xof_digest_length: u16, - pub node_depth: u8, - pub inner_length: u8, - pub salt: [u8; 8], - pub personalization: [u8; 8], -} - -impl Blake2sWithParameterBlock { - pub fn parameters(&self) -> [u32; 8] { - let mut parameters = [0; 8]; - parameters[0] = u32::from_le_bytes([ - self.digest_length, - self.key_length, - self.fan_out, - self.depth, - ]); - parameters[1] = self.leaf_length; - parameters[2] = self.node_offset; - parameters[3] = u32::from_le_bytes([ - self.xof_digest_length as u8, - (self.xof_digest_length >> 8) as u8, - self.node_depth, - self.inner_length, - ]); - - let mut salt_bytes_1 = [0; 4]; - let mut salt_bytes_2 = [0; 4]; - let mut personalization_bytes_1 = [0; 4]; - let mut personalization_bytes_2 = [0; 4]; - for i in 0..4 { - salt_bytes_1[i] = self.salt[i]; - salt_bytes_2[i] = self.salt[4 + i]; - personalization_bytes_1[i] = self.personalization[i]; - personalization_bytes_2[i] = self.personalization[4 + i]; - } - parameters[4] = u32::from_le_bytes(salt_bytes_1); - parameters[5] = u32::from_le_bytes(salt_bytes_2); - parameters[6] = u32::from_le_bytes(personalization_bytes_1); - parameters[7] = u32::from_le_bytes(personalization_bytes_2); - - parameters - } - - pub fn evaluate(&self, input: &[u8]) -> Vec { - use digest::*; - let eval_time = start_timer!(|| "Blake2sWithParameterBlock::Eval"); - let mut h = VarBlake2s::with_parameter_block(&self.parameters()); - h.input(input.as_ref()); - end_timer!(eval_time); - let mut buf = Vec::with_capacity(h.output_size()); - h.variable_result(|res| buf.extend_from_slice(res)); - buf - } -} diff --git a/crypto-primitives/src/prf/constraints.rs b/crypto-primitives/src/prf/constraints.rs deleted file mode 100644 index 84a3cbb..0000000 --- a/crypto-primitives/src/prf/constraints.rs +++ /dev/null @@ -1,20 +0,0 @@ -use algebra_core::Field; -use core::fmt::Debug; - -use crate::{prf::PRF, Vec}; -use r1cs_core::{Namespace, SynthesisError}; - -use r1cs_std::prelude::*; - -pub trait PRFGadget { - type OutputVar: EqGadget - + ToBytesGadget - + AllocVar - + R1CSVar - + Clone - + Debug; - - fn new_seed(cs: impl Into>, seed: &P::Seed) -> Vec>; - - fn evaluate(seed: &[UInt8], input: &[UInt8]) -> Result; -} diff --git a/crypto-primitives/src/prf/mod.rs b/crypto-primitives/src/prf/mod.rs deleted file mode 100644 index 9fd0338..0000000 --- a/crypto-primitives/src/prf/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -use algebra_core::bytes::{FromBytes, ToBytes}; -use core::{fmt::Debug, hash::Hash}; - -use crate::CryptoError; - -#[cfg(feature = "r1cs")] -pub mod constraints; -#[cfg(feature = "r1cs")] -pub use constraints::*; - -pub mod blake2s; -pub use self::blake2s::*; - -pub trait PRF { - type Input: FromBytes + Default; - type Output: ToBytes + Eq + Clone + Debug + Default + Hash; - type Seed: FromBytes + ToBytes + Clone + Default + Debug; - - fn evaluate(seed: &Self::Seed, input: &Self::Input) -> Result; -} diff --git a/crypto-primitives/src/signature/constraints.rs b/crypto-primitives/src/signature/constraints.rs deleted file mode 100644 index ab9eee0..0000000 --- a/crypto-primitives/src/signature/constraints.rs +++ /dev/null @@ -1,20 +0,0 @@ -use algebra_core::Field; -use r1cs_core::SynthesisError; -use r1cs_std::prelude::*; - -use crate::signature::SignatureScheme; - -pub trait SigRandomizePkGadget { - type ParametersVar: AllocVar + Clone; - - type PublicKeyVar: ToBytesGadget - + EqGadget - + AllocVar - + Clone; - - fn randomize( - parameters: &Self::ParametersVar, - public_key: &Self::PublicKeyVar, - randomness: &[UInt8], - ) -> Result; -} diff --git a/crypto-primitives/src/signature/mod.rs b/crypto-primitives/src/signature/mod.rs deleted file mode 100644 index 76c89c5..0000000 --- a/crypto-primitives/src/signature/mod.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::Error; -use algebra_core::bytes::ToBytes; -use core::hash::Hash; -use rand::Rng; - -#[cfg(feature = "r1cs")] -pub mod constraints; -#[cfg(feature = "r1cs")] -pub use constraints::*; - -pub mod schnorr; - -pub trait SignatureScheme { - type Parameters: Clone + Send + Sync; - type PublicKey: ToBytes + Hash + Eq + Clone + Default + Send + Sync; - type SecretKey: ToBytes + Clone + Default; - type Signature: Clone + Default + Send + Sync; - - fn setup(rng: &mut R) -> Result; - - fn keygen( - pp: &Self::Parameters, - rng: &mut R, - ) -> Result<(Self::PublicKey, Self::SecretKey), Error>; - - fn sign( - pp: &Self::Parameters, - sk: &Self::SecretKey, - message: &[u8], - rng: &mut R, - ) -> Result; - - fn verify( - pp: &Self::Parameters, - pk: &Self::PublicKey, - message: &[u8], - signature: &Self::Signature, - ) -> Result; - - fn randomize_public_key( - pp: &Self::Parameters, - public_key: &Self::PublicKey, - randomness: &[u8], - ) -> Result; - - fn randomize_signature( - pp: &Self::Parameters, - signature: &Self::Signature, - randomness: &[u8], - ) -> Result; -} - -#[cfg(test)] -mod test { - use crate::signature::{schnorr, *}; - use algebra::{ - ed_on_bls12_381::EdwardsProjective as JubJub, groups::Group, test_rng, to_bytes, - UniformRand, - }; - use blake2::Blake2s; - - fn sign_and_verify(message: &[u8]) { - let rng = &mut test_rng(); - let parameters = S::setup::<_>(rng).unwrap(); - let (pk, sk) = S::keygen(¶meters, rng).unwrap(); - let sig = S::sign(¶meters, &sk, &message, rng).unwrap(); - assert!(S::verify(¶meters, &pk, &message, &sig).unwrap()); - } - - fn failed_verification(message: &[u8], bad_message: &[u8]) { - let rng = &mut test_rng(); - let parameters = S::setup::<_>(rng).unwrap(); - let (pk, sk) = S::keygen(¶meters, rng).unwrap(); - let sig = S::sign(¶meters, &sk, message, rng).unwrap(); - assert!(!S::verify(¶meters, &pk, bad_message, &sig).unwrap()); - } - - fn randomize_and_verify(message: &[u8], randomness: &[u8]) { - let rng = &mut test_rng(); - let parameters = S::setup::<_>(rng).unwrap(); - let (pk, sk) = S::keygen(¶meters, rng).unwrap(); - let sig = S::sign(¶meters, &sk, message, rng).unwrap(); - assert!(S::verify(¶meters, &pk, message, &sig).unwrap()); - let randomized_pk = S::randomize_public_key(¶meters, &pk, randomness).unwrap(); - let randomized_sig = S::randomize_signature(¶meters, &sig, randomness).unwrap(); - assert!(S::verify(¶meters, &randomized_pk, &message, &randomized_sig).unwrap()); - } - - #[test] - fn schnorr_signature_test() { - let message = "Hi, I am a Schnorr signature!"; - let rng = &mut test_rng(); - sign_and_verify::>(message.as_bytes()); - failed_verification::>( - message.as_bytes(), - "Bad message".as_bytes(), - ); - let random_scalar = to_bytes!(::ScalarField::rand(rng)).unwrap(); - randomize_and_verify::>( - message.as_bytes(), - &random_scalar.as_slice(), - ); - } -} diff --git a/crypto-primitives/src/signature/schnorr/constraints.rs b/crypto-primitives/src/signature/schnorr/constraints.rs deleted file mode 100644 index 61d5587..0000000 --- a/crypto-primitives/src/signature/schnorr/constraints.rs +++ /dev/null @@ -1,158 +0,0 @@ -use crate::Vec; -use algebra_core::{Field, ProjectiveCurve}; -use r1cs_core::{Namespace, SynthesisError}; -use r1cs_std::prelude::*; - -use crate::signature::SigRandomizePkGadget; - -use core::{borrow::Borrow, marker::PhantomData}; - -use crate::signature::schnorr::{Parameters, PublicKey, Schnorr}; -use digest::Digest; - -type ConstraintF = <::BaseField as Field>::BasePrimeField; - -#[derive(Clone)] -pub struct ParametersVar>> -where - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - generator: GC, - _curve: PhantomData, -} - -#[derive(Derivative)] -#[derivative( - Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), - Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") -)] -pub struct PublicKeyVar>> -where - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - pub_key: GC, - #[doc(hidden)] - _group: PhantomData<*const C>, -} - -pub struct SchnorrRandomizePkGadget>> -where - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - #[doc(hidden)] - _group: PhantomData<*const C>, - #[doc(hidden)] - _group_gadget: PhantomData<*const GC>, -} - -impl SigRandomizePkGadget, ConstraintF> - for SchnorrRandomizePkGadget -where - C: ProjectiveCurve, - GC: CurveVar>, - D: Digest + Send + Sync, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - type ParametersVar = ParametersVar; - type PublicKeyVar = PublicKeyVar; - - #[tracing::instrument(target = "r1cs", skip(parameters, public_key, randomness))] - fn randomize( - parameters: &Self::ParametersVar, - public_key: &Self::PublicKeyVar, - randomness: &[UInt8>], - ) -> Result { - let base = parameters.generator.clone(); - let randomness = randomness - .iter() - .flat_map(|b| b.to_bits_le().unwrap()) - .collect::>(); - let rand_pk = &public_key.pub_key + &base.scalar_mul_le(randomness.iter())?; - Ok(PublicKeyVar { - pub_key: rand_pk, - _group: PhantomData, - }) - } -} - -impl AllocVar, ConstraintF> for ParametersVar -where - C: ProjectiveCurve, - GC: CurveVar>, - D: Digest, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - fn new_variable>>( - cs: impl Into>>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let generator = GC::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?; - Ok(Self { - generator, - _curve: PhantomData, - }) - } -} - -impl AllocVar, ConstraintF> for PublicKeyVar -where - C: ProjectiveCurve, - GC: CurveVar>, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - fn new_variable>>( - cs: impl Into>>, - f: impl FnOnce() -> Result, - mode: AllocationMode, - ) -> Result { - let pub_key = GC::new_variable(cs, f, mode)?; - Ok(Self { - pub_key, - _group: PhantomData, - }) - } -} - -impl EqGadget> for PublicKeyVar -where - C: ProjectiveCurve, - GC: CurveVar>, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - #[inline] - fn is_eq(&self, other: &Self) -> Result>, SynthesisError> { - self.pub_key.is_eq(&other.pub_key) - } - - #[inline] - fn conditional_enforce_equal( - &self, - other: &Self, - condition: &Boolean>, - ) -> Result<(), SynthesisError> { - self.pub_key - .conditional_enforce_equal(&other.pub_key, condition) - } - - #[inline] - fn conditional_enforce_not_equal( - &self, - other: &Self, - condition: &Boolean>, - ) -> Result<(), SynthesisError> { - self.pub_key - .conditional_enforce_not_equal(&other.pub_key, condition) - } -} - -impl ToBytesGadget> for PublicKeyVar -where - C: ProjectiveCurve, - GC: CurveVar>, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, -{ - fn to_bytes(&self) -> Result>>, SynthesisError> { - self.pub_key.to_bytes() - } -} diff --git a/crypto-primitives/src/signature/schnorr/mod.rs b/crypto-primitives/src/signature/schnorr/mod.rs deleted file mode 100644 index eab96bd..0000000 --- a/crypto-primitives/src/signature/schnorr/mod.rs +++ /dev/null @@ -1,229 +0,0 @@ -use crate::{Error, SignatureScheme, Vec}; -use algebra_core::{ - bytes::ToBytes, - fields::{Field, PrimeField}, - io::{Result as IoResult, Write}, - to_bytes, AffineCurve, One, ProjectiveCurve, ToConstraintField, UniformRand, Zero, -}; -use core::{hash::Hash, marker::PhantomData}; -use digest::Digest; -use rand::Rng; - -#[cfg(feature = "r1cs")] -pub mod constraints; - -pub struct Schnorr { - _group: PhantomData, - _hash: PhantomData, -} - -#[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, H: Digest"), Debug)] -pub struct Parameters { - _hash: PhantomData, - pub generator: C::Affine, - pub salt: [u8; 32], -} - -pub type PublicKey = ::Affine; - -#[derive(Clone, Default, Debug)] -pub struct SecretKey(pub C::ScalarField); - -impl ToBytes for SecretKey { - #[inline] - fn write(&self, writer: W) -> IoResult<()> { - self.0.write(writer) - } -} - -#[derive(Clone, Default, Debug)] -pub struct Signature { - pub prover_response: C::ScalarField, - pub verifier_challenge: C::ScalarField, -} - -impl SignatureScheme for Schnorr -where - C::ScalarField: PrimeField, -{ - type Parameters = Parameters; - type PublicKey = PublicKey; - type SecretKey = SecretKey; - type Signature = Signature; - - fn setup(rng: &mut R) -> Result { - let setup_time = start_timer!(|| "SchnorrSig::Setup"); - - let mut salt = [0u8; 32]; - rng.fill_bytes(&mut salt); - let generator = C::rand(rng).into(); - - end_timer!(setup_time); - Ok(Parameters { - _hash: PhantomData, - generator, - salt, - }) - } - - fn keygen( - parameters: &Self::Parameters, - rng: &mut R, - ) -> Result<(Self::PublicKey, Self::SecretKey), Error> { - let keygen_time = start_timer!(|| "SchnorrSig::KeyGen"); - - let secret_key = C::ScalarField::rand(rng); - let public_key = parameters.generator.mul(secret_key).into(); - - end_timer!(keygen_time); - Ok((public_key, SecretKey(secret_key))) - } - - fn sign( - parameters: &Self::Parameters, - sk: &Self::SecretKey, - message: &[u8], - rng: &mut R, - ) -> Result { - let sign_time = start_timer!(|| "SchnorrSig::Sign"); - // (k, e); - let (random_scalar, verifier_challenge) = loop { - // Sample a random scalar `k` from the prime scalar field. - let random_scalar: C::ScalarField = C::ScalarField::rand(rng); - // Commit to the random scalar via r := k · G. - // This is the prover's first msg in the Sigma protocol. - let prover_commitment = parameters.generator.mul(random_scalar).into_affine(); - - // Hash everything to get verifier challenge. - let mut hash_input = Vec::new(); - hash_input.extend_from_slice(¶meters.salt); - hash_input.extend_from_slice(&to_bytes![prover_commitment]?); - hash_input.extend_from_slice(message); - - // Compute the supposed verifier response: e := H(salt || r || msg); - if let Some(verifier_challenge) = - C::ScalarField::from_random_bytes(&D::digest(&hash_input)) - { - break (random_scalar, verifier_challenge); - }; - }; - - // k - xe; - let prover_response = random_scalar - &(verifier_challenge * &sk.0); - let signature = Signature { - prover_response, - verifier_challenge, - }; - - end_timer!(sign_time); - Ok(signature) - } - - fn verify( - parameters: &Self::Parameters, - pk: &Self::PublicKey, - message: &[u8], - signature: &Self::Signature, - ) -> Result { - let verify_time = start_timer!(|| "SchnorrSig::Verify"); - - let Signature { - prover_response, - verifier_challenge, - } = signature; - let mut claimed_prover_commitment = parameters.generator.mul(*prover_response); - let public_key_times_verifier_challenge = pk.mul(*verifier_challenge); - claimed_prover_commitment += &public_key_times_verifier_challenge; - let claimed_prover_commitment = claimed_prover_commitment.into_affine(); - - let mut hash_input = Vec::new(); - hash_input.extend_from_slice(¶meters.salt); - hash_input.extend_from_slice(&to_bytes![claimed_prover_commitment]?); - hash_input.extend_from_slice(&message); - - let obtained_verifier_challenge = if let Some(obtained_verifier_challenge) = - C::ScalarField::from_random_bytes(&D::digest(&hash_input)) - { - obtained_verifier_challenge - } else { - return Ok(false); - }; - end_timer!(verify_time); - Ok(verifier_challenge == &obtained_verifier_challenge) - } - - fn randomize_public_key( - parameters: &Self::Parameters, - public_key: &Self::PublicKey, - randomness: &[u8], - ) -> Result { - let rand_pk_time = start_timer!(|| "SchnorrSig::RandomizePubKey"); - - let randomized_pk = *public_key; - let base = parameters.generator; - let mut encoded = C::zero(); - for bit in bytes_to_bits(randomness) - .into_iter() - .rev() - .skip_while(|b| !b) - { - encoded.double_in_place(); - if bit { - encoded.add_assign_mixed(&base) - } - } - encoded.add_assign_mixed(&randomized_pk); - - end_timer!(rand_pk_time); - - Ok(encoded.into()) - } - - fn randomize_signature( - _parameter: &Self::Parameters, - signature: &Self::Signature, - randomness: &[u8], - ) -> Result { - let rand_signature_time = start_timer!(|| "SchnorrSig::RandomizeSig"); - let Signature { - prover_response, - verifier_challenge, - } = signature; - let mut base = C::ScalarField::one(); - let mut multiplier = C::ScalarField::zero(); - for bit in bytes_to_bits(randomness) { - if bit { - multiplier += &base; - } - base.double_in_place(); - } - - let new_sig = Signature { - prover_response: *prover_response - &(*verifier_challenge * &multiplier), - verifier_challenge: *verifier_challenge, - }; - end_timer!(rand_signature_time); - Ok(new_sig) - } -} - -pub fn bytes_to_bits(bytes: &[u8]) -> Vec { - let mut bits = Vec::with_capacity(bytes.len() * 8); - for byte in bytes { - for i in 0..8 { - let bit = (*byte >> (8 - i - 1)) & 1; - bits.push(bit == 1); - } - } - bits -} - -impl, D: Digest> - ToConstraintField for Parameters -{ - #[inline] - fn to_field_elements(&self) -> Result, Error> { - self.generator.into_projective().to_field_elements() - } -} diff --git a/r1cs-std/Cargo.toml b/r1cs-std/Cargo.toml deleted file mode 100644 index 7006f5a..0000000 --- a/r1cs-std/Cargo.toml +++ /dev/null @@ -1,58 +0,0 @@ -[package] -name = "r1cs-std" -version = "0.1.1-alpha.0" -authors = [ - "Sean Bowe", - "Alessandro Chiesa", - "Matthew Green", - "Ian Miers", - "Pratyush Mishra", - "Howard Wu" -] -description = "A standard library for constraint system gadgets" -homepage = "https://libzexe.org" -repository = "https://github.com/scipr/zexe" -documentation = "https://docs.rs/r1cs-std/" -keywords = ["zero knowledge", "cryptography", "zkSNARK", "SNARK"] -categories = ["cryptography"] -include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] -license = "MIT/Apache-2.0" -edition = "2018" - -################################# Dependencies ################################ - -[dependencies] -algebra = { git = "https://github.com/scipr-lab/zexe", default-features = false } -r1cs-core = { git = "https://github.com/scipr-lab/zexe", default-features = false } -derivative = { version = "2", features = ["use_core"] } -tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } - -[dev-dependencies] -rand = { version = "0.7", default-features = false } -rand_xorshift = { version = "0.2" } -# Currently this means that all downstream users of `r1cs-std` will be using -# `algebra` with the `bls12_381` feature. This is because of a cargo bug. -algebra = { git = "https://github.com/scipr-lab/zexe", default-features = false, features = [ "bls12_381" ] } - -[features] -default = ["std"] -full = [ - "bls12_377", "ed_on_bn254", "ed_on_bls12_381", "ed_on_bls12_377", "ed_on_cp6_782", - "ed_on_bw6_761", "ed_on_mnt4_298", "ed_on_mnt4_753", "mnt4_298", "mnt4_753", "mnt6_298", "mnt6_753" -] - -bls12_377 = [ "algebra/bls12_377" ] -ed_on_bn254 = [ "algebra/ed_on_bn254" ] -ed_on_bls12_381 = [ "algebra/ed_on_bls12_381" ] -ed_on_bls12_377 = [ "algebra/ed_on_bls12_377" ] -ed_on_cp6_782 = [ "algebra/ed_on_cp6_782" ] -ed_on_bw6_761 = [ "algebra/ed_on_bw6_761", "algebra/ed_on_cp6_782" ] -ed_on_mnt4_298 = [ "algebra/ed_on_mnt4_298" ] -ed_on_mnt4_753 = [ "algebra/ed_on_mnt4_753" ] -mnt4_298 = [ "algebra/mnt4_298" ] -mnt4_753 = [ "algebra/mnt4_753" ] -mnt6_298 = [ "algebra/mnt6_298" ] -mnt6_753 = [ "algebra/mnt6_753" ] - -std = [ "algebra/std", "r1cs-core/std" ] -parallel = [ "std", "algebra/parallel" ] diff --git a/r1cs-std/LICENSE-APACHE b/r1cs-std/LICENSE-APACHE deleted file mode 120000 index 965b606..0000000 --- a/r1cs-std/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE \ No newline at end of file diff --git a/r1cs-std/LICENSE-MIT b/r1cs-std/LICENSE-MIT deleted file mode 120000 index 76219eb..0000000 --- a/r1cs-std/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT \ No newline at end of file diff --git a/r1cs-std/src/fields/mod.rs b/r1cs-std/src/fields/mod.rs deleted file mode 100644 index 5320e1e..0000000 --- a/r1cs-std/src/fields/mod.rs +++ /dev/null @@ -1,422 +0,0 @@ -use algebra::{prelude::*, BitIteratorBE}; -use core::{ - fmt::Debug, - ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, -}; -use r1cs_core::SynthesisError; - -use crate::{prelude::*, Assignment}; - -/// This module contains a generic implementation of cubic extension field variables. -/// That is, it implements the R1CS equivalent of `algebra_core::CubicExtField`. -pub mod cubic_extension; -/// This module contains a generic implementation of quadratic extension field variables. -/// That is, it implements the R1CS equivalent of `algebra_core::QuadExtField`. -pub mod quadratic_extension; - -/// This module contains a generic implementation of prime field variables. -/// That is, it implements the R1CS equivalent of `algebra_core::Fp*`. -pub mod fp; - -/// This module contains a generic implementation of the degree-12 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::Fp12` -pub mod fp12; -/// This module contains a generic implementation of the degree-2 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::Fp2` -pub mod fp2; -/// This module contains a generic implementation of the degree-3 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::Fp3` -pub mod fp3; -/// This module contains a generic implementation of the degree-4 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::Fp4` -pub mod fp4; -/// This module contains a generic implementation of the degree-6 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::fp6_2over3::Fp6` -pub mod fp6_2over3; -/// This module contains a generic implementation of the degree-6 tower extension field. -/// That is, it implements the R1CS equivalent of `algebra_core::fp6_3over2::Fp6` -pub mod fp6_3over2; - -/// This trait is a hack used to work around the lack of implied bounds. -pub trait FieldOpsBounds<'a, F, T: 'a>: - Sized - + Add<&'a T, Output = T> - + Sub<&'a T, Output = T> - + Mul<&'a T, Output = T> - + Add - + Sub - + Mul - + Add - + Sub - + Mul -{ -} - -/// A variable representing a field. Corresponds to the native type `F`. -pub trait FieldVar: - 'static - + Clone - + From> - + R1CSVar - + EqGadget - + ToBitsGadget - + AllocVar - + ToBytesGadget - + CondSelectGadget - + for<'a> FieldOpsBounds<'a, F, Self> - + for<'a> AddAssign<&'a Self> - + for<'a> SubAssign<&'a Self> - + for<'a> MulAssign<&'a Self> - + AddAssign - + SubAssign - + MulAssign - + AddAssign - + SubAssign - + MulAssign - + Debug -{ - /// Returns the constant `F::zero()`. - fn zero() -> Self; - - /// Returns a `Boolean` representing whether `self == Self::zero()`. - fn is_zero(&self) -> Result, SynthesisError> { - self.is_eq(&Self::zero()) - } - - /// Returns the constant `F::one()`. - fn one() -> Self; - - /// Returns a `Boolean` representing whether `self == Self::one()`. - fn is_one(&self) -> Result, SynthesisError> { - self.is_eq(&Self::one()) - } - - /// Returns a constant with value `v`. - /// - /// This *should not* allocate any variables. - fn constant(v: F) -> Self; - - /// Computes `self + self`. - fn double(&self) -> Result { - Ok(self.clone() + self) - } - - /// Sets `self = self + self`. - fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> { - *self += self.double()?; - Ok(self) - } - - /// Coputes `-self`. - fn negate(&self) -> Result; - - /// Sets `self = -self`. - #[inline] - fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> { - *self = self.negate()?; - Ok(self) - } - - /// Computes `self * self`. - /// - /// A default implementation is provided which just invokes the underlying - /// multiplication routine. However, this method should be specialized - /// for extension fields, where faster algorithms exist for squaring. - fn square(&self) -> Result { - Ok(self.clone() * self) - } - - /// Sets `self = self.square()`. - fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> { - *self = self.square()?; - Ok(self) - } - - /// Enforces that `self * other == result`. - fn mul_equals(&self, other: &Self, result: &Self) -> Result<(), SynthesisError> { - let actual_result = self.clone() * other; - result.enforce_equal(&actual_result) - } - - /// Enforces that `self * self == result`. - fn square_equals(&self, result: &Self) -> Result<(), SynthesisError> { - let actual_result = self.square()?; - result.enforce_equal(&actual_result) - } - - /// Computes `result` such that `self * result == Self::one()`. - fn inverse(&self) -> Result; - - /// Returns `(self / denominator)`. but requires fewer constraints than - /// `self * denominator.inverse()`. - /// It is up to the caller to ensure that denominator is non-zero, - /// since in that case the result is unconstrained. - fn mul_by_inverse(&self, denominator: &Self) -> Result { - let result = Self::new_witness(self.cs(), || { - let denominator_inv_native = denominator.value()?.inverse().get()?; - let result = self.value()? * &denominator_inv_native; - Ok(result) - })?; - result.mul_equals(&denominator, &self)?; - - Ok(result) - } - - /// Computes the frobenius map over `self`. - fn frobenius_map(&self, power: usize) -> Result; - - /// Sets `self = self.frobenius_map()`. - fn frobenius_map_in_place(&mut self, power: usize) -> Result<&mut Self, SynthesisError> { - *self = self.frobenius_map(power)?; - Ok(self) - } - - /// Comptues `self^bits`, where `bits` is a *little-endian* bit-wise decomposition - /// of the exponent. - fn pow_le(&self, bits: &[Boolean]) -> Result { - let mut res = Self::one(); - let mut power = self.clone(); - for bit in bits { - let tmp = res.clone() * &power; - res = bit.select(&tmp, &res)?; - power.square_in_place()?; - } - Ok(res) - } - - /// Computes `self^S`, where S is interpreted as an little-endian u64-decomposition of - /// an integer. - fn pow_by_constant>(&self, exp: S) -> Result { - let mut res = Self::one(); - for i in BitIteratorBE::without_leading_zeros(exp) { - res.square_in_place()?; - if i { - res *= self; - } - } - Ok(res) - } -} - -#[cfg(test)] -pub(crate) mod tests { - use rand::{self, SeedableRng}; - use rand_xorshift::XorShiftRng; - - use crate::{fields::*, Vec}; - use algebra::{test_rng, BitIteratorLE, Field, UniformRand}; - use r1cs_core::{ConstraintSystem, SynthesisError}; - - #[allow(dead_code)] - pub(crate) 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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; - let b = AF::new_witness(r1cs_core::ns!(cs, "generate_b"), || Ok(b_native))?; - let b_const = AF::new_constant(r1cs_core::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 = algebra::BitIteratorLE::new(&[0u64, 1u64]).collect::>(); - let fv = AF::new_witness(r1cs_core::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(r1cs_core::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!( - algebra::to_bytes!(r_native).unwrap(), - bytes.value().unwrap() - ); - assert!(cs.is_satisfied().unwrap()); - let bytes = r.to_bytes()?; - assert_eq!( - algebra::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() { - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - } - assert!(cs.is_satisfied().unwrap()); - Ok(()) - } - - #[allow(dead_code)] - pub(crate) 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(r1cs_core::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(()) - } -} diff --git a/r1cs-std/src/instantiated/bls12_377/curves.rs b/r1cs-std/src/instantiated/bls12_377/curves.rs deleted file mode 100644 index e0b86d3..0000000 --- a/r1cs-std/src/instantiated/bls12_377/curves.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::groups::bls12; -use algebra::bls12_377::Parameters; - -/// 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 algebra::curves::models::bls12::Bls12Parameters; - crate::groups::curves::short_weierstrass::test::< - ::G1Parameters, - G1Var, - >() - .unwrap(); - crate::groups::curves::short_weierstrass::test::< - ::G2Parameters, - G2Var, - >() - .unwrap(); -} diff --git a/r1cs-std/src/instantiated/bls12_377/fields.rs b/r1cs-std/src/instantiated/bls12_377/fields.rs deleted file mode 100644 index f64a281..0000000 --- a/r1cs-std/src/instantiated/bls12_377/fields.rs +++ /dev/null @@ -1,32 +0,0 @@ -use algebra::bls12_377::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters}; - -use crate::fields::{fp::FpVar, fp12::Fp12Var, fp2::Fp2Var, fp6_3over2::Fp6Var}; - -/// A variable that is the R1CS equivalent of `algebra::bls12_377::Fq`. -pub type FqVar = FpVar; - -/// A variable that is the R1CS equivalent of `algebra::bls12_377::Fq2`. -pub type Fq2Var = Fp2Var; -/// A variable that is the R1CS equivalent of `algebra::bls12_377::Fq6`. -pub type Fq6Var = Fp6Var; -/// A variable that is the R1CS equivalent of `algebra::bls12_377::Fq12`. -pub type Fq12Var = Fp12Var; - -#[test] -fn bls12_377_field_test() { - use super::*; - use crate::fields::tests::*; - use algebra::bls12_377::{Fq, Fq12, Fq2, Fq6}; - - 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/r1cs-std/src/instantiated/bls12_377/mod.rs b/r1cs-std/src/instantiated/bls12_377/mod.rs deleted file mode 100644 index d1df08d..0000000 --- a/r1cs-std/src/instantiated/bls12_377/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::bls12_377`. -//! -//! It implements field variables for `algebra::bls12_377::{Fq, Fq2, Fq6, Fq12}`, -//! group variables for `algebra::bls12_377::{G1, G2}`, and implements constraint -//! generation for computing `Bls12_377::pairing`. -//! -//! The field underlying these constraints is `algebra::bls12_377::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, bls12_377::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::bls12_377::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, bls12_377::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::bls12_377::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G1Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G1Var::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, PairingEngine, bls12_377::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::bls12_377::{self, *}; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G2Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G2Var::new_constant(r1cs_core::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 = bls12_377::PairingVar::prepare_g1(&a)?; -//! let b_prep = bls12_377::PairingVar::prepare_g2(&b)?; -//! let pairing_result = bls12_377::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 = bls12_377::PairingVar::prepare_g1(&a_const)?; -//! let b_prep_const = bls12_377::PairingVar::prepare_g2(&b_const)?; -//! let pairing_result_const = bls12_377::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/r1cs-std/src/instantiated/bls12_377/pairing.rs b/r1cs-std/src/instantiated/bls12_377/pairing.rs deleted file mode 100644 index e9a8047..0000000 --- a/r1cs-std/src/instantiated/bls12_377/pairing.rs +++ /dev/null @@ -1,9 +0,0 @@ -use algebra::bls12_377::Parameters; - -/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear group. -pub type PairingVar = crate::pairing::bls12::PairingVar; - -#[test] -fn test() { - crate::pairing::tests::bilinearity_test::().unwrap() -} diff --git a/r1cs-std/src/instantiated/ed_on_bls12_377/curves.rs b/r1cs-std/src/instantiated/ed_on_bls12_377/curves.rs deleted file mode 100644 index ed38d21..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_377/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_bls12_377::*; - -use crate::ed_on_bls12_377::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bls12_377::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bls12_377/fields.rs b/r1cs-std/src/instantiated/ed_on_bls12_377/fields.rs deleted file mode 100644 index 32011d1..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_377/fields.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::fields::fp::FpVar; -use algebra::ed_on_bls12_377::fq::Fq; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bls12_377::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bls12_377/mod.rs b/r1cs-std/src/instantiated/ed_on_bls12_377/mod.rs deleted file mode 100644 index f7d3da3..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_377/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_bls12_377`. -//! -//! It implements field variables for `algebra::ed_on_bls12_377::Fq`, -//! and group variables for `algebra::ed_on_bls12_377::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_bls12_377::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_bls12_377::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_bls12_377::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_bls12_377::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_bls12_377::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/ed_on_bls12_381/curves.rs b/r1cs-std/src/instantiated/ed_on_bls12_381/curves.rs deleted file mode 100644 index 555f4ad..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_381/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_bls12_381::*; - -use crate::ed_on_bls12_381::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bls12_381::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::<_, EdwardsVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bls12_381/fields.rs b/r1cs-std/src/instantiated/ed_on_bls12_381/fields.rs deleted file mode 100644 index eaf367b..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_381/fields.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::fields::fp::FpVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bls12_381::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bls12_381/mod.rs b/r1cs-std/src/instantiated/ed_on_bls12_381/mod.rs deleted file mode 100644 index 8368f6d..0000000 --- a/r1cs-std/src/instantiated/ed_on_bls12_381/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_bls12_381`. -//! -//! It implements field variables for `algebra::ed_on_bls12_381::Fq`, -//! and group variables for `algebra::ed_on_bls12_381::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_bls12_381::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_bls12_381::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_bls12_381::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_bls12_381::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_bls12_381::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/ed_on_bn254/curves.rs b/r1cs-std/src/instantiated/ed_on_bn254/curves.rs deleted file mode 100644 index f3171a1..0000000 --- a/r1cs-std/src/instantiated/ed_on_bn254/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_bn254::*; - -use crate::ed_on_bn254::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bn254::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::<_, EdwardsVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bn254/fields.rs b/r1cs-std/src/instantiated/ed_on_bn254/fields.rs deleted file mode 100644 index 45b30a0..0000000 --- a/r1cs-std/src/instantiated/ed_on_bn254/fields.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::fields::fp::FpVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_bn254::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_bn254/mod.rs b/r1cs-std/src/instantiated/ed_on_bn254/mod.rs deleted file mode 100644 index c4facd7..0000000 --- a/r1cs-std/src/instantiated/ed_on_bn254/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_bn254`. -//! -//! It implements field variables for `algebra::ed_on_bn254::Fq`, -//! and group variables for `algebra::ed_on_bn254::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_bn254::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_bn254::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_bn254::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_bn254::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_bn254::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/ed_on_bw6_761/mod.rs b/r1cs-std/src/instantiated/ed_on_bw6_761/mod.rs deleted file mode 100644 index 73ae181..0000000 --- a/r1cs-std/src/instantiated/ed_on_bw6_761/mod.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_bw6_761`. -//! -//! It implements field variables for `algebra::ed_on_bw6_761::Fq`, -//! and group variables for `algebra::ed_on_bw6_761::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_bw6_761::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_bw6_761::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_bw6_761::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_bw6_761::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_bw6_761::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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 crate::instantiated::ed_on_cp6_782::*; diff --git a/r1cs-std/src/instantiated/ed_on_cp6_782/curves.rs b/r1cs-std/src/instantiated/ed_on_cp6_782/curves.rs deleted file mode 100644 index 2c5d101..0000000 --- a/r1cs-std/src/instantiated/ed_on_cp6_782/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_cp6_782::*; - -use crate::instantiated::ed_on_cp6_782::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_cp6_782::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_cp6_782/fields.rs b/r1cs-std/src/instantiated/ed_on_cp6_782/fields.rs deleted file mode 100644 index db4cf98..0000000 --- a/r1cs-std/src/instantiated/ed_on_cp6_782/fields.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::fields::fp::FpVar; -use algebra::ed_on_cp6_782::fq::Fq; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_cp6_782::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_cp6_782/mod.rs b/r1cs-std/src/instantiated/ed_on_cp6_782/mod.rs deleted file mode 100644 index 24e43f6..0000000 --- a/r1cs-std/src/instantiated/ed_on_cp6_782/mod.rs +++ /dev/null @@ -1,108 +0,0 @@ -#![allow(unreachable_pub)] -//! This module implements the R1CS equivalent of `algebra::ed_on_cp6_782`. -//! -//! It implements field variables for `algebra::ed_on_cp6_782::Fq`, -//! and group variables for `algebra::ed_on_cp6_782::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_cp6_782::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_cp6_782::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_cp6_782::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_cp6_782::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_cp6_782::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/ed_on_mnt4_298/curves.rs b/r1cs-std/src/instantiated/ed_on_mnt4_298/curves.rs deleted file mode 100644 index bc251c6..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_298/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_mnt4_298::*; - -use crate::instantiated::ed_on_mnt4_298::fields::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_mnt4_298::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_mnt4_298/fields.rs b/r1cs-std/src/instantiated/ed_on_mnt4_298/fields.rs deleted file mode 100644 index 714bd98..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_298/fields.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::fields::fp::FpVar; -use algebra::ed_on_mnt4_298::fq::Fq; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_mnt4_298::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_mnt4_298/mod.rs b/r1cs-std/src/instantiated/ed_on_mnt4_298/mod.rs deleted file mode 100644 index aa3d206..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_298/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_mnt4_298`. -//! -//! It implements field variables for `algebra::ed_on_mnt4_298::Fq`, -//! and group variables for `algebra::ed_on_mnt4_298::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_mnt4_298::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_mnt4_298::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_mnt4_298::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_mnt4_298::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_mnt4_298::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/ed_on_mnt4_753/curves.rs b/r1cs-std/src/instantiated/ed_on_mnt4_753/curves.rs deleted file mode 100644 index c0b7677..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_753/curves.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::groups::curves::twisted_edwards::AffineVar; -use algebra::ed_on_mnt4_753::*; - -use crate::instantiated::ed_on_mnt4_753::fields::FqVar; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_mnt4_753::EdwardsAffine`. -pub type EdwardsVar = AffineVar; - -#[test] -fn test() { - crate::groups::curves::twisted_edwards::test::().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_mnt4_753/fields.rs b/r1cs-std/src/instantiated/ed_on_mnt4_753/fields.rs deleted file mode 100644 index 750b1b2..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_753/fields.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::fields::fp::FpVar; -use algebra::ed_on_mnt4_753::fq::Fq; - -/// A variable that is the R1CS equivalent of `algebra::ed_on_mnt4_753::Fq`. -pub type FqVar = FpVar; - -#[test] -fn test() { - crate::fields::tests::field_test::<_, _, FqVar>().unwrap(); -} diff --git a/r1cs-std/src/instantiated/ed_on_mnt4_753/mod.rs b/r1cs-std/src/instantiated/ed_on_mnt4_753/mod.rs deleted file mode 100644 index 9d030ac..0000000 --- a/r1cs-std/src/instantiated/ed_on_mnt4_753/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::ed_on_mnt4_753`. -//! -//! It implements field variables for `algebra::ed_on_mnt4_753::Fq`, -//! and group variables for `algebra::ed_on_mnt4_753::GroupProjective`. -//! -//! The field underlying these constraints is `algebra::ed_on_mnt4_753::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, ed_on_mnt4_753::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::ed_on_mnt4_753::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, ed_on_mnt4_753::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::ed_on_mnt4_753::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = EdwardsVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = EdwardsVar::new_constant(r1cs_core::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/r1cs-std/src/instantiated/mnt4_298/curves.rs b/r1cs-std/src/instantiated/mnt4_298/curves.rs deleted file mode 100644 index ecb6015..0000000 --- a/r1cs-std/src/instantiated/mnt4_298/curves.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::groups::mnt4; -use algebra::mnt4_298::Parameters; - -/// 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 algebra::curves::models::mnt4::MNT4Parameters; - crate::groups::curves::short_weierstrass::test::< - ::G1Parameters, - G1Var, - >() - .unwrap(); - crate::groups::curves::short_weierstrass::test::< - ::G2Parameters, - G2Var, - >() - .unwrap(); -} diff --git a/r1cs-std/src/instantiated/mnt4_298/fields.rs b/r1cs-std/src/instantiated/mnt4_298/fields.rs deleted file mode 100644 index 279a5c0..0000000 --- a/r1cs-std/src/instantiated/mnt4_298/fields.rs +++ /dev/null @@ -1,26 +0,0 @@ -use algebra::mnt4_298::{Fq, Fq2Parameters, Fq4Parameters}; - -use crate::fields::{fp::FpVar, fp2::Fp2Var, fp4::Fp4Var}; - -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq`. -pub type FqVar = FpVar; -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq2`. -pub type Fq2Var = Fp2Var; -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq4`. -pub type Fq4Var = Fp4Var; - -#[test] -fn mnt4_298_field_gadgets_test() { - use super::*; - use crate::fields::tests::*; - use algebra::mnt4_298::{Fq, Fq2, Fq4}; - - 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/r1cs-std/src/instantiated/mnt4_298/mod.rs b/r1cs-std/src/instantiated/mnt4_298/mod.rs deleted file mode 100644 index fe65742..0000000 --- a/r1cs-std/src/instantiated/mnt4_298/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::mnt4_298`. -//! -//! It implements field variables for `algebra::mnt4_298::{Fq, Fq2, Fq4}`, -//! group variables for `algebra::mnt4_298::{G1, G2}`, and implements constraint -//! generation for computing `MNT4_298::pairing`. -//! -//! The field underlying these constraints is `algebra::mnt4_298::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, mnt4_298::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::mnt4_298::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, mnt4_298::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt4_298::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G1Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G1Var::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, PairingEngine, mnt4_298::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt4_298::{self, *}; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G2Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G2Var::new_constant(r1cs_core::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 = mnt4_298::PairingVar::prepare_g1(&a)?; -//! let b_prep = mnt4_298::PairingVar::prepare_g2(&b)?; -//! let pairing_result = mnt4_298::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 = mnt4_298::PairingVar::prepare_g1(&a_const)?; -//! let b_prep_const = mnt4_298::PairingVar::prepare_g2(&b_const)?; -//! let pairing_result_const = mnt4_298::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/r1cs-std/src/instantiated/mnt4_298/pairing.rs b/r1cs-std/src/instantiated/mnt4_298/pairing.rs deleted file mode 100644 index c1edc51..0000000 --- a/r1cs-std/src/instantiated/mnt4_298/pairing.rs +++ /dev/null @@ -1,9 +0,0 @@ -use algebra::mnt4_298::Parameters; - -/// Specifies the constraints for computing a pairing in the MNT4-298 bilinear group. -pub type PairingVar = crate::pairing::mnt4::PairingVar; - -#[test] -fn test() { - crate::pairing::tests::bilinearity_test::().unwrap() -} diff --git a/r1cs-std/src/instantiated/mnt4_753/curves.rs b/r1cs-std/src/instantiated/mnt4_753/curves.rs deleted file mode 100644 index 0f92230..0000000 --- a/r1cs-std/src/instantiated/mnt4_753/curves.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::groups::mnt4; -use algebra::mnt4_753::Parameters; - -/// 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 algebra::curves::models::mnt4::MNT4Parameters; - crate::groups::curves::short_weierstrass::test::< - ::G1Parameters, - G1Var, - >() - .unwrap(); - crate::groups::curves::short_weierstrass::test::< - ::G2Parameters, - G2Var, - >() - .unwrap(); -} diff --git a/r1cs-std/src/instantiated/mnt4_753/fields.rs b/r1cs-std/src/instantiated/mnt4_753/fields.rs deleted file mode 100644 index 9f79e0e..0000000 --- a/r1cs-std/src/instantiated/mnt4_753/fields.rs +++ /dev/null @@ -1,26 +0,0 @@ -use algebra::mnt4_753::{Fq, Fq2Parameters, Fq4Parameters}; - -use crate::fields::{fp::FpVar, fp2::Fp2Var, fp4::Fp4Var}; - -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq`. -pub type FqVar = FpVar; -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq2`. -pub type Fq2Var = Fp2Var; -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq4`. -pub type Fq4Var = Fp4Var; - -#[test] -fn mnt4_753_field_gadgets_test() { - use super::*; - use crate::fields::tests::*; - use algebra::mnt4_753::{Fq, Fq2, Fq4}; - - 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/r1cs-std/src/instantiated/mnt4_753/mod.rs b/r1cs-std/src/instantiated/mnt4_753/mod.rs deleted file mode 100644 index c717fdc..0000000 --- a/r1cs-std/src/instantiated/mnt4_753/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::mnt4_753`. -//! -//! It implements field variables for `algebra::mnt4_753::{Fq, Fq2, Fq4}`, -//! group variables for `algebra::mnt4_753::{G1, G2}`, and implements constraint -//! generation for computing `MNT4_753::pairing`. -//! -//! The field underlying these constraints is `algebra::mnt4_753::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, mnt4_753::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::mnt4_753::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, mnt4_753::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt4_753::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G1Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G1Var::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, PairingEngine, mnt4_753::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt4_753::{self, *}; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G2Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G2Var::new_constant(r1cs_core::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 = mnt4_753::PairingVar::prepare_g1(&a)?; -//! let b_prep = mnt4_753::PairingVar::prepare_g2(&b)?; -//! let pairing_result = mnt4_753::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 = mnt4_753::PairingVar::prepare_g1(&a_const)?; -//! let b_prep_const = mnt4_753::PairingVar::prepare_g2(&b_const)?; -//! let pairing_result_const = mnt4_753::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/r1cs-std/src/instantiated/mnt4_753/pairing.rs b/r1cs-std/src/instantiated/mnt4_753/pairing.rs deleted file mode 100644 index 677f644..0000000 --- a/r1cs-std/src/instantiated/mnt4_753/pairing.rs +++ /dev/null @@ -1,9 +0,0 @@ -use algebra::mnt4_753::Parameters; - -/// Specifies the constraints for computing a pairing in the MNT4-753 bilinear group. -pub type PairingVar = crate::pairing::mnt4::PairingVar; - -#[test] -fn test() { - crate::pairing::tests::bilinearity_test::().unwrap() -} diff --git a/r1cs-std/src/instantiated/mnt6_298/curves.rs b/r1cs-std/src/instantiated/mnt6_298/curves.rs deleted file mode 100644 index 0d7f245..0000000 --- a/r1cs-std/src/instantiated/mnt6_298/curves.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::groups::mnt6; -use algebra::mnt6_298::Parameters; - -/// 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 algebra::curves::models::mnt6::MNT6Parameters; - crate::groups::curves::short_weierstrass::test::< - ::G1Parameters, - G1Var, - >() - .unwrap(); - crate::groups::curves::short_weierstrass::test::< - ::G2Parameters, - G2Var, - >() - .unwrap(); -} diff --git a/r1cs-std/src/instantiated/mnt6_298/fields.rs b/r1cs-std/src/instantiated/mnt6_298/fields.rs deleted file mode 100644 index d864bb6..0000000 --- a/r1cs-std/src/instantiated/mnt6_298/fields.rs +++ /dev/null @@ -1,26 +0,0 @@ -use algebra::mnt6_298::{Fq, Fq3Parameters, Fq6Parameters}; - -use crate::fields::{fp::FpVar, fp3::Fp3Var, fp6_2over3::Fp6Var}; - -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq`. -pub type FqVar = FpVar; -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq3`. -pub type Fq3Var = Fp3Var; -/// A variable that is the R1CS equivalent of `algebra::mnt4_298::Fq6`. -pub type Fq6Var = Fp6Var; - -#[test] -fn mnt6_298_field_gadgets_test() { - use super::*; - use crate::fields::tests::*; - use algebra::mnt6_298::{Fq, Fq3, Fq6}; - - 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/r1cs-std/src/instantiated/mnt6_298/mod.rs b/r1cs-std/src/instantiated/mnt6_298/mod.rs deleted file mode 100644 index 292345e..0000000 --- a/r1cs-std/src/instantiated/mnt6_298/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::mnt6_298`. -//! -//! It implements field variables for `algebra::mnt6_298::{Fq, Fq3, Fq6}`, -//! group variables for `algebra::mnt6_298::{G1, G2}`, and implements constraint -//! generation for computing `MNT6_298::pairing`. -//! -//! The field underlying these constraints is `algebra::mnt6_298::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, mnt6_298::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::mnt6_298::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, mnt6_298::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt6_298::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G1Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G1Var::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, PairingEngine, mnt6_298::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt6_298::{self, *}; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G2Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G2Var::new_constant(r1cs_core::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 = mnt6_298::PairingVar::prepare_g1(&a)?; -//! let b_prep = mnt6_298::PairingVar::prepare_g2(&b)?; -//! let pairing_result = mnt6_298::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 = mnt6_298::PairingVar::prepare_g1(&a_const)?; -//! let b_prep_const = mnt6_298::PairingVar::prepare_g2(&b_const)?; -//! let pairing_result_const = mnt6_298::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/r1cs-std/src/instantiated/mnt6_298/pairing.rs b/r1cs-std/src/instantiated/mnt6_298/pairing.rs deleted file mode 100644 index 3d7881e..0000000 --- a/r1cs-std/src/instantiated/mnt6_298/pairing.rs +++ /dev/null @@ -1,9 +0,0 @@ -use algebra::mnt6_298::Parameters; - -/// Specifies the constraints for computing a pairing in the MNT6-298 bilinear group. -pub type PairingVar = crate::pairing::mnt6::PairingVar; - -#[test] -fn test() { - crate::pairing::tests::bilinearity_test::().unwrap() -} diff --git a/r1cs-std/src/instantiated/mnt6_753/curves.rs b/r1cs-std/src/instantiated/mnt6_753/curves.rs deleted file mode 100644 index b3b0160..0000000 --- a/r1cs-std/src/instantiated/mnt6_753/curves.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::groups::mnt6; -use algebra::mnt6_753::Parameters; - -/// 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 algebra::curves::models::mnt6::MNT6Parameters; - crate::groups::curves::short_weierstrass::test::< - ::G1Parameters, - G1Var, - >() - .unwrap(); - crate::groups::curves::short_weierstrass::test::< - ::G2Parameters, - G2Var, - >() - .unwrap(); -} diff --git a/r1cs-std/src/instantiated/mnt6_753/fields.rs b/r1cs-std/src/instantiated/mnt6_753/fields.rs deleted file mode 100644 index 68d1193..0000000 --- a/r1cs-std/src/instantiated/mnt6_753/fields.rs +++ /dev/null @@ -1,26 +0,0 @@ -use algebra::mnt6_753::{Fq, Fq3Parameters, Fq6Parameters}; - -use crate::fields::{fp::FpVar, fp3::Fp3Var, fp6_2over3::Fp6Var}; - -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq`. -pub type FqVar = FpVar; -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq3`. -pub type Fq3Var = Fp3Var; -/// A variable that is the R1CS equivalent of `algebra::mnt4_753::Fq6`. -pub type Fq6Var = Fp6Var; - -#[test] -fn mnt6_753_field_gadgets_test() { - use super::*; - use crate::fields::tests::*; - use algebra::mnt6_753::{Fq, Fq3, Fq6}; - - 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/r1cs-std/src/instantiated/mnt6_753/mod.rs b/r1cs-std/src/instantiated/mnt6_753/mod.rs deleted file mode 100644 index 914a582..0000000 --- a/r1cs-std/src/instantiated/mnt6_753/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements the R1CS equivalent of `algebra::mnt6_753`. -//! -//! It implements field variables for `algebra::mnt6_753::{Fq, Fq3, Fq6}`, -//! group variables for `algebra::mnt6_753::{G1, G2}`, and implements constraint -//! generation for computing `MNT6_753::pairing`. -//! -//! The field underlying these constraints is `algebra::mnt6_753::Fq`. -//! -//! # Examples -//! -//! One can perform standard algebraic operations on `FqVar`: -//! -//! ``` -//! # fn main() -> Result<(), r1cs_core::SynthesisError> { -//! use algebra::{UniformRand, mnt6_753::*}; -//! use r1cs_core::*; -//! use r1cs_std::prelude::*; -//! use r1cs_std::mnt6_753::*; -//! -//! let cs = ConstraintSystem::::new_ref(); -//! // This rng is just for test purposes; do not use it -//! // in real applications. -//! let mut rng = algebra::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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native))?; -//! let b = FqVar::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = FqVar::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, mnt6_753::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt6_753::*; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G1Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G1Var::new_constant(r1cs_core::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<(), r1cs_core::SynthesisError> { -//! # use algebra::{UniformRand, PairingEngine, mnt6_753::*}; -//! # use r1cs_core::*; -//! # use r1cs_std::prelude::*; -//! # use r1cs_std::mnt6_753::{self, *}; -//! -//! # let cs = ConstraintSystem::::new_ref(); -//! # let mut rng = algebra::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(r1cs_core::ns!(cs, "a"), || Ok(a_native))?; -//! let b = G2Var::new_witness(r1cs_core::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(r1cs_core::ns!(cs, "a_as_constant"), a_native)?; -//! let b_const = G2Var::new_constant(r1cs_core::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 = mnt6_753::PairingVar::prepare_g1(&a)?; -//! let b_prep = mnt6_753::PairingVar::prepare_g2(&b)?; -//! let pairing_result = mnt6_753::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 = mnt6_753::PairingVar::prepare_g1(&a_const)?; -//! let b_prep_const = mnt6_753::PairingVar::prepare_g2(&b_const)?; -//! let pairing_result_const = mnt6_753::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/r1cs-std/src/instantiated/mnt6_753/pairing.rs b/r1cs-std/src/instantiated/mnt6_753/pairing.rs deleted file mode 100644 index c97741b..0000000 --- a/r1cs-std/src/instantiated/mnt6_753/pairing.rs +++ /dev/null @@ -1,9 +0,0 @@ -use algebra::mnt6_753::Parameters; - -/// Specifies the constraints for computing a pairing in the MNT6-753 bilinear group. -pub type PairingVar = crate::pairing::mnt6::PairingVar; - -#[test] -fn test() { - crate::pairing::tests::bilinearity_test::().unwrap() -} diff --git a/r1cs-std/src/instantiated/mod.rs b/r1cs-std/src/instantiated/mod.rs deleted file mode 100644 index 0ca6c2c..0000000 --- a/r1cs-std/src/instantiated/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -#[cfg(feature = "bls12_377")] -pub mod bls12_377; - -#[cfg(feature = "ed_on_bls12_377")] -pub mod ed_on_bls12_377; - -#[cfg(feature = "ed_on_cp6_782")] -pub mod ed_on_cp6_782; - -#[cfg(all(not(feature = "ed_on_cp6_782"), feature = "ed_on_bw6_761"))] -pub(crate) mod ed_on_cp6_782; - -#[cfg(feature = "ed_on_bw6_761")] -pub mod ed_on_bw6_761; - -#[cfg(feature = "ed_on_bn254")] -pub mod ed_on_bn254; - -#[cfg(feature = "ed_on_bls12_381")] -pub mod ed_on_bls12_381; - -#[cfg(feature = "ed_on_mnt4_298")] -pub mod ed_on_mnt4_298; - -#[cfg(feature = "ed_on_mnt4_753")] -pub mod ed_on_mnt4_753; - -#[cfg(feature = "mnt4_298")] -pub mod mnt4_298; - -#[cfg(feature = "mnt4_753")] -pub mod mnt4_753; - -#[cfg(feature = "mnt6_298")] -pub mod mnt6_298; - -#[cfg(feature = "mnt6_753")] -pub mod mnt6_753; diff --git a/r1cs-std/src/lib.rs b/r1cs-std/src/lib.rs deleted file mode 100644 index e017234..0000000 --- a/r1cs-std/src/lib.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! This crate implements common "gadgets" that make -//! programming rank-1 constraint systems easier. -#![cfg_attr(not(feature = "std"), no_std)] -#![deny(unused_import_braces, unused_qualifications, trivial_casts)] -#![deny(trivial_numeric_casts, variant_size_differences, unreachable_pub)] -#![deny(non_shorthand_field_patterns, unused_attributes, unused_imports)] -#![deny(unused_extern_crates, renamed_and_removed_lints, unused_allocation)] -#![deny(unused_comparisons, bare_trait_objects, const_err, unused_must_use)] -#![deny(unused_mut, unused_unsafe, private_in_public, unsafe_code)] -#![deny(missing_docs)] -#![forbid(unsafe_code)] - -#[doc(hidden)] -#[cfg(all(test, not(feature = "std")))] -#[macro_use] -extern crate std; - -#[doc(hidden)] -#[cfg(not(feature = "std"))] -extern crate alloc as ralloc; - -#[doc(hidden)] -#[macro_use] -extern crate algebra; - -#[doc(hidden)] -#[macro_use] -extern crate derivative; - -/// Some utility macros for making downstream impls easier. -#[macro_use] -pub mod macros; - -#[cfg(not(feature = "std"))] -use ralloc::vec::Vec; - -#[cfg(feature = "std")] -use std::vec::Vec; - -use algebra::prelude::Field; - -/// This module implements gadgets related to bit manipulation, such as `Boolean` and `UInt`s. -pub mod bits; -pub use self::bits::*; - -/// This module implements gadgets related to field arithmetic. -pub mod fields; - -/// This module implements gadgets related to group arithmetic, and specifically elliptic curve arithmetic. -pub mod groups; - -mod instantiated; - -#[cfg(feature = "bls12_377")] -pub use instantiated::bls12_377; - -#[cfg(feature = "ed_on_bn254")] -pub use instantiated::ed_on_bn254; - -#[cfg(feature = "ed_on_bls12_377")] -pub use instantiated::ed_on_bls12_377; - -#[cfg(feature = "ed_on_mnt4_298")] -pub use instantiated::ed_on_mnt4_298; - -#[cfg(feature = "ed_on_mnt4_753")] -pub use instantiated::ed_on_mnt4_753; - -#[cfg(feature = "ed_on_cp6_782")] -pub use instantiated::ed_on_cp6_782; - -#[cfg(feature = "ed_on_bw6_761")] -pub use instantiated::ed_on_bw6_761; - -#[cfg(feature = "ed_on_bls12_381")] -pub use instantiated::ed_on_bls12_381; - -#[cfg(feature = "mnt4_298")] -pub use instantiated::mnt4_298; - -#[cfg(feature = "mnt4_753")] -pub use instantiated::mnt4_753; - -#[cfg(feature = "mnt6_298")] -pub use instantiated::mnt6_298; - -#[cfg(feature = "mnt6_753")] -pub use instantiated::mnt6_753; - -/// This module implements gadgets related to computing pairings in bilinear groups. -pub mod pairing; - -/// This module describes a trait for allocating new variables in a constraint system. -pub mod alloc; -/// This module describes a trait for checking equality of variables. -pub mod eq; -/// This module describes traits for conditionally selecting a variable from a list of variables. -pub mod select; - -#[allow(missing_docs)] -pub mod prelude { - pub use crate::{ - alloc::*, - bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget}, - eq::*, - fields::{FieldOpsBounds, FieldVar}, - groups::{CurveVar, GroupOpsBounds}, - instantiated::*, - pairing::PairingVar, - select::*, - R1CSVar, - }; -} - -/// This trait describes some core functionality that is common to high-level variables, -/// such as `Boolean`s, `FieldVar`s, `GroupVar`s, etc. -pub trait R1CSVar { - /// The type of the "native" value that `Self` represents in the constraint system. - type Value: core::fmt::Debug + Eq + Clone; - - /// Returns the underlying `ConstraintSystemRef`. - /// - /// If `self` is a constant value, then this *must* return `r1cs_core::ConstraintSystemRef::None`. - fn cs(&self) -> r1cs_core::ConstraintSystemRef; - - /// Returns `true` if `self` is a circuit-generation-time constant. - fn is_constant(&self) -> bool { - self.cs().is_none() - } - - /// Returns the value that is assigned to `self` in the underlying - /// `ConstraintSystem`. - fn value(&self) -> Result; -} - -impl> R1CSVar for [T] { - type Value = Vec; - - fn cs(&self) -> r1cs_core::ConstraintSystemRef { - let mut result = r1cs_core::ConstraintSystemRef::None; - for var in self { - result = var.cs().or(result); - } - result - } - - fn value(&self) -> Result { - let mut result = Vec::new(); - for var in self { - result.push(var.value()?); - } - Ok(result) - } -} - -impl<'a, F: Field, T: 'a + R1CSVar> R1CSVar for &'a T { - type Value = T::Value; - - fn cs(&self) -> r1cs_core::ConstraintSystemRef { - (*self).cs() - } - - fn value(&self) -> Result { - (*self).value() - } -} - -/// A utility trait to convert `Self` to `Result -pub trait Assignment { - /// Converts `self` to `Result`. - fn get(self) -> Result; -} - -impl Assignment for Option { - fn get(self) -> Result { - self.ok_or(r1cs_core::SynthesisError::AssignmentMissing) - } -} - -/// Specifies how to convert a variable of type `Self` to variables of -/// type `FpVar` -pub trait ToConstraintFieldGadget { - /// Converts `self` to `FpVar` variables. - fn to_constraint_field( - &self, - ) -> Result>, r1cs_core::SynthesisError>; -} diff --git a/r1cs-std/src/pairing/mod.rs b/r1cs-std/src/pairing/mod.rs deleted file mode 100644 index ee2ce84..0000000 --- a/r1cs-std/src/pairing/mod.rs +++ /dev/null @@ -1,183 +0,0 @@ -use crate::prelude::*; -use algebra::{Field, PairingEngine}; -use core::fmt::Debug; -use r1cs_core::SynthesisError; - -/// This module implements pairings for BLS12 bilinear groups. -pub mod bls12; -/// This module implements pairings for MNT4 bilinear groups. -pub mod mnt4; -/// This module implements pairings for MNT6 bilinear groups. -pub mod mnt6; - -/// Specifies the constraints for computing a pairing in the yybilinear group `E`. -pub trait PairingVar::Fq> { - /// An variable representing an element of `G1`. - /// This is the R1CS equivalent of `E::G1Projective`. - type G1Var: CurveVar - + AllocVar - + AllocVar; - - /// An variable representing an element of `G2`. - /// This is the R1CS equivalent of `E::G2Projective`. - type G2Var: CurveVar - + AllocVar - + AllocVar; - - /// An variable representing an element of `GT`. - /// This is the R1CS equivalent of `E::GT`. - type GTVar: FieldVar; - - /// An variable representing cached precomputation that can speed up pairings computations. - /// This is the R1CS equivalent of `E::G1Prepared`. - type G1PreparedVar: ToBytesGadget - + AllocVar - + Clone - + Debug; - /// An variable representing cached precomputation that can speed up pairings computations. - /// This is the R1CS equivalent of `E::G2Prepared`. - type G2PreparedVar: ToBytesGadget - + AllocVar - + Clone - + Debug; - - /// Computes a multi-miller loop between elements - /// of `p` and `q`. - fn miller_loop( - p: &[Self::G1PreparedVar], - q: &[Self::G2PreparedVar], - ) -> Result; - - /// Computes a final exponentiation over `p`. - fn final_exponentiation(p: &Self::GTVar) -> Result; - - /// Computes a pairing over `p` and `q`. - #[tracing::instrument(target = "r1cs")] - fn pairing( - p: Self::G1PreparedVar, - q: Self::G2PreparedVar, - ) -> Result { - let tmp = Self::miller_loop(&[p], &[q])?; - Self::final_exponentiation(&tmp) - } - - /// Computes a product of pairings over the elements in `p` and `q`. - #[must_use] - #[tracing::instrument(target = "r1cs")] - fn product_of_pairings( - p: &[Self::G1PreparedVar], - q: &[Self::G2PreparedVar], - ) -> Result { - let miller_result = Self::miller_loop(p, q)?; - Self::final_exponentiation(&miller_result) - } - - /// Performs the precomputation to generate `Self::G1PreparedVar`. - fn prepare_g1(q: &Self::G1Var) -> Result; - - /// Performs the precomputation to generate `Self::G2PreparedVar`. - fn prepare_g2(q: &Self::G2Var) -> Result; -} - -#[cfg(test)] -pub(crate) mod tests { - use crate::{prelude::*, Vec}; - use algebra::{ - test_rng, BitIteratorLE, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand, - }; - use r1cs_core::{ConstraintSystem, SynthesisError}; - - #[allow(dead_code)] - pub(crate) 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; - println!( - "Preparation 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()])?; - println!( - "ML num constraints: {}", - cs.num_constraints() - ml_constraints - ); - let fe_constraints = cs.num_constraints(); - let ans_g = P::final_exponentiation(&ml_g)?; - println!( - "FE num constraints: {}", - cs.num_constraints() - fe_constraints - ); - 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() { - println!("Unsatisfied: {:?}", cs.which_is_unsatisfied()); - } - - assert!(cs.is_satisfied().unwrap(), "cs is not satisfied"); - Ok(()) - } -} diff --git a/r1cs-std/src/alloc.rs b/src/alloc.rs similarity index 94% rename from r1cs-std/src/alloc.rs rename to src/alloc.rs index 8a5a870..55aa5d2 100644 --- a/r1cs-std/src/alloc.rs +++ b/src/alloc.rs @@ -1,7 +1,7 @@ use crate::Vec; -use algebra::Field; +use ark_ff::Field; +use ark_relations::r1cs::{Namespace, SynthesisError}; use core::borrow::Borrow; -use r1cs_core::{Namespace, SynthesisError}; /// Describes the mode that a variable should be allocated in within /// a `ConstraintSystem`. @@ -22,7 +22,8 @@ pub enum AllocationMode { } impl AllocationMode { - /// Outputs the maximum according to the relation `Constant < Input < Witness`. + /// Outputs the maximum according to the relation `Constant < Input < + /// Witness`. pub fn max(&self, other: Self) -> Self { use AllocationMode::*; match (self, other) { @@ -34,7 +35,8 @@ impl AllocationMode { } } -/// Specifies how variables of type `Self` should be allocated in a `ConstraintSystem`. +/// Specifies how variables of type `Self` should be allocated in a +/// `ConstraintSystem`. pub trait AllocVar where Self: Sized, @@ -59,7 +61,8 @@ where Self::new_variable(cs, || Ok(t), AllocationMode::Constant) } - /// Allocates a new public input of type `Self` in the `ConstraintSystem` `cs`. + /// Allocates a new public input of type `Self` in the `ConstraintSystem` + /// `cs`. #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_input>( cs: impl Into>, @@ -68,7 +71,8 @@ where Self::new_variable(cs, f, AllocationMode::Input) } - /// Allocates a new private witness of type `Self` in the `ConstraintSystem` `cs`. + /// Allocates a new private witness of type `Self` in the `ConstraintSystem` + /// `cs`. #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_witness>( cs: impl Into>, diff --git a/r1cs-std/src/bits/boolean.rs b/src/bits/boolean.rs similarity index 95% rename from r1cs-std/src/bits/boolean.rs rename to src/bits/boolean.rs index f78762e..244ec85 100644 --- a/r1cs-std/src/bits/boolean.rs +++ b/src/bits/boolean.rs @@ -1,8 +1,10 @@ -use algebra::{BitIteratorBE, Field, PrimeField}; +use ark_ff::{BitIteratorBE, Field, PrimeField}; use crate::{fields::fp::FpVar, prelude::*, Assignment, ToConstraintFieldGadget, Vec}; +use ark_relations::r1cs::{ + ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable, +}; use core::borrow::Borrow; -use r1cs_core::{lc, ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable}; /// Represents a variable in the constraint system which is guaranteed /// to be either zero or one. @@ -277,11 +279,11 @@ impl Boolean { /// This *does not* create any new variables or constraints. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let t = Boolean::::TRUE; @@ -308,10 +310,10 @@ impl Boolean { /// /// This *does not* create any new variables or constraints. /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_r1cs_std::prelude::*; /// /// let true_var = Boolean::::TRUE; /// let false_var = Boolean::::FALSE; @@ -329,11 +331,11 @@ impl Boolean { /// /// This *does not* create any new variables or constraints. /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -364,11 +366,11 @@ impl Boolean { /// *does not* create any constraints or variables. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -406,11 +408,11 @@ impl Boolean { /// *does not* create any constraints or variables. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -447,11 +449,11 @@ impl Boolean { /// *does not* create any constraints or variables. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -488,11 +490,11 @@ impl Boolean { /// Outputs `bits[0] & bits[1] & ... & bits.last().unwrap()`. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -525,11 +527,11 @@ impl Boolean { /// Outputs `bits[0] | bits[1] | ... | bits.last().unwrap()`. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -563,11 +565,11 @@ impl Boolean { /// Outputs `(bits[0] & bits[1] & ... & bits.last().unwrap()).not()`. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -590,7 +592,8 @@ impl Boolean { /// Enforces that `Self::kary_nand(bits).is_eq(&Boolean::TRUE)`. /// - /// Informally, this means that at least one element in `bits` must be `false`. + /// Informally, this means that at least one element in `bits` must be + /// `false`. #[tracing::instrument(target = "r1cs")] fn enforce_kary_nand(bits: &[Self]) -> Result<(), SynthesisError> { use Boolean::*; @@ -605,9 +608,10 @@ impl Boolean { } } - /// Enforces that `bits`, when interpreted as a integer, is less than `F::characteristic()`, - /// That is, interpret bits as a little-endian integer, and enforce that this integer - /// is "in the field Z_p", where `p = F::characteristic()` . + /// Enforces that `bits`, when interpreted as a integer, is less than + /// `F::characteristic()`, That is, interpret bits as a little-endian + /// integer, and enforce that this integer is "in the field Z_p", where + /// `p = F::characteristic()` . #[tracing::instrument(target = "r1cs")] pub fn enforce_in_field_le(bits: &[Self]) -> Result<(), SynthesisError> { // `bits` < F::characteristic() <==> `bits` <= F::characteristic() -1 @@ -681,15 +685,16 @@ impl Boolean { Ok(current_run) } - /// Conditionally selects one of `first` and `second` based on the value of `self`: + /// Conditionally selects one of `first` and `second` based on the value of + /// `self`: /// - /// If `self.is_eq(&Boolean::TRUE)`, this outputs `first`; else, it outputs `second`. - /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// If `self.is_eq(&Boolean::TRUE)`, this outputs `first`; else, it outputs + /// `second`. ``` + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// @@ -865,7 +870,6 @@ impl CondSelectGadget for Boolean { Ok(if cond { a.value()? } else { b.value()? }) })? .into(); - // // a = self; b = other; c = cond; // // r = c * a + (1 - c) * b @@ -901,10 +905,9 @@ impl CondSelectGadget for Boolean { mod test { use super::{AllocatedBit, Boolean}; use crate::prelude::*; - use algebra::{ - bls12_381::Fr, BitIteratorBE, BitIteratorLE, Field, One, PrimeField, UniformRand, Zero, - }; - use r1cs_core::{ConstraintSystem, Namespace, SynthesisError}; + use ark_ff::{BitIteratorBE, BitIteratorLE, Field, One, PrimeField, UniformRand, Zero}; + use ark_relations::r1cs::{ConstraintSystem, Namespace, SynthesisError}; + use ark_test_curves::bls12_381::Fr; use rand::SeedableRng; use rand_xorshift::XorShiftRng; @@ -1093,7 +1096,7 @@ mod test { } let false_cond = - Boolean::new_witness(r1cs_core::ns!(cs, "cond"), || Ok(false))?; + Boolean::new_witness(ark_relations::ns!(cs, "cond"), || Ok(false))?; a.conditional_enforce_equal(&b, &false_cond)?; assert!(cs.is_satisfied().unwrap()); @@ -1170,8 +1173,8 @@ mod test { for second_operand in VARIANTS.iter().cloned() { let cs = ConstraintSystem::::new_ref(); - let a = construct(r1cs_core::ns!(cs, "a"), first_operand)?; - let b = construct(r1cs_core::ns!(cs, "b"), second_operand)?; + let a = construct(ark_relations::ns!(cs, "a"), first_operand)?; + let b = construct(ark_relations::ns!(cs, "b"), second_operand)?; let c = Boolean::xor(&a, &b)?; assert!(cs.is_satisfied().unwrap()); @@ -1300,9 +1303,9 @@ mod test { for second_operand in VARIANTS.iter().cloned() { let cs = ConstraintSystem::::new_ref(); - let cond = construct(r1cs_core::ns!(cs, "cond"), condition)?; - let a = construct(r1cs_core::ns!(cs, "a"), first_operand)?; - let b = construct(r1cs_core::ns!(cs, "b"), second_operand)?; + let cond = construct(ark_relations::ns!(cs, "cond"), condition)?; + let a = construct(ark_relations::ns!(cs, "a"), first_operand)?; + let b = construct(ark_relations::ns!(cs, "b"), second_operand)?; let c = cond.select(&a, &b)?; assert!( @@ -1332,8 +1335,8 @@ mod test { for second_operand in VARIANTS.iter().cloned() { let cs = ConstraintSystem::::new_ref(); - let a = construct(r1cs_core::ns!(cs, "a"), first_operand)?; - let b = construct(r1cs_core::ns!(cs, "b"), second_operand)?; + let a = construct(ark_relations::ns!(cs, "a"), first_operand)?; + let b = construct(ark_relations::ns!(cs, "b"), second_operand)?; let c = a.or(&b)?; assert!(cs.is_satisfied().unwrap()); @@ -1453,8 +1456,8 @@ mod test { for second_operand in VARIANTS.iter().cloned() { let cs = ConstraintSystem::::new_ref(); - let a = construct(r1cs_core::ns!(cs, "a"), first_operand)?; - let b = construct(r1cs_core::ns!(cs, "b"), second_operand)?; + let a = construct(ark_relations::ns!(cs, "a"), first_operand)?; + let b = construct(ark_relations::ns!(cs, "b"), second_operand)?; let c = a.and(&b)?; assert!(cs.is_satisfied().unwrap()); diff --git a/r1cs-std/src/bits/mod.rs b/src/bits/mod.rs similarity index 94% rename from r1cs-std/src/bits/mod.rs rename to src/bits/mod.rs index 745ae5c..ccedc02 100644 --- a/r1cs-std/src/bits/mod.rs +++ b/src/bits/mod.rs @@ -2,15 +2,15 @@ use crate::{ bits::{boolean::Boolean, uint8::UInt8}, Vec, }; -use algebra::Field; -use r1cs_core::SynthesisError; +use ark_ff::Field; +use ark_relations::r1cs::SynthesisError; /// This module contains `Boolean`, a R1CS equivalent of the `bool` type. pub mod boolean; /// This module contains `UInt8`, a R1CS equivalent of the `u8` type. pub mod uint8; -/// This module contains a macro for generating `UIntN` types, which are R1CS equivalents of -/// `N`-bit unsigned integers. +/// This module contains a macro for generating `UIntN` types, which are R1CS +/// equivalents of `N`-bit unsigned integers. #[macro_use] pub mod uint; @@ -18,14 +18,16 @@ make_uint!(UInt16, 16, u16, uint16, "16"); make_uint!(UInt32, 32, u32, uint32, "32"); make_uint!(UInt64, 64, u64, uint64, "64"); -/// Specifies constraints for conversion to a little-endian bit representation of `self`. +/// Specifies constraints for conversion to a little-endian bit representation +/// of `self`. pub trait ToBitsGadget { /// Outputs the canonical little-endian bit-wise representation of `self`. /// /// This is the correct default for 99% of use cases. fn to_bits_le(&self) -> Result>, SynthesisError>; - /// Outputs a possibly non-unique little-endian bit-wise representation of `self`. + /// Outputs a possibly non-unique little-endian bit-wise representation of + /// `self`. /// /// If you're not absolutely certain that your usecase can get away with a /// non-canonical representation, please use `self.to_bits()` instead. @@ -40,7 +42,8 @@ pub trait ToBitsGadget { Ok(res) } - /// Outputs a possibly non-unique big-endian bit-wise representation of `self`. + /// Outputs a possibly non-unique big-endian bit-wise representation of + /// `self`. fn to_non_unique_bits_be(&self) -> Result>, SynthesisError> { let mut res = self.to_non_unique_bits_le()?; res.reverse(); @@ -89,7 +92,8 @@ where } } -/// Specifies constraints for conversion to a little-endian byte representation of `self`. +/// Specifies constraints for conversion to a little-endian byte representation +/// of `self`. pub trait ToBytesGadget { /// Outputs a canonical, little-endian, byte decomposition of `self`. /// diff --git a/r1cs-std/src/bits/uint.rs b/src/bits/uint.rs similarity index 97% rename from r1cs-std/src/bits/uint.rs rename to src/bits/uint.rs index df0c06a..2bafeb2 100644 --- a/r1cs-std/src/bits/uint.rs +++ b/src/bits/uint.rs @@ -6,12 +6,12 @@ macro_rules! make_uint { #[doc = $native_doc_name] #[doc = "`type."] pub mod $mod_name { - use algebra::{Field, FpParameters, PrimeField}; + use ark_ff::{Field, FpParameters, PrimeField}; use core::borrow::Borrow; use core::convert::TryFrom; - use r1cs_core::{ - lc, ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable, + use ark_relations::r1cs::{ + ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable, }; use crate::{ @@ -357,8 +357,8 @@ macro_rules! make_uint { mod test { use super::$name; use crate::{bits::boolean::Boolean, prelude::*, Vec}; - use algebra::bls12_381::Fr; - use r1cs_core::{ConstraintSystem, SynthesisError}; + use ark_test_curves::bls12_381::Fr; + use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -481,10 +481,10 @@ macro_rules! make_uint { let mut expected = (a ^ b).wrapping_add(c).wrapping_add(d); - let a_bit = $name::new_witness(r1cs_core::ns!(cs, "a_bit"), || Ok(a))?; + let a_bit = $name::new_witness(ark_relations::ns!(cs, "a_bit"), || Ok(a))?; let b_bit = $name::constant(b); let c_bit = $name::constant(c); - let d_bit = $name::new_witness(r1cs_core::ns!(cs, "d_bit"), || Ok(d))?; + let d_bit = $name::new_witness(ark_relations::ns!(cs, "d_bit"), || Ok(d))?; let r = a_bit.xor(&b_bit).unwrap(); let r = $name::addmany(&[r, c_bit, d_bit]).unwrap(); diff --git a/r1cs-std/src/bits/uint8.rs b/src/bits/uint8.rs similarity index 87% rename from r1cs-std/src/bits/uint8.rs rename to src/bits/uint8.rs index 6facd9b..bc50eb5 100644 --- a/r1cs-std/src/bits/uint8.rs +++ b/src/bits/uint8.rs @@ -1,7 +1,6 @@ -use algebra::Field; -use algebra::{FpParameters, PrimeField, ToConstraintField}; +use ark_ff::{Field, FpParameters, PrimeField, ToConstraintField}; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; +use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use crate::{fields::fp::AllocatedFp, prelude::*, Assignment, Vec}; use core::borrow::Borrow; @@ -41,11 +40,11 @@ impl UInt8 { /// /// This *does not* create any new variables or constraints. /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let var = vec![UInt8::new_witness(cs.clone(), || Ok(2))?]; @@ -69,11 +68,11 @@ impl UInt8 { /// This *does not* create new variables or constraints. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let var = UInt8::new_witness(cs.clone(), || Ok(2))?; @@ -116,19 +115,19 @@ impl UInt8 { } /// Allocates a slice of `u8`'s as public inputs by first packing them into - /// elements of `F`, (thus reducing the number of input allocations), allocating - /// these elements as public inputs, and then converting these field variables - /// `FpVar` variables back into bytes. + /// elements of `F`, (thus reducing the number of input allocations), + /// allocating these elements as public inputs, and then converting + /// these field variables `FpVar` variables back into bytes. /// /// From a user perspective, this trade-off adds constraints, but improves /// verifier time and verification key size. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let two = UInt8::new_witness(cs.clone(), || Ok(2))?; @@ -177,11 +176,11 @@ impl UInt8 { /// `UInt8`. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let var = UInt8::new_witness(cs.clone(), || Ok(128))?; @@ -222,11 +221,11 @@ impl UInt8 { /// *does not* create any constraints or variables. /// /// ``` - /// # fn main() -> Result<(), r1cs_core::SynthesisError> { + /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> { /// // We'll use the BLS12-381 scalar field for our constraints. - /// use algebra::bls12_381::Fr; - /// use r1cs_core::*; - /// use r1cs_std::prelude::*; + /// use ark_test_curves::bls12_381::Fr; + /// use ark_relations::r1cs::*; + /// use ark_r1cs_std::prelude::*; /// /// let cs = ConstraintSystem::::new_ref(); /// let a = UInt8::new_witness(cs.clone(), || Ok(16))?; @@ -313,8 +312,8 @@ impl AllocVar for UInt8 { mod test { use super::UInt8; use crate::{prelude::*, Vec}; - use algebra::bls12_381::Fr; - use r1cs_core::{ConstraintSystem, SynthesisError}; + use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; + use ark_test_curves::bls12_381::Fr; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -322,7 +321,8 @@ mod test { fn test_uint8_from_bits_to_bits() -> Result<(), SynthesisError> { let cs = ConstraintSystem::::new_ref(); let byte_val = 0b01110001; - let byte = UInt8::new_witness(r1cs_core::ns!(cs, "alloc value"), || Ok(byte_val)).unwrap(); + let byte = + UInt8::new_witness(ark_relations::ns!(cs, "alloc value"), || Ok(byte_val)).unwrap(); let bits = byte.to_bits_le()?; for (i, bit) in bits.iter().enumerate() { assert_eq!(bit.value()?, (byte_val >> i) & 1 == 1) @@ -334,7 +334,8 @@ mod test { fn test_uint8_new_input_vec() -> Result<(), SynthesisError> { let cs = ConstraintSystem::::new_ref(); let byte_vals = (64u8..128u8).collect::>(); - let bytes = UInt8::new_input_vec(r1cs_core::ns!(cs, "alloc value"), &byte_vals).unwrap(); + let bytes = + UInt8::new_input_vec(ark_relations::ns!(cs, "alloc value"), &byte_vals).unwrap(); dbg!(bytes.value())?; for (native, variable) in byte_vals.into_iter().zip(bytes) { let bits = variable.to_bits_le()?; @@ -395,9 +396,9 @@ mod test { let mut expected = a ^ b ^ c; - let a_bit = UInt8::new_witness(r1cs_core::ns!(cs, "a_bit"), || Ok(a)).unwrap(); + let a_bit = UInt8::new_witness(ark_relations::ns!(cs, "a_bit"), || Ok(a)).unwrap(); let b_bit = UInt8::constant(b); - let c_bit = UInt8::new_witness(r1cs_core::ns!(cs, "c_bit"), || Ok(c)).unwrap(); + let c_bit = UInt8::new_witness(ark_relations::ns!(cs, "c_bit"), || Ok(c)).unwrap(); let r = a_bit.xor(&b_bit).unwrap(); let r = r.xor(&c_bit).unwrap(); diff --git a/r1cs-std/src/eq.rs b/src/eq.rs similarity index 85% rename from r1cs-std/src/eq.rs rename to src/eq.rs index 80798ae..f118461 100644 --- a/r1cs-std/src/eq.rs +++ b/src/eq.rs @@ -1,24 +1,28 @@ use crate::{prelude::*, Vec}; -use algebra::Field; -use r1cs_core::SynthesisError; +use ark_ff::Field; +use ark_relations::r1cs::SynthesisError; -/// Specifies how to generate constraints that check for equality for two variables of type `Self`. +/// Specifies how to generate constraints that check for equality for two +/// variables of type `Self`. pub trait EqGadget { - /// Output a `Boolean` value representing whether `self.value() == other.value()`. + /// Output a `Boolean` value representing whether `self.value() == + /// other.value()`. fn is_eq(&self, other: &Self) -> Result, SynthesisError>; - /// Output a `Boolean` value representing whether `self.value() != other.value()`. + /// Output a `Boolean` value representing whether `self.value() != + /// other.value()`. /// /// By default, this is defined as `self.is_eq(other)?.not()`. fn is_neq(&self, other: &Self) -> Result, SynthesisError> { Ok(self.is_eq(other)?.not()) } - /// If `should_enforce == true`, enforce that `self` and `other` are equal; else, - /// enforce a vacuously true statement. + /// If `should_enforce == true`, enforce that `self` and `other` are equal; + /// else, enforce a vacuously true statement. /// - /// A safe default implementation is provided that generates the following constraints: - /// `self.is_eq(other)?.conditional_enforce_equal(&Boolean::TRUE, should_enforce)`. + /// A safe default implementation is provided that generates the following + /// constraints: `self.is_eq(other)?.conditional_enforce_equal(&Boolean: + /// :TRUE, should_enforce)`. /// /// More efficient specialized implementation may be possible; implementors /// are encouraged to carefully analyze the efficiency and safety of these. @@ -34,8 +38,9 @@ pub trait EqGadget { /// Enforce that `self` and `other` are equal. /// - /// A safe default implementation is provided that generates the following constraints: - /// `self.conditional_enforce_equal(other, &Boolean::TRUE)`. + /// A safe default implementation is provided that generates the following + /// constraints: `self.conditional_enforce_equal(other, + /// &Boolean::TRUE)`. /// /// More efficient specialized implementation may be possible; implementors /// are encouraged to carefully analyze the efficiency and safety of these. @@ -44,11 +49,12 @@ pub trait EqGadget { self.conditional_enforce_equal(other, &Boolean::constant(true)) } - /// If `should_enforce == true`, enforce that `self` and `other` are *not* equal; else, - /// enforce a vacuously true statement. + /// If `should_enforce == true`, enforce that `self` and `other` are *not* + /// equal; else, enforce a vacuously true statement. /// - /// A safe default implementation is provided that generates the following constraints: - /// `self.is_neq(other)?.conditional_enforce_equal(&Boolean::TRUE, should_enforce)`. + /// A safe default implementation is provided that generates the following + /// constraints: `self.is_neq(other)?.conditional_enforce_equal(& + /// Boolean::TRUE, should_enforce)`. /// /// More efficient specialized implementation may be possible; implementors /// are encouraged to carefully analyze the efficiency and safety of these. @@ -64,8 +70,9 @@ pub trait EqGadget { /// Enforce that `self` and `other` are *not* equal. /// - /// A safe default implementation is provided that generates the following constraints: - /// `self.conditional_enforce_not_equal(other, &Boolean::TRUE)`. + /// A safe default implementation is provided that generates the following + /// constraints: `self.conditional_enforce_not_equal(other, + /// &Boolean::TRUE)`. /// /// More efficient specialized implementation may be possible; implementors /// are encouraged to carefully analyze the efficiency and safety of these. diff --git a/r1cs-std/src/fields/cubic_extension.rs b/src/fields/cubic_extension.rs similarity index 96% rename from r1cs-std/src/fields/cubic_extension.rs rename to src/fields/cubic_extension.rs index 0a96bf2..eb3e3d1 100644 --- a/r1cs-std/src/fields/cubic_extension.rs +++ b/src/fields/cubic_extension.rs @@ -1,19 +1,18 @@ -use algebra::{ +use ark_ff::{ fields::{CubicExtField, CubicExtParameters, Field}, Zero, }; +use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use core::{borrow::Borrow, marker::PhantomData}; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::fields::fp::FpVar; use crate::{ - fields::{FieldOpsBounds, FieldVar}, + fields::{fp::FpVar, FieldOpsBounds, FieldVar}, prelude::*, ToConstraintFieldGadget, Vec, }; /// This struct is the `R1CS` equivalent of the cubic extension field type -/// in `algebra-core`, i.e. `algebra_core::CubicExtField`. +/// in `ark-ff`, i.e. `ark_ff::CubicExtField`. #[derive(Derivative)] #[derivative(Debug(bound = "BF: core::fmt::Debug"), Clone(bound = "BF: Clone"))] #[must_use] @@ -31,14 +30,16 @@ where _params: PhantomData

, } -/// This trait describes parameters that are used to implement arithmetic for `CubicExtVar`. +/// This trait describes parameters that are used to implement arithmetic for +/// `CubicExtVar`. pub trait CubicExtVarParams>: CubicExtParameters where for<'a> &'a BF: FieldOpsBounds<'a, Self::BaseField, BF>, { - /// Multiply the base field of the `CubicExtVar` by the appropriate Frobenius coefficient. - /// This is equivalent to `Self::mul_base_field_by_frob_coeff(c1, c2, power)`. + /// Multiply the base field of the `CubicExtVar` by the appropriate + /// Frobenius coefficient. This is equivalent to + /// `Self::mul_base_field_by_frob_coeff(c1, c2, power)`. fn mul_base_field_vars_by_frob_coeff(c1: &mut BF, c2: &mut BF, power: usize); } @@ -58,8 +59,8 @@ where } } - /// Multiplies a variable of the base field by the cubic nonresidue `P::NONRESIDUE` that - /// is used to construct the extension field. + /// Multiplies a variable of the base field by the cubic nonresidue + /// `P::NONRESIDUE` that is used to construct the extension field. #[inline] pub fn mul_base_field_by_nonresidue(fe: &BF) -> Result { Ok(fe * P::NONRESIDUE) @@ -570,9 +571,9 @@ where ), }; - let c0 = BF::new_variable(r1cs_core::ns!(cs, "c0"), || c0, mode)?; - let c1 = BF::new_variable(r1cs_core::ns!(cs, "c1"), || c1, mode)?; - let c2 = BF::new_variable(r1cs_core::ns!(cs, "c2"), || c2, mode)?; + let c0 = BF::new_variable(ark_relations::ns!(cs, "c0"), || c0, mode)?; + let c1 = BF::new_variable(ark_relations::ns!(cs, "c1"), || c1, mode)?; + let c2 = BF::new_variable(ark_relations::ns!(cs, "c2"), || c2, mode)?; Ok(Self::new(c0, c1, c2)) } } diff --git a/r1cs-std/src/fields/fp/cmp.rs b/src/fields/fp/cmp.rs similarity index 83% rename from r1cs-std/src/fields/fp/cmp.rs rename to src/fields/fp/cmp.rs index e346f9b..dcdf036 100644 --- a/r1cs-std/src/fields/fp/cmp.rs +++ b/src/fields/fp/cmp.rs @@ -4,16 +4,16 @@ use crate::{ prelude::*, ToBitsGadget, }; -use algebra::PrimeField; +use ark_ff::PrimeField; +use ark_relations::r1cs::{SynthesisError, Variable}; use core::cmp::Ordering; -use r1cs_core::{lc, SynthesisError, Variable}; impl FpVar { /// This function enforces the ordering between `self` and `other`. The /// constraint system will not be satisfied otherwise. If `self` should - /// also be checked for equality, e.g. `self <= other` instead of `self < other`, set - /// `should_also_check_quality` to `true`. This variant verifies `self` and `other` - /// are `<= (p-1)/2`. + /// also be checked for equality, e.g. `self <= other` instead of `self < + /// other`, set `should_also_check_quality` to `true`. This variant + /// verifies `self` and `other` are `<= (p-1)/2`. #[tracing::instrument(target = "r1cs")] pub fn enforce_cmp( &self, @@ -27,9 +27,10 @@ impl FpVar { /// This function enforces the ordering between `self` and `other`. The /// constraint system will not be satisfied otherwise. If `self` should - /// also be checked for equality, e.g. `self <= other` instead of `self < other`, set - /// `should_also_check_quality` to `true`. This variant assumes `self` and `other` - /// are `<= (p-1)/2` and does not generate constraints to verify that. + /// also be checked for equality, e.g. `self <= other` instead of `self < + /// other`, set `should_also_check_quality` to `true`. This variant + /// assumes `self` and `other` are `<= (p-1)/2` and does not generate + /// constraints to verify that. #[tracing::instrument(target = "r1cs")] pub fn enforce_cmp_unchecked( &self, @@ -41,12 +42,12 @@ impl FpVar { left.enforce_smaller_than_unchecked(&right) } - /// This function checks the ordering between `self` and `other`. It outputs self - /// `Boolean` that contains the result - `1` if true, `0` otherwise. The - /// constraint system will be satisfied in any case. If `self` should - /// also be checked for equality, e.g. `self <= other` instead of `self < other`, set - /// `should_also_check_quality` to `true`. This variant verifies `self` and `other` - /// are `<= (p-1)/2`. + /// This function checks the ordering between `self` and `other`. It outputs + /// self `Boolean` that contains the result - `1` if true, `0` + /// otherwise. The constraint system will be satisfied in any case. If + /// `self` should also be checked for equality, e.g. `self <= other` + /// instead of `self < other`, set `should_also_check_quality` to + /// `true`. This variant verifies `self` and `other` are `<= (p-1)/2`. #[tracing::instrument(target = "r1cs")] pub fn is_cmp( &self, @@ -58,12 +59,13 @@ impl FpVar { left.is_smaller_than(&right) } - /// This function checks the ordering between `self` and `other`. It outputs a - /// `Boolean` that contains the result - `1` if true, `0` otherwise. The - /// constraint system will be satisfied in any case. If `self` should - /// also be checked for equality, e.g. `self <= other` instead of `self < other`, set - /// `should_also_check_quality` to `true`. This variant assumes `self` and `other` - /// are `<= (p-1)/2` and does not generate constraints to verify that. + /// This function checks the ordering between `self` and `other`. It outputs + /// a `Boolean` that contains the result - `1` if true, `0` otherwise. + /// The constraint system will be satisfied in any case. If `self` + /// should also be checked for equality, e.g. `self <= other` instead of + /// `self < other`, set `should_also_check_quality` to `true`. This + /// variant assumes `self` and `other` are `<= (p-1)/2` and does not + /// generate constraints to verify that. #[tracing::instrument(target = "r1cs")] pub fn is_cmp_unchecked( &self, @@ -109,17 +111,17 @@ impl FpVar { Ok(()) } - /// Helper function to check `self < other` and output a result bit. This function - /// verifies `self` and `other` are `<= (p-1)/2`. + /// Helper function to check `self < other` and output a result bit. This + /// function verifies `self` and `other` are `<= (p-1)/2`. fn is_smaller_than(&self, other: &FpVar) -> Result, SynthesisError> { self.enforce_smaller_or_equal_than_mod_minus_one_div_two()?; other.enforce_smaller_or_equal_than_mod_minus_one_div_two()?; self.is_smaller_than_unchecked(other) } - /// Helper function to check `self < other` and output a result bit. This function - /// assumes `self` and `other` are `<= (p-1)/2` and does not generate constraints - /// to verify that. + /// Helper function to check `self < other` and output a result bit. This + /// function assumes `self` and `other` are `<= (p-1)/2` and does not + /// generate constraints to verify that. fn is_smaller_than_unchecked(&self, other: &FpVar) -> Result, SynthesisError> { Ok((self - other) .double()? @@ -129,16 +131,17 @@ impl FpVar { .clone()) } - /// Helper function to enforce `self < other`. This function verifies `self` and `other` - /// are `<= (p-1)/2`. + /// Helper function to enforce `self < other`. This function verifies `self` + /// and `other` are `<= (p-1)/2`. fn enforce_smaller_than(&self, other: &FpVar) -> Result<(), SynthesisError> { self.enforce_smaller_or_equal_than_mod_minus_one_div_two()?; other.enforce_smaller_or_equal_than_mod_minus_one_div_two()?; self.enforce_smaller_than_unchecked(other) } - /// Helper function to enforce `self < other`. This function assumes `self` and `other` - /// are `<= (p-1)/2` and does not generate constraints to verify that. + /// Helper function to enforce `self < other`. This function assumes `self` + /// and `other` are `<= (p-1)/2` and does not generate constraints to + /// verify that. fn enforce_smaller_than_unchecked(&self, other: &FpVar) -> Result<(), SynthesisError> { let is_smaller_than = self.is_smaller_than_unchecked(other)?; let lc_one = lc!() + Variable::One; @@ -155,8 +158,9 @@ mod test { use std::cmp::Ordering; use crate::{alloc::AllocVar, fields::fp::FpVar}; - use algebra::{bls12_381::Fr, PrimeField, UniformRand}; - use r1cs_core::ConstraintSystem; + use ark_ff::{PrimeField, UniformRand}; + use ark_relations::r1cs::ConstraintSystem; + use ark_test_curves::bls12_381::Fr; #[test] fn test_cmp() { diff --git a/r1cs-std/src/fields/fp/mod.rs b/src/fields/fp/mod.rs similarity index 96% rename from r1cs-std/src/fields/fp/mod.rs rename to src/fields/fp/mod.rs index 1fa2266..f6f484b 100644 --- a/r1cs-std/src/fields/fp/mod.rs +++ b/src/fields/fp/mod.rs @@ -1,10 +1,15 @@ -use algebra::{BigInteger, FpParameters, PrimeField}; -use r1cs_core::{lc, ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable}; +use ark_ff::{BigInteger, FpParameters, PrimeField}; +use ark_relations::r1cs::{ + ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable, +}; use core::borrow::Borrow; -use crate::fields::{FieldOpsBounds, FieldVar}; -use crate::{prelude::*, Assignment, ToConstraintFieldGadget, Vec}; +use crate::{ + fields::{FieldOpsBounds, FieldVar}, + prelude::*, + Assignment, ToConstraintFieldGadget, Vec, +}; mod cmp; @@ -21,8 +26,8 @@ pub struct AllocatedFp { } impl AllocatedFp { - /// Constructs a new `AllocatedFp` from a (optional) value, a low-level Variable, - /// and a `ConstraintSystemRef`. + /// Constructs a new `AllocatedFp` from a (optional) value, a low-level + /// Variable, and a `ConstraintSystemRef`. pub fn new(value: Option, variable: Variable, cs: ConstraintSystemRef) -> Self { Self { value, @@ -88,7 +93,8 @@ impl<'a, F: PrimeField> FieldOpsBounds<'a, F, Self> for FpVar {} impl<'a, F: PrimeField> FieldOpsBounds<'a, F, FpVar> for &'a FpVar {} impl AllocatedFp { - /// Constructs `Self` from a `Boolean`: if `other` is false, this outputs `zero`, else it outputs `one`. + /// Constructs `Self` from a `Boolean`: if `other` is false, this outputs + /// `zero`, else it outputs `one`. pub fn from(other: Boolean) -> Self { let cs = other.cs(); let variable = cs.new_lc(other.lc()).unwrap(); @@ -307,7 +313,8 @@ impl AllocatedFp { // ---------------------- // constraint 1: // (self - other) * multiplier = is_not_equal - // => (non_zero) * multiplier = 1 (satisfied, because multiplier = 1/(self - other) + // => (non_zero) * multiplier = 1 (satisfied, because multiplier = 1/(self - + // other) // // constraint 2: // (self - other) * not(is_not_equal) = 0 @@ -398,8 +405,8 @@ impl AllocatedFp { } } -/****************************************************************************/ -/****************************************************************************/ +/// ************************************************************************* +/// ************************************************************************* impl ToBitsGadget for AllocatedFp { /// Outputs the unique bit-wise decomposition of `self` in *little-endian* @@ -417,7 +424,7 @@ impl ToBitsGadget for AllocatedFp { #[tracing::instrument(target = "r1cs")] fn to_non_unique_bits_le(&self) -> Result>, SynthesisError> { let cs = self.cs.clone(); - use algebra::BitIteratorBE; + use ark_ff::BitIteratorBE; let mut bits = if let Some(value) = self.value { let field_char = BitIteratorBE::new(F::characteristic()); let bits: Vec<_> = BitIteratorBE::new(value.into_repr()) @@ -740,9 +747,6 @@ impl FieldVar for FpVar { } } -/****************************************************************************/ -/****************************************************************************/ - impl_ops!( FpVar, F, @@ -807,8 +811,8 @@ impl_ops!( F: PrimeField ); -/****************************************************************************/ -/****************************************************************************/ +/// ************************************************************************* +/// ************************************************************************* impl EqGadget for FpVar { #[tracing::instrument(target = "r1cs")] @@ -870,7 +874,7 @@ impl ToBitsGadget for FpVar { #[tracing::instrument(target = "r1cs")] fn to_non_unique_bits_le(&self) -> Result>, SynthesisError> { - use algebra::BitIteratorLE; + use ark_ff::BitIteratorLE; match self { Self::Constant(c) => Ok(BitIteratorLE::without_trailing_zeros(&c.into_repr()) .map(Boolean::constant) @@ -886,7 +890,7 @@ impl ToBytesGadget for FpVar { #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { match self { - Self::Constant(c) => Ok(UInt8::constant_vec(&to_bytes![c].unwrap())), + Self::Constant(c) => Ok(UInt8::constant_vec(&ark_ff::to_bytes![c].unwrap())), Self::Var(v) => v.to_bytes(), } } @@ -894,7 +898,7 @@ impl ToBytesGadget for FpVar { #[tracing::instrument(target = "r1cs")] fn to_non_unique_bytes(&self) -> Result>, SynthesisError> { match self { - Self::Constant(c) => Ok(UInt8::constant_vec(&to_bytes![c].unwrap())), + Self::Constant(c) => Ok(UInt8::constant_vec(&ark_ff::to_bytes![c].unwrap())), Self::Var(v) => v.to_non_unique_bytes(), } } @@ -925,7 +929,7 @@ impl CondSelectGadget for FpVar { // cond * t + (1 - cond) * f Ok(is.mul_constant(*t).add(¬.mul_constant(*f)).into()) } - (_, _) => { + (..) => { let cs = cond.cs(); let true_value = match true_value { Self::Constant(f) => AllocatedFp::new_constant(cs.clone(), f)?, diff --git a/r1cs-std/src/fields/fp12.rs b/src/fields/fp12.rs similarity index 94% rename from r1cs-std/src/fields/fp12.rs rename to src/fields/fp12.rs index aa5a95f..3f60c20 100644 --- a/r1cs-std/src/fields/fp12.rs +++ b/src/fields/fp12.rs @@ -1,10 +1,10 @@ use crate::fields::{fp2::Fp2Var, fp6_3over2::Fp6Var, quadratic_extension::*, FieldVar}; -use algebra::fields::{fp12_2over3over2::*, fp6_3over2::Fp6Parameters, Field, QuadExtParameters}; -use r1cs_core::SynthesisError; +use ark_ff::fields::{fp12_2over3over2::*, fp6_3over2::Fp6Parameters, Field, QuadExtParameters}; +use ark_relations::r1cs::SynthesisError; /// A degree-12 extension field constructed as the tower of a /// quadratic extension over a cubic extension over a quadratic extension field. -/// This is the R1CS equivalent of `algebra_core::fp12_2over3over2::Fp12

`. +/// This is the R1CS equivalent of `ark_ff::fp12_2over3over2::Fp12

`. pub type Fp12Var

= QuadExtVar::Fp6Params>, Fp12ParamsWrapper

>; type Fp2Params

= <

::Fp6Params as Fp6Parameters>::Fp2Params; @@ -18,7 +18,8 @@ impl QuadExtVarParams> for Fp12ParamsWra } impl Fp12Var

{ - /// Multiplies by a sparse element of the form `(c0 = (c0, c1, 0), c1 = (0, d1, 0))`. + /// Multiplies by a sparse element of the form `(c0 = (c0, c1, 0), c1 = (0, + /// d1, 0))`. #[inline] pub fn mul_by_014( &self, @@ -34,7 +35,8 @@ impl Fp12Var

{ Ok(Self::new(new_c0, new_c1)) } - /// Multiplies by a sparse element of the form `(c0 = (c0, 0, 0), c1 = (d0, d1, 0))`. + /// Multiplies by a sparse element of the form `(c0 = (c0, 0, 0), c1 = (d0, + /// d1, 0))`. #[inline] pub fn mul_by_034( &self, @@ -141,7 +143,7 @@ impl Fp12Var

{ &self, exponent: impl AsRef<[u64]>, ) -> Result { - use algebra::biginteger::arithmetic::find_wnaf; + use ark_ff::biginteger::arithmetic::find_wnaf; let mut res = Self::one(); let self_inverse = self.unitary_inverse()?; diff --git a/r1cs-std/src/fields/fp2.rs b/src/fields/fp2.rs similarity index 77% rename from r1cs-std/src/fields/fp2.rs rename to src/fields/fp2.rs index 7a358ad..f1183df 100644 --- a/r1cs-std/src/fields/fp2.rs +++ b/src/fields/fp2.rs @@ -1,8 +1,8 @@ use crate::fields::{fp::FpVar, quadratic_extension::*}; -use algebra::fields::{Fp2Parameters, Fp2ParamsWrapper, QuadExtParameters}; +use ark_ff::fields::{Fp2Parameters, Fp2ParamsWrapper, QuadExtParameters}; /// A quadratic extension field constructed over a prime field. -/// This is the R1CS equivalent of `algebra_core::Fp2

`. +/// This is the R1CS equivalent of `ark_ff::Fp2

`. pub type Fp2Var

= QuadExtVar::Fp>, Fp2ParamsWrapper

>; impl QuadExtVarParams> for Fp2ParamsWrapper

{ diff --git a/r1cs-std/src/fields/fp3.rs b/src/fields/fp3.rs similarity index 81% rename from r1cs-std/src/fields/fp3.rs rename to src/fields/fp3.rs index b2feb39..b20b80c 100644 --- a/r1cs-std/src/fields/fp3.rs +++ b/src/fields/fp3.rs @@ -1,8 +1,8 @@ use crate::fields::{cubic_extension::*, fp::FpVar}; -use algebra::fields::{CubicExtParameters, Fp3Parameters, Fp3ParamsWrapper}; +use ark_ff::fields::{CubicExtParameters, Fp3Parameters, Fp3ParamsWrapper}; /// A cubic extension field constructed over a prime field. -/// This is the R1CS equivalent of `algebra_core::Fp3

`. +/// This is the R1CS equivalent of `ark_ff::Fp3

`. pub type Fp3Var

= CubicExtVar::Fp>, Fp3ParamsWrapper

>; impl CubicExtVarParams> for Fp3ParamsWrapper

{ diff --git a/r1cs-std/src/fields/fp4.rs b/src/fields/fp4.rs similarity index 82% rename from r1cs-std/src/fields/fp4.rs rename to src/fields/fp4.rs index e0a82be..1023873 100644 --- a/r1cs-std/src/fields/fp4.rs +++ b/src/fields/fp4.rs @@ -1,9 +1,9 @@ use crate::fields::{fp2::Fp2Var, quadratic_extension::*}; -use algebra::fields::{Fp4Parameters, Fp4ParamsWrapper, QuadExtParameters}; +use ark_ff::fields::{Fp4Parameters, Fp4ParamsWrapper, QuadExtParameters}; /// A quartic extension field constructed as the tower of a /// quadratic extension over a quadratic extension field. -/// This is the R1CS equivalent of `algebra_core::Fp4

`. +/// This is the R1CS equivalent of `ark_ff::Fp4

`. pub type Fp4Var

= QuadExtVar::Fp2Params>, Fp4ParamsWrapper

>; impl QuadExtVarParams> for Fp4ParamsWrapper

{ diff --git a/r1cs-std/src/fields/fp6_2over3.rs b/src/fields/fp6_2over3.rs similarity index 84% rename from r1cs-std/src/fields/fp6_2over3.rs rename to src/fields/fp6_2over3.rs index 8a12aa6..07b172b 100644 --- a/r1cs-std/src/fields/fp6_2over3.rs +++ b/src/fields/fp6_2over3.rs @@ -1,9 +1,9 @@ use crate::fields::{fp3::Fp3Var, quadratic_extension::*}; -use algebra::fields::{fp6_2over3::*, QuadExtParameters}; +use ark_ff::fields::{fp6_2over3::*, QuadExtParameters}; /// A sextic extension field constructed as the tower of a /// quadratic extension over a cubic extension field. -/// This is the R1CS equivalent of `algebra_core::fp6_2over3::Fp6

`. +/// This is the R1CS equivalent of `ark_ff::fp6_2over3::Fp6

`. pub type Fp6Var

= QuadExtVar::Fp3Params>, Fp6ParamsWrapper

>; impl QuadExtVarParams> for Fp6ParamsWrapper

{ diff --git a/r1cs-std/src/fields/fp6_3over2.rs b/src/fields/fp6_3over2.rs similarity index 94% rename from r1cs-std/src/fields/fp6_3over2.rs rename to src/fields/fp6_3over2.rs index 709e33d..fdef07d 100644 --- a/r1cs-std/src/fields/fp6_3over2.rs +++ b/src/fields/fp6_3over2.rs @@ -1,11 +1,11 @@ use crate::fields::{cubic_extension::*, fp2::*}; -use algebra::fields::{fp6_3over2::*, CubicExtParameters, Fp2}; +use ark_ff::fields::{fp6_3over2::*, CubicExtParameters, Fp2}; +use ark_relations::r1cs::SynthesisError; use core::ops::MulAssign; -use r1cs_core::SynthesisError; /// A sextic extension field constructed as the tower of a /// cubic extension over a quadratic extension field. -/// This is the R1CS equivalent of `algebra_core::fp6_3over3::Fp6

`. +/// This is the R1CS equivalent of `ark_ff::fp6_3over3::Fp6

`. pub type Fp6Var

= CubicExtVar::Fp2Params>, Fp6ParamsWrapper

>; impl CubicExtVarParams> for Fp6ParamsWrapper

{ diff --git a/src/fields/mod.rs b/src/fields/mod.rs new file mode 100644 index 0000000..41bab8f --- /dev/null +++ b/src/fields/mod.rs @@ -0,0 +1,207 @@ +use ark_ff::{prelude::*, BitIteratorBE}; +use ark_relations::r1cs::SynthesisError; +use core::{ + fmt::Debug, + ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, +}; + +use crate::{prelude::*, Assignment}; + +/// This module contains a generic implementation of cubic extension field +/// variables. That is, it implements the R1CS equivalent of +/// `ark_ff::CubicExtField`. +pub mod cubic_extension; +/// This module contains a generic implementation of quadratic extension field +/// variables. That is, it implements the R1CS equivalent of +/// `ark_ff::QuadExtField`. +pub mod quadratic_extension; + +/// This module contains a generic implementation of prime field variables. +/// That is, it implements the R1CS equivalent of `ark_ff::Fp*`. +pub mod fp; + +/// This module contains a generic implementation of the degree-12 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::Fp12` +pub mod fp12; +/// This module contains a generic implementation of the degree-2 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::Fp2` +pub mod fp2; +/// This module contains a generic implementation of the degree-3 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::Fp3` +pub mod fp3; +/// This module contains a generic implementation of the degree-4 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::Fp4` +pub mod fp4; +/// This module contains a generic implementation of the degree-6 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::fp6_2over3::Fp6` +pub mod fp6_2over3; +/// This module contains a generic implementation of the degree-6 tower +/// extension field. That is, it implements the R1CS equivalent of +/// `ark_ff::fp6_3over2::Fp6` +pub mod fp6_3over2; + +/// This trait is a hack used to work around the lack of implied bounds. +pub trait FieldOpsBounds<'a, F, T: 'a>: + Sized + + Add<&'a T, Output = T> + + Sub<&'a T, Output = T> + + Mul<&'a T, Output = T> + + Add + + Sub + + Mul + + Add + + Sub + + Mul +{ +} + +/// A variable representing a field. Corresponds to the native type `F`. +pub trait FieldVar: + 'static + + Clone + + From> + + R1CSVar + + EqGadget + + ToBitsGadget + + AllocVar + + ToBytesGadget + + CondSelectGadget + + for<'a> FieldOpsBounds<'a, F, Self> + + for<'a> AddAssign<&'a Self> + + for<'a> SubAssign<&'a Self> + + for<'a> MulAssign<&'a Self> + + AddAssign + + SubAssign + + MulAssign + + AddAssign + + SubAssign + + MulAssign + + Debug +{ + /// Returns the constant `F::zero()`. + fn zero() -> Self; + + /// Returns a `Boolean` representing whether `self == Self::zero()`. + fn is_zero(&self) -> Result, SynthesisError> { + self.is_eq(&Self::zero()) + } + + /// Returns the constant `F::one()`. + fn one() -> Self; + + /// Returns a `Boolean` representing whether `self == Self::one()`. + fn is_one(&self) -> Result, SynthesisError> { + self.is_eq(&Self::one()) + } + + /// Returns a constant with value `v`. + /// + /// This *should not* allocate any variables. + fn constant(v: F) -> Self; + + /// Computes `self + self`. + fn double(&self) -> Result { + Ok(self.clone() + self) + } + + /// Sets `self = self + self`. + fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> { + *self += self.double()?; + Ok(self) + } + + /// Coputes `-self`. + fn negate(&self) -> Result; + + /// Sets `self = -self`. + #[inline] + fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> { + *self = self.negate()?; + Ok(self) + } + + /// Computes `self * self`. + /// + /// A default implementation is provided which just invokes the underlying + /// multiplication routine. However, this method should be specialized + /// for extension fields, where faster algorithms exist for squaring. + fn square(&self) -> Result { + Ok(self.clone() * self) + } + + /// Sets `self = self.square()`. + fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> { + *self = self.square()?; + Ok(self) + } + + /// Enforces that `self * other == result`. + fn mul_equals(&self, other: &Self, result: &Self) -> Result<(), SynthesisError> { + let actual_result = self.clone() * other; + result.enforce_equal(&actual_result) + } + + /// Enforces that `self * self == result`. + fn square_equals(&self, result: &Self) -> Result<(), SynthesisError> { + let actual_result = self.square()?; + result.enforce_equal(&actual_result) + } + + /// Computes `result` such that `self * result == Self::one()`. + fn inverse(&self) -> Result; + + /// Returns `(self / denominator)`. but requires fewer constraints than + /// `self * denominator.inverse()`. + /// It is up to the caller to ensure that denominator is non-zero, + /// since in that case the result is unconstrained. + fn mul_by_inverse(&self, denominator: &Self) -> Result { + let result = Self::new_witness(self.cs(), || { + let denominator_inv_native = denominator.value()?.inverse().get()?; + let result = self.value()? * &denominator_inv_native; + Ok(result) + })?; + result.mul_equals(&denominator, &self)?; + + Ok(result) + } + + /// Computes the frobenius map over `self`. + fn frobenius_map(&self, power: usize) -> Result; + + /// Sets `self = self.frobenius_map()`. + fn frobenius_map_in_place(&mut self, power: usize) -> Result<&mut Self, SynthesisError> { + *self = self.frobenius_map(power)?; + Ok(self) + } + + /// Comptues `self^bits`, where `bits` is a *little-endian* bit-wise + /// decomposition of the exponent. + fn pow_le(&self, bits: &[Boolean]) -> Result { + let mut res = Self::one(); + let mut power = self.clone(); + for bit in bits { + let tmp = res.clone() * &power; + res = bit.select(&tmp, &res)?; + power.square_in_place()?; + } + Ok(res) + } + + /// Computes `self^S`, where S is interpreted as an little-endian + /// u64-decomposition of an integer. + fn pow_by_constant>(&self, exp: S) -> Result { + let mut res = Self::one(); + for i in BitIteratorBE::without_leading_zeros(exp) { + res.square_in_place()?; + if i { + res *= self; + } + } + Ok(res) + } +} diff --git a/r1cs-std/src/fields/quadratic_extension.rs b/src/fields/quadratic_extension.rs similarity index 95% rename from r1cs-std/src/fields/quadratic_extension.rs rename to src/fields/quadratic_extension.rs index 4b1cb30..4107107 100644 --- a/r1cs-std/src/fields/quadratic_extension.rs +++ b/src/fields/quadratic_extension.rs @@ -1,19 +1,18 @@ -use algebra::{ +use ark_ff::{ fields::{Field, QuadExtField, QuadExtParameters}, Zero, }; +use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use core::{borrow::Borrow, marker::PhantomData}; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::fields::fp::FpVar; use crate::{ - fields::{FieldOpsBounds, FieldVar}, + fields::{fp::FpVar, FieldOpsBounds, FieldVar}, prelude::*, ToConstraintFieldGadget, Vec, }; /// This struct is the `R1CS` equivalent of the quadratic extension field type -/// in `algebra-core`, i.e. `algebra_core::QuadExtField`. +/// in `ark-ff`, i.e. `ark_ff::QuadExtField`. #[derive(Derivative)] #[derivative(Debug(bound = "BF: core::fmt::Debug"), Clone(bound = "BF: Clone"))] #[must_use] @@ -29,14 +28,16 @@ where _params: PhantomData

, } -/// This trait describes parameters that are used to implement arithmetic for `QuadExtVar`. +/// This trait describes parameters that are used to implement arithmetic for +/// `QuadExtVar`. pub trait QuadExtVarParams>: QuadExtParameters where for<'a> &'a BF: FieldOpsBounds<'a, Self::BaseField, BF>, { - /// Multiply the base field of the `QuadExtVar` by the appropriate Frobenius coefficient. - /// This is equivalent to `Self::mul_base_field_by_frob_coeff(power)`. + /// Multiply the base field of the `QuadExtVar` by the appropriate Frobenius + /// coefficient. This is equivalent to + /// `Self::mul_base_field_by_frob_coeff(power)`. fn mul_base_field_var_by_frob_coeff(fe: &mut BF, power: usize); } @@ -53,8 +54,8 @@ where } } - /// Multiplies a variable of the base field by the quadratic nonresidue `P::NONRESIDUE` that - /// is used to construct the extension field. + /// Multiplies a variable of the base field by the quadratic nonresidue + /// `P::NONRESIDUE` that is used to construct the extension field. #[inline] pub fn mul_base_field_by_nonresidue(fe: &BF) -> Result { Ok(fe * P::NONRESIDUE) @@ -74,25 +75,26 @@ where *self = (&*self).mul_by_base_field_constant(fe); } - /// This is only to be used when the element is *known* to be in the cyclotomic subgroup. + /// This is only to be used when the element is *known* to be in the + /// cyclotomic subgroup. #[inline] pub fn unitary_inverse(&self) -> Result { Ok(Self::new(self.c0.clone(), self.c1.negate()?)) } - /// This is only to be used when the element is *known* to be in the cyclotomic subgroup. + /// This is only to be used when the element is *known* to be in the + /// cyclotomic subgroup. #[inline] #[tracing::instrument(target = "r1cs", skip(exponent))] pub fn cyclotomic_exp(&self, exponent: impl AsRef<[u64]>) -> Result where Self: FieldVar, P::BasePrimeField>, { - use algebra::biginteger::arithmetic::find_wnaf; let mut res = Self::one(); let self_inverse = self.unitary_inverse()?; let mut found_nonzero = false; - let naf = find_wnaf(exponent.as_ref()); + let naf = ark_ff::biginteger::arithmetic::find_wnaf(exponent.as_ref()); for &value in naf.iter().rev() { if found_nonzero { @@ -552,8 +554,8 @@ where ), }; - let c0 = BF::new_variable(r1cs_core::ns!(cs, "c0"), || c0, mode)?; - let c1 = BF::new_variable(r1cs_core::ns!(cs, "c1"), || c1, mode)?; + let c0 = BF::new_variable(ark_relations::ns!(cs, "c0"), || c0, mode)?; + let c1 = BF::new_variable(ark_relations::ns!(cs, "c1"), || c1, mode)?; Ok(Self::new(c0, c1)) } } diff --git a/r1cs-std/src/groups/curves/mod.rs b/src/groups/curves/mod.rs similarity index 100% rename from r1cs-std/src/groups/curves/mod.rs rename to src/groups/curves/mod.rs diff --git a/r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs b/src/groups/curves/short_weierstrass/bls12/mod.rs similarity index 90% rename from r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs rename to src/groups/curves/short_weierstrass/bls12/mod.rs index 384ac76..bafa68c 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs +++ b/src/groups/curves/short_weierstrass/bls12/mod.rs @@ -1,12 +1,9 @@ -use algebra::{ - curves::{ - bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType}, - short_weierstrass_jacobian::GroupAffine, - }, - fields::Field, - BitIteratorBE, One, +use ark_ec::{ + bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType}, + short_weierstrass_jacobian::GroupAffine, }; -use r1cs_core::{Namespace, SynthesisError}; +use ark_ff::{BitIteratorBE, Field, One}; +use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ fields::{fp::FpVar, fp2::Fp2Var, FieldVar}, @@ -20,15 +17,17 @@ use core::fmt::Debug; pub type G1Var

= ProjectiveVar<

::G1Parameters, FpVar<

::Fp>>; -/// Represents an affine point on G1. Should be used only for comparison and when -/// a canonical representation of a point is required, and not for arithmetic. +/// Represents an affine point on G1. Should be used only for comparison and +/// when a canonical representation of a point is required, and not for +/// arithmetic. pub type G1AffineVar

= AffineVar<

::G1Parameters, FpVar<

::Fp>>; /// Represents a projective point in G2. pub type G2Var

= ProjectiveVar<

::G2Parameters, Fp2G

>; -/// Represents an affine point on G2. Should be used only for comparison and when -/// a canonical representation of a point is required, and not for arithmetic. +/// Represents an affine point on G2. Should be used only for comparison and +/// when a canonical representation of a point is required, and not for +/// arithmetic. pub type G2AffineVar

= AffineVar<

::G2Parameters, Fp2G

>; /// Represents the cached precomputation that can be performed on a G1 element @@ -38,7 +37,8 @@ pub type G2AffineVar

= AffineVar<

::G2Parameters, Fp2G

(pub AffineVar>); impl G1PreparedVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let x = self.0.x.value()?; let y = self.0.y.value()?; @@ -64,10 +64,10 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let cs = ns.cs(); let g1_prep = f().map(|b| b.borrow().0); - let x = FpVar::new_variable(r1cs_core::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(r1cs_core::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; + let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; let infinity = Boolean::new_variable( - r1cs_core::ns!(cs, "inf"), + ark_relations::ns!(cs, "inf"), || g1_prep.map(|g| g.infinity), mode, )?; @@ -128,7 +128,7 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ .iter() .map(|(_, _, z)| *z) .collect::>(); - algebra::fields::batch_inversion(&mut z_s); + ark_ff::fields::batch_inversion(&mut z_s); projective_coeffs .iter() .zip(z_s) @@ -137,7 +137,7 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ }); let l = Vec::new_variable( - r1cs_core::ns!(cs, "l"), + ark_relations::ns!(cs, "l"), || { g2_prep .clone() @@ -146,7 +146,7 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ mode, )?; let r = Vec::new_variable( - r1cs_core::ns!(cs, "r"), + ark_relations::ns!(cs, "r"), || g2_prep.map(|c| c.iter().map(|(_, r)| *r).collect::>()), mode, )?; diff --git a/r1cs-std/src/groups/curves/short_weierstrass/mnt4/mod.rs b/src/groups/curves/short_weierstrass/mnt4/mod.rs similarity index 90% rename from r1cs-std/src/groups/curves/short_weierstrass/mnt4/mod.rs rename to src/groups/curves/short_weierstrass/mnt4/mod.rs index e78d967..49421ed 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/mnt4/mod.rs +++ b/src/groups/curves/short_weierstrass/mnt4/mod.rs @@ -1,11 +1,9 @@ -use algebra::{ - curves::mnt4::{ - g2::{AteAdditionCoefficients, AteDoubleCoefficients}, - G1Prepared, G2Prepared, MNT4Parameters, - }, - Field, +use ark_ec::mnt4::{ + g2::{AteAdditionCoefficients, AteDoubleCoefficients}, + G1Prepared, G2Prepared, MNT4Parameters, }; -use r1cs_core::{Namespace, SynthesisError}; +use ark_ff::Field; +use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ fields::{fp::FpVar, fp2::Fp2Var, FieldVar}, @@ -50,15 +48,15 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let g1_prep = f().map(|b| *b.borrow()); - let x = FpVar::new_variable(r1cs_core::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(r1cs_core::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; + let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; let x_twist = Fp2Var::new_variable( - r1cs_core::ns!(cs, "x_twist"), + ark_relations::ns!(cs, "x_twist"), || g1_prep.map(|g| g.x_twist), mode, )?; let y_twist = Fp2Var::new_variable( - r1cs_core::ns!(cs, "y_twist"), + ark_relations::ns!(cs, "y_twist"), || g1_prep.map(|g| g.y_twist), mode, )?; @@ -72,7 +70,8 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ } impl G1PreparedVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let (x, y, x_twist, y_twist) = ( self.x.value()?, @@ -166,25 +165,25 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ let g2_prep = f().map(|b| b.borrow().clone()); let g2 = g2_prep.as_ref().map_err(|e| *e); - let x = Fp2Var::new_variable(r1cs_core::ns!(cs, "x"), || g2.map(|g| g.x), mode)?; - let y = Fp2Var::new_variable(r1cs_core::ns!(cs, "y"), || g2.map(|g| g.y), mode)?; + let x = Fp2Var::new_variable(ark_relations::ns!(cs, "x"), || g2.map(|g| g.x), mode)?; + let y = Fp2Var::new_variable(ark_relations::ns!(cs, "y"), || g2.map(|g| g.y), mode)?; let x_over_twist = Fp2Var::new_variable( - r1cs_core::ns!(cs, "x_over_twist"), + ark_relations::ns!(cs, "x_over_twist"), || g2.map(|g| g.x_over_twist), mode, )?; let y_over_twist = Fp2Var::new_variable( - r1cs_core::ns!(cs, "y_over_twist"), + ark_relations::ns!(cs, "y_over_twist"), || g2.map(|g| g.y_over_twist), mode, )?; let double_coefficients = Vec::new_variable( - r1cs_core::ns!(cs, "double coeffs"), + ark_relations::ns!(cs, "double coeffs"), || g2.map(|g| g.double_coefficients.clone()), mode, )?; let addition_coefficients = Vec::new_variable( - r1cs_core::ns!(cs, "add coeffs"), + ark_relations::ns!(cs, "add coeffs"), || g2.map(|g| g.addition_coefficients.clone()), mode, )?; @@ -243,7 +242,8 @@ impl ToBytesGadget for G2PreparedVar

{ } impl G2PreparedVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let x = self.x.value()?; let y = self.y.value()?; @@ -363,10 +363,11 @@ impl AllocVar, P::Fp> for AteDoubleC let c_prep = f().map(|c| c.borrow().clone()); let c = c_prep.as_ref().map_err(|e| *e); - let c_h = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_h"), || c.map(|c| c.c_h), mode)?; - let c_4c = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_4c"), || c.map(|c| c.c_4c), mode)?; - let c_j = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_j"), || c.map(|c| c.c_j), mode)?; - let c_l = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_l"), || c.map(|c| c.c_l), mode)?; + let c_h = Fp2Var::new_variable(ark_relations::ns!(cs, "c_h"), || c.map(|c| c.c_h), mode)?; + let c_4c = + Fp2Var::new_variable(ark_relations::ns!(cs, "c_4c"), || c.map(|c| c.c_4c), mode)?; + let c_j = Fp2Var::new_variable(ark_relations::ns!(cs, "c_j"), || c.map(|c| c.c_j), mode)?; + let c_l = Fp2Var::new_variable(ark_relations::ns!(cs, "c_l"), || c.map(|c| c.c_l), mode)?; Ok(Self { c_h, c_4c, @@ -406,7 +407,8 @@ impl ToBytesGadget for AteDoubleCoefficientsVar

{ } impl AteDoubleCoefficientsVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let (c_h, c_4c, c_j, c_l) = ( self.c_l.value()?, @@ -446,8 +448,10 @@ impl AllocVar, P::Fp> let c_prep = f().map(|c| c.borrow().clone()); let c = c_prep.as_ref().map_err(|e| *e); - let c_l1 = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_l1"), || c.map(|c| c.c_l1), mode)?; - let c_rz = Fp2Var::new_variable(r1cs_core::ns!(cs, "c_rz"), || c.map(|c| c.c_rz), mode)?; + let c_l1 = + Fp2Var::new_variable(ark_relations::ns!(cs, "c_l1"), || c.map(|c| c.c_l1), mode)?; + let c_rz = + Fp2Var::new_variable(ark_relations::ns!(cs, "c_rz"), || c.map(|c| c.c_rz), mode)?; Ok(Self { c_l1, c_rz }) } } @@ -474,7 +478,8 @@ impl ToBytesGadget for AteAdditionCoefficientsVar

{ } impl AteAdditionCoefficientsVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let (c_l1, c_rz) = (self.c_l1.value()?, self.c_rz.value()?); Ok(AteAdditionCoefficients { c_l1, c_rz }) diff --git a/r1cs-std/src/groups/curves/short_weierstrass/mnt6/mod.rs b/src/groups/curves/short_weierstrass/mnt6/mod.rs similarity index 90% rename from r1cs-std/src/groups/curves/short_weierstrass/mnt6/mod.rs rename to src/groups/curves/short_weierstrass/mnt6/mod.rs index 6562928..4b6d55e 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/mnt6/mod.rs +++ b/src/groups/curves/short_weierstrass/mnt6/mod.rs @@ -1,11 +1,9 @@ -use algebra::{ - curves::mnt6::{ - g2::{AteAdditionCoefficients, AteDoubleCoefficients}, - G1Prepared, G2Prepared, MNT6Parameters, - }, - Field, +use ark_ec::mnt6::{ + g2::{AteAdditionCoefficients, AteDoubleCoefficients}, + G1Prepared, G2Prepared, MNT6Parameters, }; -use r1cs_core::{Namespace, SynthesisError}; +use ark_ff::Field; +use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ fields::{fp::FpVar, fp3::Fp3Var, FieldVar}, @@ -39,7 +37,8 @@ pub struct G1PreparedVar { } impl G1PreparedVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let x = self.x.value()?; let y = self.y.value()?; @@ -82,15 +81,15 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let g1_prep = f().map(|b| *b.borrow()); - let x = FpVar::new_variable(r1cs_core::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(r1cs_core::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; + let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; let x_twist = Fp3Var::new_variable( - r1cs_core::ns!(cs, "x_twist"), + ark_relations::ns!(cs, "x_twist"), || g1_prep.map(|g| g.x_twist), mode, )?; let y_twist = Fp3Var::new_variable( - r1cs_core::ns!(cs, "y_twist"), + ark_relations::ns!(cs, "y_twist"), || g1_prep.map(|g| g.y_twist), mode, )?; @@ -166,25 +165,25 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ let g2_prep = f().map(|b| b.borrow().clone()); let g2 = g2_prep.as_ref().map_err(|e| *e); - let x = Fp3Var::new_variable(r1cs_core::ns!(cs, "x"), || g2.map(|g| g.x), mode)?; - let y = Fp3Var::new_variable(r1cs_core::ns!(cs, "y"), || g2.map(|g| g.y), mode)?; + let x = Fp3Var::new_variable(ark_relations::ns!(cs, "x"), || g2.map(|g| g.x), mode)?; + let y = Fp3Var::new_variable(ark_relations::ns!(cs, "y"), || g2.map(|g| g.y), mode)?; let x_over_twist = Fp3Var::new_variable( - r1cs_core::ns!(cs, "x_over_twist"), + ark_relations::ns!(cs, "x_over_twist"), || g2.map(|g| g.x_over_twist), mode, )?; let y_over_twist = Fp3Var::new_variable( - r1cs_core::ns!(cs, "y_over_twist"), + ark_relations::ns!(cs, "y_over_twist"), || g2.map(|g| g.y_over_twist), mode, )?; let double_coefficients = Vec::new_variable( - r1cs_core::ns!(cs, "double coeffs"), + ark_relations::ns!(cs, "double coeffs"), || g2.map(|g| g.double_coefficients.clone()), mode, )?; let addition_coefficients = Vec::new_variable( - r1cs_core::ns!(cs, "add coeffs"), + ark_relations::ns!(cs, "add coeffs"), || g2.map(|g| g.addition_coefficients.clone()), mode, )?; @@ -243,7 +242,8 @@ impl ToBytesGadget for G2PreparedVar

{ } impl G2PreparedVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let x = self.x.value()?; let y = self.y.value()?; @@ -363,10 +363,11 @@ impl AllocVar, P::Fp> for AteDoubleC let c_prep = f().map(|c| c.borrow().clone()); let c = c_prep.as_ref().map_err(|e| *e); - let c_h = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_h"), || c.map(|c| c.c_h), mode)?; - let c_4c = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_4c"), || c.map(|c| c.c_4c), mode)?; - let c_j = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_j"), || c.map(|c| c.c_j), mode)?; - let c_l = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_l"), || c.map(|c| c.c_l), mode)?; + let c_h = Fp3Var::new_variable(ark_relations::ns!(cs, "c_h"), || c.map(|c| c.c_h), mode)?; + let c_4c = + Fp3Var::new_variable(ark_relations::ns!(cs, "c_4c"), || c.map(|c| c.c_4c), mode)?; + let c_j = Fp3Var::new_variable(ark_relations::ns!(cs, "c_j"), || c.map(|c| c.c_j), mode)?; + let c_l = Fp3Var::new_variable(ark_relations::ns!(cs, "c_l"), || c.map(|c| c.c_l), mode)?; Ok(Self { c_h, c_4c, @@ -406,7 +407,8 @@ impl ToBytesGadget for AteDoubleCoefficientsVar

{ } impl AteDoubleCoefficientsVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let c_h = self.c_h.value()?; let c_4c = self.c_4c.value()?; @@ -444,8 +446,10 @@ impl AllocVar, P::Fp> let c_prep = f().map(|c| c.borrow().clone()); let c = c_prep.as_ref().map_err(|e| *e); - let c_l1 = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_l1"), || c.map(|c| c.c_l1), mode)?; - let c_rz = Fp3Var::new_variable(r1cs_core::ns!(cs, "c_rz"), || c.map(|c| c.c_rz), mode)?; + let c_l1 = + Fp3Var::new_variable(ark_relations::ns!(cs, "c_l1"), || c.map(|c| c.c_l1), mode)?; + let c_rz = + Fp3Var::new_variable(ark_relations::ns!(cs, "c_rz"), || c.map(|c| c.c_rz), mode)?; Ok(Self { c_l1, c_rz }) } } @@ -472,7 +476,8 @@ impl ToBytesGadget for AteAdditionCoefficientsVar

{ } impl AteAdditionCoefficientsVar

{ - /// Returns the value assigned to `self` in the underlying constraint system. + /// Returns the value assigned to `self` in the underlying constraint + /// system. pub fn value(&self) -> Result, SynthesisError> { let c_l1 = self.c_l1.value()?; let c_rz = self.c_rz.value()?; diff --git a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs b/src/groups/curves/short_weierstrass/mod.rs similarity index 86% rename from r1cs-std/src/groups/curves/short_weierstrass/mod.rs rename to src/groups/curves/short_weierstrass/mod.rs index b73470e..6465323 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -1,15 +1,12 @@ -use algebra::{ - curves::{ - short_weierstrass_jacobian::{GroupAffine as SWAffine, GroupProjective as SWProjective}, - SWModelParameters, - }, - AffineCurve, BigInteger, BitIteratorBE, Field, One, PrimeField, ProjectiveCurve, Zero, +use ark_ec::{ + short_weierstrass_jacobian::{GroupAffine as SWAffine, GroupProjective as SWProjective}, + AffineCurve, ProjectiveCurve, SWModelParameters, }; +use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; +use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use core::{borrow::Borrow, marker::PhantomData}; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::fields::fp::FpVar; -use crate::{prelude::*, ToConstraintFieldGadget, Vec}; +use crate::{fields::fp::FpVar, prelude::*, ToConstraintFieldGadget, Vec}; /// This module provides a generic implementation of G1 and G2 for /// the [[BLS12]](https://eprint.iacr.org/2002/088.pdf) family of bilinear groups. @@ -168,7 +165,7 @@ where let zero_y = F::one(); let non_zero_x = F::new_variable( - r1cs_core::ns!(cs, "non-zero x"), + ark_relations::ns!(cs, "non-zero x"), || { let z_inv = self.z.value()?.inverse().unwrap_or(P::BaseField::zero()); Ok(self.x.value()? * &z_inv) @@ -176,7 +173,7 @@ where mode, )?; let non_zero_y = F::new_variable( - r1cs_core::ns!(cs, "non-zero y"), + ark_relations::ns!(cs, "non-zero y"), || { let z_inv = self.z.value()?.inverse().unwrap_or(P::BaseField::zero()); Ok(self.y.value()? * &z_inv) @@ -220,9 +217,9 @@ where ), }; - let x = F::new_variable(r1cs_core::ns!(cs, "x"), || x, mode)?; - let y = F::new_variable(r1cs_core::ns!(cs, "y"), || y, mode)?; - let z = F::new_variable(r1cs_core::ns!(cs, "z"), || z, mode)?; + let x = F::new_variable(ark_relations::ns!(cs, "x"), || x, mode)?; + let y = F::new_variable(ark_relations::ns!(cs, "y"), || y, mode)?; + let z = F::new_variable(ark_relations::ns!(cs, "z"), || z, mode)?; Ok(Self::new(x, y, z)) } @@ -580,7 +577,7 @@ where let (mut ge, iter) = if cofactor_weight < modulus_minus_1_weight { let ge = Self::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Witness without subgroup check with cofactor mul"), + ark_relations::ns!(cs, "Witness without subgroup check with cofactor mul"), || f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()), mode, )?; @@ -590,7 +587,7 @@ where ) } else { let ge = Self::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Witness without subgroup check with `r` check"), + ark_relations::ns!(cs, "Witness without subgroup check with `r` check"), || { f().map(|g| { let g = g.into_affine(); @@ -708,91 +705,3 @@ where Ok(bytes) } } - -#[cfg(test)] -#[allow(dead_code)] -pub(crate) fn test() -> Result<(), SynthesisError> -where - P: SWModelParameters, - GG: CurveVar, ::BasePrimeField>, - for<'a> &'a GG: GroupOpsBounds<'a, SWProjective

, GG>, -{ - use crate::prelude::*; - use algebra::{test_rng, BitIteratorLE, Group, UniformRand}; - use r1cs_core::ConstraintSystem; - - crate::groups::test::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(); - - println!("Allocating things"); - let ns = r1cs_core::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); - println!("Done Allocating things"); - 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); - - println!("Checking addition"); - // 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()); - println!("Done checking addition"); - - println!("Checking doubling"); - // 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()); - println!("Done checking doubling"); - - println!("Checking mul_bits"); - // 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(r1cs_core::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()); - println!("Done checking mul_bits"); - - if !cs.is_satisfied().unwrap() { - println!("Not satisfied"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - } - - assert!(cs.is_satisfied().unwrap()); - Ok(()) -} diff --git a/r1cs-std/src/groups/curves/twisted_edwards/mod.rs b/src/groups/curves/twisted_edwards/mod.rs similarity index 86% rename from r1cs-std/src/groups/curves/twisted_edwards/mod.rs rename to src/groups/curves/twisted_edwards/mod.rs index f8dc5ce..9006c58 100644 --- a/r1cs-std/src/groups/curves/twisted_edwards/mod.rs +++ b/src/groups/curves/twisted_edwards/mod.rs @@ -1,12 +1,10 @@ -use algebra::{ - curves::{ - twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective}, - AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters, - }, - BigInteger, BitIteratorBE, Field, One, PrimeField, Zero, +use ark_ec::{ + twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective}, + AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters, }; +use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; -use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError}; +use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use crate::{prelude::*, ToConstraintFieldGadget, Vec}; @@ -38,7 +36,8 @@ pub struct MontgomeryAffineVar< mod montgomery_affine_impl { use super::*; - use algebra::{twisted_edwards_extended::GroupAffine, Field}; + use ark_ec::twisted_edwards_extended::GroupAffine; + use ark_ff::Field; use core::ops::Add; impl R1CSVar<::BasePrimeField> for MontgomeryAffineVar @@ -76,8 +75,8 @@ mod montgomery_affine_impl { } } - /// Converts a Twisted Edwards curve point to coordinates for the corresponding affine - /// Montgomery curve point. + /// Converts a Twisted Edwards curve point to coordinates for the + /// corresponding affine Montgomery curve point. #[tracing::instrument(target = "r1cs")] pub fn from_edwards_to_coords( p: &TEAffine

, @@ -96,16 +95,16 @@ mod montgomery_affine_impl { Ok((montgomery_point.x, montgomery_point.y)) } - /// Converts a Twisted Edwards curve point to coordinates for the corresponding affine - /// Montgomery curve point. + /// Converts a Twisted Edwards curve point to coordinates for the + /// corresponding affine Montgomery curve point. #[tracing::instrument(target = "r1cs")] pub fn new_witness_from_edwards( cs: ConstraintSystemRef<::BasePrimeField>, p: &TEAffine

, ) -> Result { let montgomery_coords = Self::from_edwards_to_coords(p)?; - let u = F::new_witness(r1cs_core::ns!(cs, "u"), || Ok(montgomery_coords.0))?; - let v = F::new_witness(r1cs_core::ns!(cs, "v"), || Ok(montgomery_coords.1))?; + let u = F::new_witness(ark_relations::ns!(cs, "u"), || Ok(montgomery_coords.0))?; + let v = F::new_witness(ark_relations::ns!(cs, "v"), || Ok(montgomery_coords.1))?; Ok(Self::new(u, v)) } @@ -114,7 +113,7 @@ mod montgomery_affine_impl { pub fn into_edwards(&self) -> Result, SynthesisError> { let cs = self.cs(); // Compute u = x / y - let u = F::new_witness(r1cs_core::ns!(cs, "u"), || { + let u = F::new_witness(ark_relations::ns!(cs, "u"), || { let y_inv = self .y .value()? @@ -125,7 +124,7 @@ mod montgomery_affine_impl { u.mul_equals(&self.y, &self.x)?; - let v = F::new_witness(r1cs_core::ns!(cs, "v"), || { + let v = F::new_witness(ark_relations::ns!(cs, "v"), || { let mut t0 = self.x.value()?; let mut t1 = t0; t0 -= &P::BaseField::one(); @@ -163,7 +162,7 @@ mod montgomery_affine_impl { let coeff_a = P::MontgomeryModelParameters::COEFF_A; let lambda = F::new_variable( - r1cs_core::ns!(cs, "lambda"), + ark_relations::ns!(cs, "lambda"), || { let n = other.y.value()? - &self.y.value()?; let d = other.x.value()? - &self.x.value()?; @@ -178,7 +177,7 @@ mod montgomery_affine_impl { // Compute x'' = B*lambda^2 - A - x - x' let xprime = F::new_variable( - r1cs_core::ns!(cs, "xprime"), + ark_relations::ns!(cs, "xprime"), || { Ok(lambda.value()?.square() * &coeff_b - &coeff_a @@ -195,7 +194,7 @@ mod montgomery_affine_impl { lambda_b.mul_equals(&lambda, &xprime_lc).unwrap(); let yprime = F::new_variable( - r1cs_core::ns!(cs, "yprime"), + ark_relations::ns!(cs, "yprime"), || { Ok(-(self.y.value()? + &(lambda.value()? * &(xprime.value()? - &self.x.value()?)))) @@ -269,8 +268,8 @@ where ), }; - let x = F::new_variable(r1cs_core::ns!(cs, "x"), || x, mode)?; - let y = F::new_variable(r1cs_core::ns!(cs, "y"), || y, mode)?; + let x = F::new_variable(ark_relations::ns!(cs, "x"), || x, mode)?; + let y = F::new_variable(ark_relations::ns!(cs, "y"), || y, mode)?; Ok(Self::new(x, y)) } @@ -289,9 +288,10 @@ where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// Compute a scalar multiplication of `bases` with respect to `scalars`, - /// where the elements of `scalars` are length-three slices of bits, and which - /// such that the first two bits are use to select one of the bases, - /// while the third bit is used to conditionally negate the selection. + /// where the elements of `scalars` are length-three slices of bits, and + /// which such that the first two bits are use to select one of the + /// bases, while the third bit is used to conditionally negate the + /// selection. #[tracing::instrument(target = "r1cs", skip(bases, scalars))] pub fn precomputed_base_3_bit_signed_digit_scalar_mul( bases: &[impl Borrow<[TEProjective

]>], @@ -475,7 +475,7 @@ where let a_x2 = &x2 * a; // Compute x3 = (2xy) / (ax^2 + y^2) - let x3 = F::new_witness(r1cs_core::ns!(cs, "x3"), || { + let x3 = F::new_witness(ark_relations::ns!(cs, "x3"), || { let t0 = xy.value()?.double(); let t1 = a * &x2.value()? + &y2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -487,7 +487,7 @@ where // Compute y3 = (y^2 - ax^2) / (2 - ax^2 - y^2) let two = P::BaseField::one().double(); - let y3 = F::new_witness(r1cs_core::ns!(cs, "y3"), || { + let y3 = F::new_witness(ark_relations::ns!(cs, "y3"), || { let a_x2 = a * &x2.value()?; let t0 = y2.value()? - &a_x2; let t1 = two - &a_x2 - &y2.value()?; @@ -600,7 +600,7 @@ where let (mut ge, iter) = if cofactor_weight < modulus_minus_1_weight { let ge = Self::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Witness without subgroup check with cofactor mul"), + ark_relations::ns!(cs, "Witness without subgroup check with cofactor mul"), || f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()), mode, )?; @@ -610,7 +610,7 @@ where ) } else { let ge = Self::new_variable_omit_prime_order_check( - r1cs_core::ns!(cs, "Witness without subgroup check with `r` check"), + ark_relations::ns!(cs, "Witness without subgroup check with `r` check"), || { f().map(|g| { let g = g.into_affine(); @@ -733,7 +733,7 @@ impl_bounded_ops!( let v2 = &v0 * &v1 * d; // Compute x3 = (v0 + v1) / (1 + v2) - let x3 = F::new_witness(r1cs_core::ns!(cs, "x3"), || { + let x3 = F::new_witness(ark_relations::ns!(cs, "x3"), || { let t0 = v0.value()? + &v1.value()?; let t1 = P::BaseField::one() + &v2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -744,7 +744,7 @@ impl_bounded_ops!( x3.mul_equals(&v2_plus_one, &v0_plus_v1).unwrap(); // Compute y3 = (U + a * v0 - v1) / (1 - v2) - let y3 = F::new_witness(r1cs_core::ns!(cs, "y3"), || { + let y3 = F::new_witness(ark_relations::ns!(cs, "y3"), || { let t0 = u.value()? + &(a * &v0.value()?) - &v1.value()?; let t1 = P::BaseField::one() - &v2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -919,91 +919,3 @@ where Ok(x_bytes) } } - -#[cfg(test)] -#[allow(dead_code)] -pub(crate) fn test() -> Result<(), SynthesisError> -where - P: TEModelParameters, - GG: CurveVar, ::BasePrimeField>, - for<'a> &'a GG: GroupOpsBounds<'a, TEProjective

, GG>, -{ - use crate::prelude::*; - use algebra::{test_rng, BitIteratorLE, Group, UniformRand}; - use r1cs_core::ConstraintSystem; - - crate::groups::test::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(); - - println!("Allocating things"); - let ns = r1cs_core::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); - println!("Done Allocating things"); - 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); - - println!("Checking addition"); - // 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()); - println!("Done checking addition"); - - println!("Checking doubling"); - // 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()); - println!("Done checking doubling"); - - println!("Checking mul_bits"); - // 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(r1cs_core::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()); - println!("Done checking mul_bits"); - - if !cs.is_satisfied().unwrap() { - println!("Not satisfied"); - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - } - - assert!(cs.is_satisfied().unwrap()); - Ok(()) -} diff --git a/r1cs-std/src/groups/mod.rs b/src/groups/mod.rs similarity index 62% rename from r1cs-std/src/groups/mod.rs rename to src/groups/mod.rs index a2682ef..e695240 100644 --- a/r1cs-std/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -1,16 +1,15 @@ use crate::prelude::*; -use algebra::{Field, ProjectiveCurve}; +use ark_ec::ProjectiveCurve; +use ark_ff::Field; +use ark_relations::r1cs::{Namespace, SynthesisError}; use core::ops::{Add, AddAssign, Sub, SubAssign}; -use r1cs_core::{Namespace, SynthesisError}; use core::{borrow::Borrow, fmt::Debug}; /// This module contains implementations of arithmetic for various curve models. pub mod curves; -pub use self::curves::short_weierstrass::bls12; -pub use self::curves::short_weierstrass::mnt4; -pub use self::curves::short_weierstrass::mnt6; +pub use self::curves::short_weierstrass::{bls12, mnt4, mnt6}; /// A hack used to work around the lack of implied bounds. pub trait GroupOpsBounds<'a, F, T: 'a>: @@ -147,81 +146,3 @@ pub trait CurveVar: Ok(result) } } - -#[cfg(test)] -mod test { - use algebra::{test_rng, Field, ProjectiveCurve}; - use r1cs_core::{ConstraintSystem, SynthesisError}; - - use crate::prelude::*; - - pub(crate) fn group_test>( - ) -> Result<(), SynthesisError> - where - 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(r1cs_core::ns!(cs, "generate_a"), || Ok(a_native)).unwrap(); - let b = GG::new_witness(r1cs_core::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() { - println!("{:?}", cs.which_is_unsatisfied().unwrap()); - } - assert!(cs.is_satisfied().unwrap()); - Ok(()) - } -} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6386584 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,143 @@ +#![cfg_attr(not(feature = "std"), no_std)] +//! This crate implements common "gadgets" that make +//! programming rank-1 constraint systems easier. +#![deny( + warnings, + unused, + future_incompatible, + nonstandard_style, + rust_2018_idioms +)] + +#[macro_use] +extern crate ark_std; + +#[macro_use] +extern crate ark_relations; + +#[doc(hidden)] +#[macro_use] +extern crate derivative; + +/// Some utility macros for making downstream impls easier. +#[macro_use] +pub mod macros; + +pub(crate) use ark_std::vec::Vec; + +use ark_ff::Field; + +/// This module implements gadgets related to bit manipulation, such as +/// `Boolean` and `UInt`s. +pub mod bits; +pub use self::bits::*; + +/// This module implements gadgets related to field arithmetic. +pub mod fields; + +/// This module implements gadgets related to group arithmetic, and specifically +/// elliptic curve arithmetic. +pub mod groups; + +/// This module implements gadgets related to computing pairings in bilinear +/// groups. +pub mod pairing; + +/// This module describes a trait for allocating new variables in a constraint +/// system. +pub mod alloc; +/// This module describes a trait for checking equality of variables. +pub mod eq; +/// This module describes traits for conditionally selecting a variable from a +/// list of variables. +pub mod select; + +#[allow(missing_docs)] +pub mod prelude { + pub use crate::{ + alloc::*, + bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget}, + eq::*, + fields::{FieldOpsBounds, FieldVar}, + groups::{CurveVar, GroupOpsBounds}, + pairing::PairingVar, + select::*, + R1CSVar, + }; +} + +/// This trait describes some core functionality that is common to high-level +/// variables, such as `Boolean`s, `FieldVar`s, `GroupVar`s, etc. +pub trait R1CSVar { + /// The type of the "native" value that `Self` represents in the constraint + /// system. + type Value: core::fmt::Debug + Eq + Clone; + + /// Returns the underlying `ConstraintSystemRef`. + /// + /// If `self` is a constant value, then this *must* return + /// `ark_relations::r1cs::ConstraintSystemRef::None`. + fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef; + + /// Returns `true` if `self` is a circuit-generation-time constant. + fn is_constant(&self) -> bool { + self.cs().is_none() + } + + /// Returns the value that is assigned to `self` in the underlying + /// `ConstraintSystem`. + fn value(&self) -> Result; +} + +impl> R1CSVar for [T] { + type Value = Vec; + + fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef { + let mut result = ark_relations::r1cs::ConstraintSystemRef::None; + for var in self { + result = var.cs().or(result); + } + result + } + + fn value(&self) -> Result { + let mut result = Vec::new(); + for var in self { + result.push(var.value()?); + } + Ok(result) + } +} + +impl<'a, F: Field, T: 'a + R1CSVar> R1CSVar for &'a T { + type Value = T::Value; + + fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef { + (*self).cs() + } + + fn value(&self) -> Result { + (*self).value() + } +} + +/// A utility trait to convert `Self` to `Result +pub trait Assignment { + /// Converts `self` to `Result`. + fn get(self) -> Result; +} + +impl Assignment for Option { + fn get(self) -> Result { + self.ok_or(ark_relations::r1cs::SynthesisError::AssignmentMissing) + } +} + +/// Specifies how to convert a variable of type `Self` to variables of +/// type `FpVar` +pub trait ToConstraintFieldGadget { + /// Converts `self` to `FpVar` variables. + fn to_constraint_field( + &self, + ) -> Result>, ark_relations::r1cs::SynthesisError>; +} diff --git a/r1cs-std/src/macros.rs b/src/macros.rs similarity index 94% rename from r1cs-std/src/macros.rs rename to src/macros.rs index c943a5d..9e62a90 100644 --- a/r1cs-std/src/macros.rs +++ b/src/macros.rs @@ -1,7 +1,9 @@ #[allow(unused_braces)] -/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type using the impl in `$impl`. +/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type +/// using the impl in `$impl`. /// -/// Used primarily for implementing these traits for `FieldVar`s and `GroupVar`s. +/// Used primarily for implementing these traits for `FieldVar`s and +/// `GroupVar`s. #[macro_export] macro_rules! impl_ops { ( @@ -19,11 +21,14 @@ macro_rules! impl_ops { }; } -/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type using the impl in `$impl`. +/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type +/// using the impl in `$impl`. /// -/// Used primarily for implementing these traits for `FieldVar`s and `GroupVar`s. +/// Used primarily for implementing these traits for `FieldVar`s and +/// `GroupVar`s. /// -/// When compared to `impl_ops`, this macro allows specifying additional trait bounds. +/// When compared to `impl_ops`, this macro allows specifying additional trait +/// bounds. #[macro_export] macro_rules! impl_bounded_ops { ( @@ -47,7 +52,7 @@ macro_rules! impl_bounded_ops { #[tracing::instrument(target = "r1cs", skip(self))] #[allow(unused_braces)] fn $fn(self, other: Self) -> Self::Output { - $impl(self, other) + ($impl)(self, other) } } @@ -127,7 +132,7 @@ macro_rules! impl_bounded_ops { #[tracing::instrument(target = "r1cs", skip(self))] #[allow(unused_braces)] fn $fn(self, other: $native) -> Self::Output { - $constant_impl(self, other) + ($constant_impl)(self, other) } } diff --git a/r1cs-std/src/pairing/bls12/mod.rs b/src/pairing/bls12/mod.rs similarity index 97% rename from r1cs-std/src/pairing/bls12/mod.rs rename to src/pairing/bls12/mod.rs index 25dbb49..4ef7d54 100644 --- a/r1cs-std/src/pairing/bls12/mod.rs +++ b/src/pairing/bls12/mod.rs @@ -1,4 +1,4 @@ -use r1cs_core::SynthesisError; +use ark_relations::r1cs::SynthesisError; use super::PairingVar as PG; @@ -6,10 +6,8 @@ use crate::{ fields::{fp::FpVar, fp12::Fp12Var, fp2::Fp2Var, FieldVar}, groups::bls12::{G1AffineVar, G1PreparedVar, G1Var, G2PreparedVar, G2Var}, }; -use algebra::{ - curves::bls12::{Bls12, Bls12Parameters, TwistType}, - fields::BitIteratorBE, -}; +use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType}; +use ark_ff::fields::BitIteratorBE; use core::marker::PhantomData; /// Specifies the constraints for computing a pairing in a BLS12 bilinear group. diff --git a/r1cs-std/src/pairing/mnt4/mod.rs b/src/pairing/mnt4/mod.rs similarity index 97% rename from r1cs-std/src/pairing/mnt4/mod.rs rename to src/pairing/mnt4/mod.rs index 46d75c6..d8ed2b8 100644 --- a/r1cs-std/src/pairing/mnt4/mod.rs +++ b/src/pairing/mnt4/mod.rs @@ -1,4 +1,4 @@ -use r1cs_core::SynthesisError; +use ark_relations::r1cs::SynthesisError; use super::PairingVar as PG; @@ -9,10 +9,9 @@ use crate::{ G2ProjectiveExtendedVar, G2Var, }, }; -use algebra::{ - curves::mnt4::{MNT4Parameters, MNT4}, - fields::BitIteratorBE, -}; +use ark_ec::mnt4::{MNT4Parameters, MNT4}; +use ark_ff::BitIteratorBE; + use core::marker::PhantomData; /// Specifies the constraints for computing a pairing in a MNT4 bilinear group. @@ -20,7 +19,7 @@ pub struct PairingVar(PhantomData

); type Fp2G

= Fp2Var<

::Fp2Params>; type Fp4G

= Fp4Var<

::Fp4Params>; -/// A variable corresponding to `algebra_core::mnt4::GT`. +/// A variable corresponding to `ark_ec::mnt4::GT`. pub type GTVar

= Fp4G

; impl PairingVar

{ diff --git a/r1cs-std/src/pairing/mnt6/mod.rs b/src/pairing/mnt6/mod.rs similarity index 97% rename from r1cs-std/src/pairing/mnt6/mod.rs rename to src/pairing/mnt6/mod.rs index accf267..72b2973 100644 --- a/r1cs-std/src/pairing/mnt6/mod.rs +++ b/src/pairing/mnt6/mod.rs @@ -1,4 +1,4 @@ -use r1cs_core::SynthesisError; +use ark_relations::r1cs::SynthesisError; use super::PairingVar as PG; @@ -9,10 +9,8 @@ use crate::{ G2ProjectiveExtendedVar, G2Var, }, }; -use algebra::{ - curves::mnt6::{MNT6Parameters, MNT6}, - fields::BitIteratorBE, -}; +use ark_ec::mnt6::{MNT6Parameters, MNT6}; +use ark_ff::fields::BitIteratorBE; use core::marker::PhantomData; /// Specifies the constraints for computing a pairing in a MNT6 bilinear group. @@ -20,7 +18,7 @@ pub struct PairingVar(PhantomData

); type Fp3G

= Fp3Var<

::Fp3Params>; type Fp6G

= Fp6Var<

::Fp6Params>; -/// A variable corresponding to `algebra_core::mnt6::GT`. +/// A variable corresponding to `ark_ec::mnt6::GT`. pub type GTVar

= Fp6G

; impl PairingVar

{ diff --git a/src/pairing/mod.rs b/src/pairing/mod.rs new file mode 100644 index 0000000..157f26d --- /dev/null +++ b/src/pairing/mod.rs @@ -0,0 +1,84 @@ +use crate::prelude::*; +use ark_ec::PairingEngine; +use ark_ff::Field; +use ark_relations::r1cs::SynthesisError; +use core::fmt::Debug; + +/// This module implements pairings for BLS12 bilinear groups. +pub mod bls12; +/// This module implements pairings for MNT4 bilinear groups. +pub mod mnt4; +/// This module implements pairings for MNT6 bilinear groups. +pub mod mnt6; + +/// Specifies the constraints for computing a pairing in the yybilinear group +/// `E`. +pub trait PairingVar::Fq> { + /// An variable representing an element of `G1`. + /// This is the R1CS equivalent of `E::G1Projective`. + type G1Var: CurveVar + + AllocVar + + AllocVar; + + /// An variable representing an element of `G2`. + /// This is the R1CS equivalent of `E::G2Projective`. + type G2Var: CurveVar + + AllocVar + + AllocVar; + + /// An variable representing an element of `GT`. + /// This is the R1CS equivalent of `E::GT`. + type GTVar: FieldVar; + + /// An variable representing cached precomputation that can speed up + /// pairings computations. This is the R1CS equivalent of + /// `E::G1Prepared`. + type G1PreparedVar: ToBytesGadget + + AllocVar + + Clone + + Debug; + /// An variable representing cached precomputation that can speed up + /// pairings computations. This is the R1CS equivalent of + /// `E::G2Prepared`. + type G2PreparedVar: ToBytesGadget + + AllocVar + + Clone + + Debug; + + /// Computes a multi-miller loop between elements + /// of `p` and `q`. + fn miller_loop( + p: &[Self::G1PreparedVar], + q: &[Self::G2PreparedVar], + ) -> Result; + + /// Computes a final exponentiation over `p`. + fn final_exponentiation(p: &Self::GTVar) -> Result; + + /// Computes a pairing over `p` and `q`. + #[tracing::instrument(target = "r1cs")] + fn pairing( + p: Self::G1PreparedVar, + q: Self::G2PreparedVar, + ) -> Result { + let tmp = Self::miller_loop(&[p], &[q])?; + Self::final_exponentiation(&tmp) + } + + /// Computes a product of pairings over the elements in `p` and `q`. + #[must_use] + #[tracing::instrument(target = "r1cs")] + fn product_of_pairings( + p: &[Self::G1PreparedVar], + q: &[Self::G2PreparedVar], + ) -> Result { + let miller_result = Self::miller_loop(p, q)?; + Self::final_exponentiation(&miller_result) + } + + /// Performs the precomputation to generate `Self::G1PreparedVar`. + fn prepare_g1(q: &Self::G1Var) -> Result; + + /// Performs the precomputation to generate `Self::G2PreparedVar`. + fn prepare_g2(q: &Self::G2Var) -> Result; +} diff --git a/r1cs-std/src/select.rs b/src/select.rs similarity index 77% rename from r1cs-std/src/select.rs rename to src/select.rs index 0440711..f79bb1e 100644 --- a/r1cs-std/src/select.rs +++ b/src/select.rs @@ -1,17 +1,18 @@ use crate::prelude::*; -use algebra::Field; -use r1cs_core::SynthesisError; +use ark_ff::Field; +use ark_relations::r1cs::SynthesisError; /// Generates constraints for selecting between one of two values. pub trait CondSelectGadget where Self: Sized, { - /// If `cond == &Boolean::TRUE`, then this returns `true_value`; else, returns `false_value`. + /// If `cond == &Boolean::TRUE`, then this returns `true_value`; else, + /// returns `false_value`. /// /// # Note - /// `Self::conditionally_select(cond, true_value, false_value)?` can be more succinctly written as - /// `cond.select(&true_value, &false_value)?`. + /// `Self::conditionally_select(cond, true_value, false_value)?` can be more + /// succinctly written as `cond.select(&true_value, &false_value)?`. fn conditionally_select( cond: &Boolean, true_value: &Self, @@ -27,11 +28,11 @@ where /// The type of values being looked up. type TableConstant; - /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1] << 1)`, - /// and then outputs `constants[b]`. + /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1] + /// << 1)`, and then outputs `constants[b]`. /// - /// For example, if `bits == [0, 1]`, and `constants == [0, 1, 2, 3]`, this method - /// should output a variable corresponding to `2`. + /// For example, if `bits == [0, 1]`, and `constants == [0, 1, 2, 3]`, this + /// method should output a variable corresponding to `2`. /// /// # Panics /// @@ -51,13 +52,14 @@ where /// The type of values being looked up. type TableConstant; - /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1] << 1)`, - /// and then outputs `constants[b] * c`, where `c = if bits[2] { -1 } else { 1 };`. + /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1] + /// << 1)`, and then outputs `constants[b] * c`, where `c = if bits[2] { + /// -1 } else { 1 };`. /// /// That is, `bits[2]` conditionally negates the looked-up value. /// - /// For example, if `bits == [1, 0, 1]`, and `constants == [0, 1, 2, 3]`, this method - /// should output a variable corresponding to `-1`. + /// For example, if `bits == [1, 0, 1]`, and `constants == [0, 1, 2, 3]`, + /// this method should output a variable corresponding to `-1`. /// /// # Panics ///