From baf18f7e05ce349651b2f54f8cc24e48a4e6cddb Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 5 May 2021 19:18:10 +0200 Subject: [PATCH 01/17] wip --- Cargo.lock | 62 ++++++ zokrates_core/src/embed.rs | 19 +- zokrates_core/src/ir/interpreter.rs | 2 +- zokrates_embed/Cargo.toml | 11 +- zokrates_embed/src/ark.rs | 137 ++++++++++++ zokrates_embed/src/bellman.rs | 289 +++++++++++++++++++++++++ zokrates_embed/src/lib.rs | 314 ++-------------------------- 7 files changed, 523 insertions(+), 311 deletions(-) create mode 100644 zokrates_embed/src/ark.rs create mode 100644 zokrates_embed/src/bellman.rs diff --git a/Cargo.lock b/Cargo.lock index 44f43a5a..7ff88f70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,7 @@ checksum = "eb89b97424403ec9cc22a1df0db748dd7396c9ba5fb5c71a6f0e10ae1d1a7449" dependencies = [ "ark-ec", "ark-ff", + "ark-r1cs-std", "ark-std", ] @@ -88,12 +89,15 @@ checksum = "74b83a7e125e5c611e4a997123effb2f02e3fbc66531dd77751d3016ee920741" dependencies = [ "ark-ec", "ark-ff", + "ark-nonnative-field", + "ark-r1cs-std", "ark-relations", "ark-snark", "ark-std", "blake2", "derivative", "digest 0.9.0", + "tracing", ] [[package]] @@ -158,9 +162,30 @@ dependencies = [ "ark-ec", "ark-ff", "ark-poly", + "ark-r1cs-std", "ark-relations", "ark-serialize", "ark-std", + "derivative", + "tracing", +] + +[[package]] +name = "ark-nonnative-field" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17887af156e9911d1dba5b30d49256d508f82f6a4f765a6fad8b5c637b700353" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-relations", + "ark-std", + "derivative", + "num-bigint 0.4.0", + "num-integer", + "num-traits 0.2.14", + "tracing", ] [[package]] @@ -176,6 +201,22 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "ark-r1cs-std" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a90fea2b84ae4443983d56540360ea004cab952292b7a6535798b6b9dcb7f41" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "derivative", + "num-bigint 0.4.0", + "num-traits 0.2.14", + "tracing", +] + [[package]] name = "ark-relations" version = "0.2.0" @@ -1961,9 +2002,21 @@ checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.67", +] + [[package]] name = "tracing-core" version = "0.1.17" @@ -2345,6 +2398,15 @@ dependencies = [ name = "zokrates_embed" version = "0.1.2" dependencies = [ + "ark-bls12-377", + "ark-bw6-761", + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-gm17", + "ark-r1cs-std", + "ark-relations", + "ark-std", "bellman_ce", "sapling-crypto_ce", ] diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 8a782e34..6ad18b1a 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -14,7 +14,7 @@ cfg_if::cfg_if! { use pairing_ce::bn256::Bn256; use pairing_ce::ff::{PrimeField, PrimeFieldRepr}; use pairing_ce::Engine; - use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint}; + use zokrates_embed::{bellman::generate_sha256_round_constraints, Constraint}; } } @@ -184,14 +184,12 @@ fn flat_expression_from_vec(v: &[(usize, E::Fr)]) -> FlatEx } #[cfg(feature = "bellman")] -impl From> for FlatStatement { - fn from(c: BellmanConstraint) -> FlatStatement { - let rhs_a = flat_expression_from_vec::(&c.a); - let rhs_b = flat_expression_from_vec::(&c.b); - let lhs = flat_expression_from_vec::(&c.c); +fn flat_statement_from_constraint(c: Constraint) -> FlatStatement { + let rhs_a = flat_expression_from_vec::(&c.a); + let rhs_b = flat_expression_from_vec::(&c.b); + let lhs = flat_expression_from_vec::(&c.c); - FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) - } + FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) } /// Returns a flat function which computes a sha256 round @@ -251,7 +249,10 @@ pub fn sha256_round() -> FlatFunction { ) }); // insert flattened statements to represent constraints - let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into()); + let constraint_statements = r1cs + .constraints + .into_iter() + .map(|c| flat_statement_from_constraint::(c)); // define which subset of the witness is returned let outputs: Vec> = output_indices .map(|o| FlatExpression::Identifier(FlatVariable::new(o))) diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 8dc603ff..26ad6630 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fmt; #[cfg(feature = "bellman")] -use zokrates_embed::generate_sha256_round_witness; +use zokrates_embed::bellman::generate_sha256_round_witness; use zokrates_field::Field; pub type ExecutionResult = Result, Error>; diff --git a/zokrates_embed/Cargo.toml b/zokrates_embed/Cargo.toml index 6135df31..854c2a97 100644 --- a/zokrates_embed/Cargo.toml +++ b/zokrates_embed/Cargo.toml @@ -11,4 +11,13 @@ multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"] [dependencies] bellman_ce = { version = "^0.3", default-features = false } -sapling-crypto_ce = { version = "^0.1", default-features = false } \ No newline at end of file +sapling-crypto_ce = { version = "^0.1", default-features = false } +ark-bls12-377 = { version = "^0.2.0", features = ["curve", "r1cs"], default-features = false } +ark-bw6-761 = { version = "^0.2.0", default-features = false } +ark-gm17 = { version = "^0.2.0", default-features = false, features = ["r1cs"] } +ark-relations = { version = "^0.2.0", default-features = false } +ark-crypto-primitives = { version = "^0.2.0", default-features = false, features = ["r1cs"] } +ark-r1cs-std = { version = "^0.2.0", default-features = false } +ark-std = { version = "^0.2.0", default-features = false } +ark-ec = { version = "^0.2.0", default-features = false } +ark-ff = { version = "^0.2.0", default-features = false} \ No newline at end of file diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs new file mode 100644 index 00000000..ff724775 --- /dev/null +++ b/zokrates_embed/src/ark.rs @@ -0,0 +1,137 @@ +use ark_bls12_377::{ + constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fr as BLS12Fr, +}; +use ark_bw6_761::Fr as BW6Fr; +use ark_ec::PairingEngine; +use ark_ff::{Field, One, UniformRand}; +use ark_r1cs_std::bits::boolean::Boolean; +use ark_relations::{ + lc, ns, + r1cs::{ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError}, +}; + +use ark_crypto_primitives::snark::constraints::SNARKGadget; +use ark_crypto_primitives::snark::{CircuitSpecificSetupSNARK, SNARK}; +use ark_gm17::{constraints::GM17VerifierGadget, GM17}; + +use ark_r1cs_std::alloc::AllocVar; +use ark_std::test_rng; + +use crate::Constraint; +use ark_r1cs_std::eq::EqGadget; +use ark_relations::r1cs::{OptimizationGoal, Variable}; +use ark_std::ops::{Mul, MulAssign}; + +#[derive(Copy, Clone)] +struct DummyCircuit { + a: Option, + b: Option, + input_size: usize, +} + +impl ConstraintSynthesizer for DummyCircuit { + fn generate_constraints( + self, + cs: ConstraintSystemRef, + ) -> Result<(), SynthesisError> { + let a = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?; + let b = cs.new_witness_variable(|| self.b.ok_or(SynthesisError::AssignmentMissing))?; + + for _ in 0..self.input_size { + let c = cs.new_input_variable(|| { + let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?; + let b = self.b.ok_or(SynthesisError::AssignmentMissing)?; + + a.mul_assign(&b); + Ok(a) + })?; + cs.enforce_constraint(lc!() + a, lc!() + b, lc!() + c)?; + } + + Ok(()) + } +} + +type GM17Snark = GM17; +type VerifierGadget = GM17VerifierGadget; + +pub fn generate_verify_constraints(input_size: usize) -> (usize, Vec>) { + let mut rng = test_rng(); + let a = BLS12Fr::rand(&mut rng); + let b = BLS12Fr::rand(&mut rng); + let mut c = a.clone(); + c.mul_assign(&b); + + let circuit = DummyCircuit { + a: Some(a), + b: Some(b), + input_size, + }; + + let (pk, vk) = GM17Snark::setup(circuit.clone(), &mut rng).unwrap(); + let proof = GM17Snark::prove(&pk, circuit, &mut rng).unwrap(); + + let cs_sys = ConstraintSystem::::new(); + let cs = ConstraintSystemRef::new(cs_sys); + + let input_gadget = + ::Fr, + ::Fq, + GM17Snark, + >>::InputVar::new_input(ns!(cs, "alloc_inputs"), || Ok(vec![c; input_size])) + .unwrap(); + + let proof_gadget = ::Fr, + ::Fq, + GM17Snark, + >>::ProofVar::new_witness(ns!(cs, "alloc_proof"), || Ok(proof)) + .unwrap(); + + let vk_gadget = ::Fr, + ::Fq, + GM17Snark, + >>::VerifyingKeyVar::new_constant(ns!(cs, "alloc_vk"), vk.clone()) + .unwrap(); + + let res = ::Fr, + ::Fq, + GM17Snark, + >>::verify(&vk_gadget, &input_gadget, &proof_gadget) + .unwrap(); + + let out_index = match &res { + Boolean::Is(x) => var_to_index(x.variable()), + Boolean::Not(x) => var_to_index(x.variable()), + _ => unreachable!(), + }; + + res.conditional_enforce_equal(&Boolean::constant(true), &Boolean::constant(true)) + .unwrap(); + cs.finalize(); + + let matrices = cs.to_matrices().unwrap(); + let constraints: Vec> = matrices + .a + .into_iter() + .zip(matrices.b.into_iter()) + .zip(matrices.c.into_iter()) + .map(|((a, b), c)| Constraint { + a: a.into_iter().map(|(f, index)| (index, f)).collect(), + b: b.into_iter().map(|(f, index)| (index, f)).collect(), + c: c.into_iter().map(|(f, index)| (index, f)).collect(), + }) + .collect(); + + assert!(cs.is_satisfied().unwrap()); + + (out_index, constraints) +} + +fn var_to_index(v: Variable) -> usize { + v.get_index_unchecked(0) + .expect("Could not get variable index") +} diff --git a/zokrates_embed/src/bellman.rs b/zokrates_embed/src/bellman.rs new file mode 100644 index 00000000..dda5d424 --- /dev/null +++ b/zokrates_embed/src/bellman.rs @@ -0,0 +1,289 @@ +extern crate sapling_crypto_ce as sapling_crypto; +use sapling_crypto::bellman; + +use crate::{Constraint, Witness, R1CS}; +use bellman::{ + pairing::{ff::Field, Engine}, + ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, +}; +use sapling_crypto::circuit::{ + boolean::{AllocatedBit, Boolean}, + sha256::sha256_compression_function, + uint32::UInt32, +}; + +fn sha256_round>( + mut cs: CS, + input: &[Option], + current_hash: &[Option], +) -> (Vec, Vec, Vec) { + // Allocate bits for `input` + let input_bits = input + .iter() + .enumerate() + .map(|(index, i)| { + AllocatedBit::alloc::( + &mut cs.namespace(|| format!("input_{}", index)), + Some(*i == Some(::one())), + ) + .unwrap() + }) + .collect::>(); + + // Define Booleans whose values are the defined bits + let input = input_bits + .iter() + .map(|i| Boolean::Is(i.clone())) + .collect::>(); + + // Allocate bits for `current_hash` + let current_hash_bits = current_hash + .iter() + .enumerate() + .map(|(index, i)| { + AllocatedBit::alloc::( + &mut cs.namespace(|| format!("current_hash_{}", index)), + Some(*i == Some(::one())), + ) + .unwrap() + }) + .collect::>(); + + // Define Booleans whose values are the defined bits + let current_hash = current_hash_bits + .chunks(32) + .map(|chunk| { + UInt32::from_bits_be( + &chunk + .iter() + .map(|i| Boolean::Is(i.clone())) + .collect::>(), + ) + }) + .collect::>(); + + // Apply the compression function, returning the 8 bytes of outputs + let res = sha256_compression_function::(&mut cs, &input, ¤t_hash).unwrap(); + + // Extract the 256 bits of output out of the 8 bytes + let output_bits = res + .into_iter() + .flat_map(|u| u.into_bits_be()) + .map(|b| b.get_variable().unwrap().clone()); + + // Return indices of `input`, `current_hash` and `output` in the CS + ( + input_bits + .into_iter() + .map(|b| var_to_index(b.get_variable())) + .collect(), + current_hash_bits + .into_iter() + .map(|b| var_to_index(b.get_variable())) + .collect(), + output_bits + .map(|b| var_to_index(b.get_variable())) + .collect(), + ) +} + +impl ConstraintSystem for Witness { + type Root = Self; + + fn alloc(&mut self, _: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + let index = self.values.len(); + let var = Variable::new_unchecked(Index::Aux(index)); + self.values.push(f().unwrap()); + Ok(var) + } + + fn alloc_input(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + unreachable!("Bellman helpers are not allowed to allocate public variables") + } + + fn enforce(&mut self, _: A, _: LA, _: LB, _: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, + { + // do nothing + } + + fn push_namespace(&mut self, _: N) + where + NR: Into, + N: FnOnce() -> NR, + { + // do nothing + } + + fn pop_namespace(&mut self) { + // do nothing + } + + fn get_root(&mut self) -> &mut Self::Root { + self + } +} + +impl ConstraintSystem for R1CS { + type Root = Self; + + fn alloc(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + // we don't care about the value as we're only generating the CS + let index = self.aux_count.clone(); + let var = Variable::new_unchecked(Index::Aux(index)); + self.aux_count += 1; + Ok(var) + } + + fn alloc_input(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + unreachable!("Bellman helpers are not allowed to allocate public variables") + } + + fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, + { + let a = a(LinearCombination::zero()); + let b = b(LinearCombination::zero()); + let c = c(LinearCombination::zero()); + + let a = a + .as_ref() + .iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + let b = b + .as_ref() + .iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + let c = c + .as_ref() + .iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + + self.constraints.push(Constraint { a, b, c }); + } + + fn push_namespace(&mut self, _: N) + where + NR: Into, + N: FnOnce() -> NR, + { + // do nothing + } + + fn pop_namespace(&mut self) { + // do nothing + } + + fn get_root(&mut self) -> &mut Self::Root { + self + } +} + +pub fn generate_sha256_round_constraints( +) -> (R1CS, Vec, Vec, Vec) { + let mut cs = R1CS::default(); + + let (input_bits, current_hash_bits, output_bits) = + sha256_round::(&mut cs, &[None; 512], &[None; 256]); + + // res is now the allocated bits for `input`, `current_hash` and `sha256_output` + + (cs, input_bits, current_hash_bits, output_bits) +} + +pub fn generate_sha256_round_witness( + input: &[E::Fr], + current_hash: &[E::Fr], +) -> Vec { + assert_eq!(input.len(), 512); + assert_eq!(current_hash.len(), 256); + + let mut cs: Witness = Witness { + values: vec![::one()], + }; + + sha256_round::( + &mut cs, + &input.iter().map(|x| Some(*x)).collect::>(), + ¤t_hash.iter().map(|x| Some(*x)).collect::>(), + ); + + cs.values +} + +fn var_to_index(v: Variable) -> usize { + match v.get_unchecked() { + Index::Aux(i) => i + 1, + Index::Input(0) => 0, + _ => unreachable!("No public variables should have been allocated"), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bellman::pairing::bn256::{Bn256, Fr}; + + #[test] + fn generate_constraints() { + let (_c, input, current_hash, output) = generate_sha256_round_constraints::(); + assert_eq!(input.len(), 512); + assert_eq!(current_hash.len(), 256); + assert_eq!(output.len(), 256); + } + + #[test] + fn generate_witness() { + let witness = + generate_sha256_round_witness::(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]); + assert_eq!(witness.len(), 26935); + } + + #[test] + fn test_cs() { + use sapling_crypto::circuit::test::TestConstraintSystem; + + let mut cs: TestConstraintSystem = TestConstraintSystem::new(); + + let _ = sha256_round( + &mut cs, + &vec![Some(Fr::zero()); 512], + &vec![Some(Fr::one()); 256], + ); + + assert!(cs.is_satisfied()); + } +} diff --git a/zokrates_embed/src/lib.rs b/zokrates_embed/src/lib.rs index b7a3e2d5..b22972f3 100644 --- a/zokrates_embed/src/lib.rs +++ b/zokrates_embed/src/lib.rs @@ -1,26 +1,16 @@ -extern crate sapling_crypto_ce as sapling_crypto; -use sapling_crypto::bellman; +pub mod ark; +pub mod bellman; -use bellman::{ - pairing::{ff::Field, Engine}, - ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, -}; -use sapling_crypto::circuit::{ - boolean::{AllocatedBit, Boolean}, - sha256::sha256_compression_function, - uint32::UInt32, -}; - -#[derive(Debug)] +#[derive(Debug, Clone)] #[allow(clippy::upper_case_acronyms)] -pub struct BellmanR1CS { +pub struct R1CS { pub aux_count: usize, - pub constraints: Vec>, + pub constraints: Vec>, } -impl Default for BellmanR1CS { +impl Default for R1CS { fn default() -> Self { - BellmanR1CS { + Self { aux_count: 0, constraints: vec![], } @@ -28,289 +18,13 @@ impl Default for BellmanR1CS { } #[derive(Debug)] -pub struct BellmanWitness { - pub values: Vec, +pub struct Witness { + pub values: Vec, } -#[derive(Debug, PartialEq)] -pub struct BellmanConstraint { - pub a: Vec<(usize, E::Fr)>, - pub b: Vec<(usize, E::Fr)>, - pub c: Vec<(usize, E::Fr)>, -} - -fn sha256_round>( - mut cs: CS, - input: &[Option], - current_hash: &[Option], -) -> (Vec, Vec, Vec) { - // Allocate bits for `input` - let input_bits = input - .iter() - .enumerate() - .map(|(index, i)| { - AllocatedBit::alloc::( - &mut cs.namespace(|| format!("input_{}", index)), - Some(*i == Some(::one())), - ) - .unwrap() - }) - .collect::>(); - - // Define Booleans whose values are the defined bits - let input = input_bits - .iter() - .map(|i| Boolean::Is(i.clone())) - .collect::>(); - - // Allocate bits for `current_hash` - let current_hash_bits = current_hash - .iter() - .enumerate() - .map(|(index, i)| { - AllocatedBit::alloc::( - &mut cs.namespace(|| format!("current_hash_{}", index)), - Some(*i == Some(::one())), - ) - .unwrap() - }) - .collect::>(); - - // Define Booleans whose values are the defined bits - let current_hash = current_hash_bits - .chunks(32) - .map(|chunk| { - UInt32::from_bits_be( - &chunk - .iter() - .map(|i| Boolean::Is(i.clone())) - .collect::>(), - ) - }) - .collect::>(); - - // Apply the compression function, returning the 8 bytes of outputs - let res = sha256_compression_function::(&mut cs, &input, ¤t_hash).unwrap(); - - // Extract the 256 bits of output out of the 8 bytes - let output_bits = res - .into_iter() - .flat_map(|u| u.into_bits_be()) - .map(|b| b.get_variable().unwrap().clone()); - - // Return indices of `input`, `current_hash` and `output` in the CS - ( - input_bits - .into_iter() - .map(|b| var_to_index(b.get_variable())) - .collect(), - current_hash_bits - .into_iter() - .map(|b| var_to_index(b.get_variable())) - .collect(), - output_bits - .map(|b| var_to_index(b.get_variable())) - .collect(), - ) -} - -impl ConstraintSystem for BellmanWitness { - type Root = Self; - - fn alloc(&mut self, _: A, f: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - let index = self.values.len(); - let var = Variable::new_unchecked(Index::Aux(index)); - self.values.push(f().unwrap()); - Ok(var) - } - - fn alloc_input(&mut self, _: A, _: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - unreachable!("Bellman helpers are not allowed to allocate public variables") - } - - fn enforce(&mut self, _: A, _: LA, _: LB, _: LC) - where - A: FnOnce() -> AR, - AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination, - { - // do nothing - } - - fn push_namespace(&mut self, _: N) - where - NR: Into, - N: FnOnce() -> NR, - { - // do nothing - } - - fn pop_namespace(&mut self) { - // do nothing - } - - fn get_root(&mut self) -> &mut Self::Root { - self - } -} - -impl ConstraintSystem for BellmanR1CS { - type Root = Self; - - fn alloc(&mut self, _: A, _: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - // we don't care about the value as we're only generating the CS - let index = self.aux_count; - let var = Variable::new_unchecked(Index::Aux(index)); - self.aux_count += 1; - Ok(var) - } - - fn alloc_input(&mut self, _: A, _: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - unreachable!("Bellman helpers are not allowed to allocate public variables") - } - - fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) - where - A: FnOnce() -> AR, - AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination, - { - let a = a(LinearCombination::zero()); - let b = b(LinearCombination::zero()); - let c = c(LinearCombination::zero()); - - let a = a - .as_ref() - .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) - .collect(); - let b = b - .as_ref() - .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) - .collect(); - let c = c - .as_ref() - .iter() - .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) - .collect(); - - self.constraints.push(BellmanConstraint { a, b, c }); - } - - fn push_namespace(&mut self, _: N) - where - NR: Into, - N: FnOnce() -> NR, - { - // do nothing - } - - fn pop_namespace(&mut self) { - // do nothing - } - - fn get_root(&mut self) -> &mut Self::Root { - self - } -} - -pub fn generate_sha256_round_constraints( -) -> (BellmanR1CS, Vec, Vec, Vec) { - let mut cs = BellmanR1CS::default(); - - let (input_bits, current_hash_bits, output_bits) = - sha256_round(&mut cs, &[None; 512], &[None; 256]); - - // res is now the allocated bits for `input`, `current_hash` and `sha256_output` - - (cs, input_bits, current_hash_bits, output_bits) -} - -pub fn generate_sha256_round_witness( - input: &[E::Fr], - current_hash: &[E::Fr], -) -> Vec { - assert_eq!(input.len(), 512); - assert_eq!(current_hash.len(), 256); - - let mut cs: BellmanWitness = BellmanWitness { - values: vec![::one()], - }; - - sha256_round( - &mut cs, - &input.iter().map(|x| Some(*x)).collect::>(), - ¤t_hash.iter().map(|x| Some(*x)).collect::>(), - ); - - cs.values -} - -fn var_to_index(v: Variable) -> usize { - match v.get_unchecked() { - Index::Aux(i) => i + 1, - Index::Input(0) => 0, - _ => unreachable!("No public variables should have been allocated"), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bellman::pairing::bn256::{Bn256, Fr}; - - #[test] - fn generate_constraints() { - let (_c, input, current_hash, output) = generate_sha256_round_constraints::(); - assert_eq!(input.len(), 512); - assert_eq!(current_hash.len(), 256); - assert_eq!(output.len(), 256); - } - - #[test] - fn generate_witness() { - let witness = - generate_sha256_round_witness::(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]); - assert_eq!(witness.len(), 26935); - } - - #[test] - fn test_cs() { - use sapling_crypto::circuit::test::TestConstraintSystem; - - let mut cs: TestConstraintSystem = TestConstraintSystem::new(); - - let _ = sha256_round( - &mut cs, - &vec![Some(Fr::zero()); 512], - &vec![Some(Fr::one()); 256], - ); - - assert!(cs.is_satisfied()); - } +#[derive(Default, Debug, PartialEq, Clone)] +pub struct Constraint { + pub a: Vec<(usize, T)>, + pub b: Vec<(usize, T)>, + pub c: Vec<(usize, T)>, } From 59f62d2ffa8f5e365d5564db39b91841e56d4e06 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 7 Jun 2021 13:13:21 +0200 Subject: [PATCH 02/17] wip --- Cargo.lock | 1 + zokrates_core/src/embed.rs | 273 ++++++++-------- zokrates_core/src/imports.rs | 4 + zokrates_core/src/ir/interpreter.rs | 6 +- zokrates_core/src/solvers/mod.rs | 2 +- .../src/static_analysis/propagation.rs | 1 + zokrates_embed/Cargo.toml | 1 + zokrates_embed/src/ark.rs | 308 ++++++++++++------ zokrates_embed/src/bellman.rs | 32 +- 9 files changed, 386 insertions(+), 242 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76585428..3071f1d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2409,6 +2409,7 @@ dependencies = [ "ark-std", "bellman_ce", "sapling-crypto_ce", + "zokrates_field", ] [[package]] diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index e5e5a7c6..932c9367 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -7,17 +7,16 @@ use crate::typed_absy::types::{ ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier, }; use ark_bls12_377::Bls12_377; -use ark_bw6_761::BW6_761; use std::collections::HashMap; -use zokrates_embed::ark::generate_verify_constraints; +use zokrates_embed::ark::{from_ark, generate_verify_constraints}; +use zokrates_embed::bellman::from_bellman; +use zokrates_embed::Constraint; use zokrates_field::{Bn128Field, Field}; cfg_if::cfg_if! { if #[cfg(feature = "bellman")] { use pairing_ce::bn256::Bn256; - use pairing_ce::ff::{PrimeField, PrimeFieldRepr}; - use pairing_ce::Engine; - use zokrates_embed::{bellman::generate_sha256_round_constraints, Constraint}; + use zokrates_embed::{bellman::generate_sha256_round_constraints}; } } @@ -133,19 +132,19 @@ impl FlatEmbed { .inputs(vec![ DeclarationType::array(( DeclarationType::FieldElement, - Some(Constant::Generic(GenericIdentifier { - name: "V", - index: 1, - })), - )), // 18 + (2 * n) - DeclarationType::array(( - DeclarationType::FieldElement, - Some(Constant::Generic(GenericIdentifier { + GenericIdentifier { name: "N", index: 0, - })), + }, )), // inputs - DeclarationType::array((DeclarationType::FieldElement, 8)), // proof + DeclarationType::array((DeclarationType::FieldElement, 8usize)), // proof + DeclarationType::array(( + DeclarationType::FieldElement, + GenericIdentifier { + name: "V", + index: 1, + }, + )), // 18 + (2 * n) // vk ]) .outputs(vec![DeclarationType::Boolean]), } @@ -191,7 +190,7 @@ impl FlatEmbed { #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => sha256_round(), #[cfg(feature = "ark")] - FlatEmbed::Verify => verify(), + FlatEmbed::Verify => verify(generics[0] as usize), _ => unreachable!(), } } @@ -199,37 +198,33 @@ impl FlatEmbed { // util to convert a vector of `(variable_id, coefficient)` to a flat_expression // we build a binary tree of additions by splitting the vector recursively -#[cfg(feature = "bellman")] -fn flat_expression_from_vec(v: &[(usize, E::Fr)]) -> FlatExpression { +fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { match v.len() { 0 => FlatExpression::Number(T::zero()), 1 => { - let (key, val) = v[0]; - let mut res: Vec = vec![]; - val.into_repr().write_le(&mut res).unwrap(); + let (key, val) = v[0].clone(); FlatExpression::Mult( - box FlatExpression::Number(T::from_byte_vector(res)), + box FlatExpression::Number(val), box FlatExpression::Identifier(FlatVariable::new(key)), ) } n => { let (u, v) = v.split_at(n / 2); FlatExpression::Add( - box flat_expression_from_vec::(u), - box flat_expression_from_vec::(v), + box flat_expression_from_vec::(u), + box flat_expression_from_vec::(v), ) } } } -#[cfg(feature = "bellman")] -fn flat_statement_from_constraint(c: Constraint) -> FlatStatement { - let rhs_a = flat_expression_from_vec::(&c.a); - let rhs_b = flat_expression_from_vec::(&c.b); - let lhs = flat_expression_from_vec::(&c.c); - - FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) -} +// fn flat_statement_from_constraint(c: Constraint) -> FlatStatement { +// let rhs_a = flat_expression_from_vec::(&c.a); +// let rhs_b = flat_expression_from_vec::(&c.b); +// let lhs = flat_expression_from_vec::(&c.c); +// +// FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) +// } /// Returns a flat function which computes a sha256 round /// @@ -288,10 +283,15 @@ pub fn sha256_round() -> FlatFunction { ) }); // insert flattened statements to represent constraints - let constraint_statements = r1cs - .constraints - .into_iter() - .map(|c| flat_statement_from_constraint::(c)); + let constraint_statements = r1cs.constraints.into_iter().map(|c| { + let c = from_bellman::(c); + let rhs_a = flat_expression_from_vec::(c.a.as_slice()); + let rhs_b = flat_expression_from_vec::(c.b.as_slice()); + let lhs = flat_expression_from_vec::(c.c.as_slice()); + + FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) + }); + // define which subset of the witness is returned let outputs: Vec> = output_indices .map(|o| FlatExpression::Identifier(FlatVariable::new(o))) @@ -323,114 +323,99 @@ pub fn sha256_round() -> FlatFunction { #[cfg(feature = "ark")] pub fn verify(n: usize) -> FlatFunction { - unreachable!(); - // - // let (output_index, constraints) = generate_verify_constraints(n); - // - // let statements = constraints - // .into_iter() - // .map(|c| flat_statement_from_constraint::(c)) - // .collect(); - // - // //indices of the arguments to the function - // // apply an offset of `variable_count` to get the index of our dummy `input` argument - // let input_argument_indices = input_indices - // .clone() - // .into_iter() - // .map(|i| i + variable_count); - // - // let proof_argument_indices = proof_indices - // .clone() - // .into_iter() - // .map(|i| i + variable_count); - // - // let vk_argument_indices = vk_indices.clone().into_iter().map(|i| i + variable_count); - // - // // define parameters to the function based on the variables - // let proof_arguments = proof_argument_indices.clone().map(|i| FlatParameter { - // id: FlatVariable::new(i), - // private: true, - // }); - // - // let input_arguments = input_argument_indices.clone().map(|i| FlatParameter { - // id: FlatVariable::new(i), - // private: false, - // }); - // - // let vk_arguments = vk_argument_indices.clone().map(|i| FlatParameter { - // id: FlatVariable::new(i), - // private: true, - // }); - // - // let arguments = proof_arguments - // .clone() - // .chain(input_arguments) - // .chain(vk_arguments) - // .collect(); - // - // let one_binding_statement = FlatStatement::Condition( - // FlatExpression::Identifier(FlatVariable::new(0)), - // FlatExpression::Number(T::from(1)), - // ); - // - // let input_binding_statements: Vec<_> = proof_indices - // .clone() - // .chain(input_indices.clone()) - // .chain(vk_indices.clone()) - // .zip( - // proof_argument_indices - // .clone() - // .chain(input_argument_indices.clone()) - // .chain(vk_argument_indices.clone()), - // ) - // .map(|(cs_index, argument_index)| { - // FlatStatement::Condition( - // FlatVariable::new(cs_index).into(), - // FlatVariable::new(argument_index).into(), - // ) - // }) - // .collect(); - // - // let directive_outputs: Vec = output_indices - // .clone() - // .map(|o| FlatVariable::new(o)) - // .collect(); - // - // let outputs: Vec> = directive_outputs - // .iter() - // .enumerate() - // .map(|(_, o)| FlatExpression::Identifier(o.clone())) - // .collect(); - // - // // insert flattened statements to represent constraints - // let constraint_statements: Vec> = - // r1cs.constraints.into_iter().map(|c| to_fs(c)).collect(); - // let return_statement = FlatStatement::Return(FlatExpressionList { - // expressions: outputs.clone(), - // }); - // - // // insert a directive to set the witness based on the zexe gadget and inputs - // let directive_statement = FlatStatement::Directive(FlatDirective { - // outputs: cs_indices.map(|i| FlatVariable::new(i)).collect(), - // inputs: proof_argument_indices - // .chain(input_argument_indices.clone()) - // .chain(vk_argument_indices.clone()) - // .map(|i| FlatVariable::new(i).into()) - // .collect(), - // solver: Solver::Verify(n), - // }); - // - // let statements: Vec<_> = std::iter::once(directive_statement) - // .chain(std::iter::once(one_binding_statement)) - // .chain(input_binding_statements) - // .chain(constraint_statements) - // .chain(std::iter::once(return_statement)) - // .collect(); - // - // FlatFunction { - // arguments, - // statements, - // } + let (out_index, input_indices, proof_indices, vk_indices, constraints, aux_count) = + generate_verify_constraints(n); + + let variable_count = aux_count + 1; // aux + ~one + let cs_indices = 0..variable_count; + let input_indices = input_indices.into_iter(); + let proof_indices = proof_indices.into_iter(); + let vk_indices = vk_indices.into_iter(); + + // indices of the arguments to the function + let input_argument_indices = input_indices.clone().map(|i| i + variable_count); + + let proof_argument_indices = proof_indices.clone().map(|i| i + variable_count); + + let vk_argument_indices = vk_indices.clone().map(|i| i + variable_count); + + let input_arguments = input_argument_indices + .clone() + .map(|i| FlatParameter::private(FlatVariable::new(i))); + + let proof_arguments = proof_argument_indices + .clone() + .map(|i| FlatParameter::private(FlatVariable::new(i))); + + let vk_arguments = vk_argument_indices + .clone() + .map(|i| FlatParameter::private(FlatVariable::new(i))); + + let arguments = input_arguments + .chain(proof_arguments) + .chain(vk_arguments) + .collect(); + + let one_binding_statement = FlatStatement::Condition( + FlatExpression::Identifier(FlatVariable::new(0)), + FlatExpression::Number(T::from(1)), + ); + + let input_binding_statements: Vec<_> = input_indices + .chain(proof_indices) + .chain(vk_indices) + .zip( + input_argument_indices + .clone() + .chain(proof_argument_indices.clone()) + .chain(vk_argument_indices.clone()), + ) + .map(|(cs_index, argument_index)| { + FlatStatement::Condition( + FlatVariable::new(cs_index).into(), + FlatVariable::new(argument_index).into(), + ) + }) + .collect(); + + let constraint_statements: Vec> = constraints + .into_iter() + .map(|c| { + let c: Constraint = from_ark::(c); + let rhs_a = flat_expression_from_vec::(c.a.as_slice()); + let rhs_b = flat_expression_from_vec::(c.b.as_slice()); + let lhs = flat_expression_from_vec::(c.c.as_slice()); + + FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) + }) + .collect(); + + let return_statement = FlatStatement::Return(FlatExpressionList { + expressions: vec![FlatExpression::Identifier(FlatVariable::new(out_index))], + }); + + // insert a directive to set the witness + let directive_statement = FlatStatement::Directive(FlatDirective { + outputs: cs_indices.map(FlatVariable::new).collect(), + inputs: input_argument_indices + .chain(proof_argument_indices) + .chain(vk_argument_indices) + .map(|i| FlatVariable::new(i).into()) + .collect(), + solver: Solver::Verify(n), + }); + + let statements: Vec<_> = std::iter::once(directive_statement) + .chain(std::iter::once(one_binding_statement)) + .chain(input_binding_statements) + .chain(constraint_statements) + .chain(std::iter::once(return_statement)) + .collect(); + + FlatFunction { + arguments, + statements, + } } fn use_variable( diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index f43c388a..26f1f2d9 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -156,6 +156,10 @@ impl Importer { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::U8FromBits), }, + "verify" => SymbolDeclaration { + id: symbol.get_alias(), + symbol: Symbol::Flat(FlatEmbed::Verify), + }, s => { return Err(CompileErrorInner::ImportError( Error::new(format!("Embed {} not found", s)).with_pos(Some(pos)), diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 26ad6630..ed528e42 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -144,7 +144,7 @@ impl Interpreter { inputs: &[T], ) -> Result, String> { let (expected_input_count, expected_output_count) = solver.get_signature(); - assert!(inputs.len() == expected_input_count); + assert_eq!(inputs.len(), expected_input_count); let res = match solver { Solver::ConditionEq => match inputs[0].is_zero() { @@ -233,6 +233,10 @@ impl Interpreter { }) .collect() } + #[cfg(feature = "ark")] + Solver::Verify(_n) => { + todo!() + } }; assert_eq!(res.len(), expected_output_count); diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs index 7845e8d7..c4ff1dea 100644 --- a/zokrates_core/src/solvers/mod.rs +++ b/zokrates_core/src/solvers/mod.rs @@ -37,7 +37,7 @@ impl Solver { #[cfg(feature = "bellman")] Solver::Sha256Round => (768, 26935), #[cfg(feature = "ark")] - Solver::Verify(n) => (26 + 3 * n, 56953 + 3078 * n), // TODO: update this + Solver::Verify(n) => (26 + 3 * n, 0), // TODO: update output count } } } diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 317e1281..48d6157c 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -549,6 +549,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { } } FlatEmbed::Sha256Round => None, + FlatEmbed::Verify => None, }; match r { diff --git a/zokrates_embed/Cargo.toml b/zokrates_embed/Cargo.toml index 854c2a97..dd92cd9b 100644 --- a/zokrates_embed/Cargo.toml +++ b/zokrates_embed/Cargo.toml @@ -10,6 +10,7 @@ wasm = ["bellman_ce/wasm", "sapling-crypto_ce/wasm"] multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"] [dependencies] +zokrates_field = { version = "0.4.0", path = "../zokrates_field", default-features = false } bellman_ce = { version = "^0.3", default-features = false } sapling-crypto_ce = { version = "^0.1", default-features = false } ark-bls12-377 = { version = "^0.2.0", features = ["curve", "r1cs"], default-features = false } diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index a1d182e3..1a51f36d 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -1,54 +1,38 @@ use ark_bls12_377::{ - constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fr as BLS12Fr, + constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fq as BLS12Fq, }; use ark_bw6_761::Fr as BW6Fr; use ark_ec::PairingEngine; -use ark_ff::{Field, UniformRand}; +use ark_ff::{BigInteger, One, PrimeField}; use ark_r1cs_std::bits::boolean::Boolean; use ark_relations::{ - lc, ns, + ns, r1cs::{ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError}, }; use ark_crypto_primitives::snark::constraints::SNARKGadget; -use ark_crypto_primitives::snark::{CircuitSpecificSetupSNARK, SNARK}; +use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARK}; use ark_gm17::{constraints::GM17VerifierGadget, GM17}; -use ark_r1cs_std::ToBitsGadget; +use ark_r1cs_std::ToConstraintFieldGadget; use ark_r1cs_std::alloc::AllocVar; use ark_std::test_rng; use crate::Constraint; -use ark_r1cs_std::eq::EqGadget; +use ark_r1cs_std::fields::fp::FpVar; use ark_relations::r1cs::Variable; -use ark_std::ops::MulAssign; #[derive(Copy, Clone)] -struct DummyCircuit { - a: Option, - b: Option, - input_size: usize, +struct DefaultCircuit { + pub public_input_size: usize, } -impl ConstraintSynthesizer for DummyCircuit { - fn generate_constraints( - self, - cs: ConstraintSystemRef, - ) -> Result<(), SynthesisError> { - let a = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?; - let b = cs.new_witness_variable(|| self.b.ok_or(SynthesisError::AssignmentMissing))?; - - for _ in 0..self.input_size { - let c = cs.new_input_variable(|| { - let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?; - let b = self.b.ok_or(SynthesisError::AssignmentMissing)?; - - a.mul_assign(&b); - Ok(a) - })?; - cs.enforce_constraint(lc!() + a, lc!() + b, lc!() + c)?; +impl ConstraintSynthesizer for DefaultCircuit { + fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { + for _ in 0..self.public_input_size { + let _ = FpVar::::new_input(ns!(cs, "alloc"), || Ok(F::one()))?; + // gadget.to_bits_le()?; } - Ok(()) } } @@ -56,49 +40,45 @@ impl ConstraintSynthesizer for DummyCircuit; type VerifierGadget = GM17VerifierGadget; -// pub fn generate_verify_constraints(input_size: usize) -> (usize, Vec>) { -#[test] -pub fn generate_verify_constraints() { - let input_size: usize = 1; +#[allow(clippy::type_complexity)] +pub fn generate_verify_constraints( + public_input_size: usize, +) -> ( + usize, + Vec, + Vec, + Vec, + Vec>, + usize, +) { let mut rng = test_rng(); - let a = BLS12Fr::rand(&mut rng); - let b = BLS12Fr::rand(&mut rng); - let mut c = a.clone(); - c.mul_assign(&b); + let circuit = DefaultCircuit { public_input_size }; - let circuit = DummyCircuit { - a: Some(a), - b: Some(b), - input_size, - }; - - let (pk, vk) = GM17Snark::setup(circuit.clone(), &mut rng).unwrap(); + let (pk, vk) = GM17Snark::circuit_specific_setup(circuit, &mut rng).unwrap(); let proof = GM17Snark::prove(&pk, circuit, &mut rng).unwrap(); let cs_sys = ConstraintSystem::::new(); let cs = ConstraintSystemRef::new(cs_sys); - let input_gadget = - ::Fr, - ::Fq, - GM17Snark, - >>::InputVar::new_input(ns!(cs, "alloc_inputs"), || Ok(vec![c; input_size])) - .unwrap(); + let mut inputs = Vec::new(); + for _ in 0..public_input_size { + inputs.push(FpVar::new_input(ns!(cs, "alloc_input"), || Ok(BLS12Fq::one())).unwrap()); + } - let input_indices = input_gadget - .clone() - .into_iter() - .map(|f| { - f.iter() - .map(|b| match b { - Boolean::Is(x) => var_to_index(x.variable()), - Boolean::Not(x) => var_to_index(x.variable()), - _ => unreachable!(), - }) - .collect() + let input_indices = inputs + .iter() + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), }) - .collect::>>(); + .collect::>(); + + let input_gadget = ::Fr, + ::Fq, + GM17Snark, + >>::InputVar::from_field_elements(&inputs) + .unwrap(); let proof_gadget = ::Fr, @@ -107,35 +87,128 @@ pub fn generate_verify_constraints() { >>::ProofVar::new_witness(ns!(cs, "alloc_proof"), || Ok(proof)) .unwrap(); - let proof_indices = proof_gadget - .clone() - .a - .to_bits_le() - .unwrap() - .into_iter() - .map(|b| match b { - Boolean::Is(x) => var_to_index(x.variable()), - Boolean::Not(x) => var_to_index(x.variable()), - _ => unreachable!(), - }) - .collect::>(); + let proof_indices: Vec = vec![ + proof_gadget + .a + .to_constraint_field() + .unwrap() + .iter() + .take(2) // [x, y, infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + proof_gadget + .b + .to_constraint_field() + .unwrap() + .iter() + .take(4) // [[x0, y0], [x1, y1], infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + proof_gadget + .c + .to_constraint_field() + .unwrap() + .iter() + .take(2) // [x, y, infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + ] + .into_iter() + .flatten() + .collect(); let vk_gadget = ::Fr, ::Fq, GM17Snark, - >>::VerifyingKeyVar::new_constant(ns!(cs, "alloc_vk"), vk.clone()) + >>::VerifyingKeyVar::new_witness(ns!(cs, "alloc_vk"), || Ok(vk.clone())) .unwrap(); - // let vk_indices = vk_gadget - // .clone() - // .into_iter() - // .map(|f| f.iter().map(|b| match b { - // Boolean::Is(x) => var_to_index(x.variable()), - // Boolean::Not(x) => var_to_index(x.variable()), - // _ => unreachable!(), - // }).collect()) - // .collect::>>(); + let vk_indices: Vec = vec![ + vk_gadget + .h_g2 + .to_constraint_field() + .unwrap() + .iter() + .take(4) // [[x0, y0], [x1, y1], infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + vk_gadget + .g_alpha_g1 + .to_constraint_field() + .unwrap() + .iter() + .take(2) // [x, y, infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + vk_gadget + .h_beta_g2 + .to_constraint_field() + .unwrap() + .iter() + .take(4) // [[x0, y0], [x1, y1], infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + vk_gadget + .g_gamma_g1 + .to_constraint_field() + .unwrap() + .iter() + .take(2) // [x, y, infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + vk_gadget + .h_gamma_g2 + .to_constraint_field() + .unwrap() + .iter() + .take(4) // [[x0, y0], [x1, y1], infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>(), + vk_gadget + .query + .iter() + .map(|q| { + q.to_constraint_field() + .unwrap() + .iter() + .take(2) // [x, y, infinity] - infinity + .map(|f| match f { + FpVar::Var(fp) => var_to_index(&fp.variable), + _ => unreachable!(), + }) + .collect::>() + }) + .flatten() + .collect::>(), + ] + .into_iter() + .flatten() + .collect::>(); let res = ::Fr, @@ -145,13 +218,12 @@ pub fn generate_verify_constraints() { .unwrap(); let out_index = match &res { - Boolean::Is(x) => var_to_index(x.variable()), - Boolean::Not(x) => var_to_index(x.variable()), + Boolean::Is(x) => var_to_index(&x.variable()), + Boolean::Not(x) => var_to_index(&x.variable()), _ => unreachable!(), }; - res.conditional_enforce_equal(&Boolean::constant(true), &Boolean::constant(true)) - .unwrap(); + // res.conditional_enforce_equal(&Boolean::TRUE, &Boolean::TRUE).unwrap(); cs.finalize(); let matrices = cs.to_matrices().unwrap(); @@ -167,16 +239,62 @@ pub fn generate_verify_constraints() { }) .collect(); - assert!(cs.is_satisfied().unwrap()); + // println!("input_indices: {:?}", input_indices); + // println!("proof_indices: {:?}", proof_indices); + // println!("vk_indices: {:?}", vk_indices); + // println!("out_index: {:?}", out_index); - println!("{}", input_indices.len()); - println!("{}", proof_indices.len()); - // println!("{}", vk_indices.len()); + assert!( + cs.is_satisfied().unwrap(), + "Constraint not satisfied: {}", + cs.which_is_unsatisfied().unwrap().unwrap_or_default() + ); - // (out_index, constraints) + ( + out_index, + input_indices, + proof_indices, + vk_indices, + constraints, + cs.num_witness_variables(), + ) } -fn var_to_index(v: Variable) -> usize { +#[test] +fn generate_verify_constraints_test() { + let _ = generate_verify_constraints(2); +} + +fn var_to_index(v: &Variable) -> usize { v.get_index_unchecked(0) .expect("Could not get variable index") } + +pub fn from_ark(c: Constraint) -> Constraint { + Constraint { + a: c.a + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + b: c.b + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + c: c.c + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + } +} diff --git a/zokrates_embed/src/bellman.rs b/zokrates_embed/src/bellman.rs index dda5d424..b178f295 100644 --- a/zokrates_embed/src/bellman.rs +++ b/zokrates_embed/src/bellman.rs @@ -6,6 +6,7 @@ use bellman::{ pairing::{ff::Field, Engine}, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, }; +use sapling_crypto::bellman::pairing::ff::{PrimeField, PrimeFieldRepr}; use sapling_crypto::circuit::{ boolean::{AllocatedBit, Boolean}, sha256::sha256_compression_function, @@ -149,7 +150,7 @@ impl ConstraintSystem for R1CS { AR: Into, { // we don't care about the value as we're only generating the CS - let index = self.aux_count.clone(); + let index = self.aux_count; let var = Variable::new_unchecked(Index::Aux(index)); self.aux_count += 1; Ok(var) @@ -252,6 +253,35 @@ fn var_to_index(v: Variable) -> usize { } } +pub fn from_bellman(c: Constraint) -> Constraint { + Constraint { + a: c.a + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + b: c.b + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + c: c.c + .into_iter() + .map(|(index, fq)| { + let mut res: Vec = vec![]; + fq.into_repr().write_le(&mut res).unwrap(); + (index, T::from_byte_vector(res)) + }) + .collect(), + } +} + #[cfg(test)] mod tests { use super::*; From f9f42b7cbac8a03c30900441a08321df8897bf49 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 16 Jun 2021 15:59:41 +0200 Subject: [PATCH 03/17] remove dummy circuit --- zokrates_core/src/embed.rs | 3 +- zokrates_embed/src/ark.rs | 283 ++++++++++++++----------------------- 2 files changed, 108 insertions(+), 178 deletions(-) diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 932c9367..8a9365fc 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -323,10 +323,9 @@ pub fn sha256_round() -> FlatFunction { #[cfg(feature = "ark")] pub fn verify(n: usize) -> FlatFunction { - let (out_index, input_indices, proof_indices, vk_indices, constraints, aux_count) = + let (out_index, input_indices, proof_indices, vk_indices, constraints, variable_count) = generate_verify_constraints(n); - let variable_count = aux_count + 1; // aux + ~one let cs_indices = 0..variable_count; let input_indices = input_indices.into_iter(); let proof_indices = proof_indices.into_iter(); diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 1a51f36d..5cf4d92f 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -7,39 +7,35 @@ use ark_ff::{BigInteger, One, PrimeField}; use ark_r1cs_std::bits::boolean::Boolean; use ark_relations::{ ns, - r1cs::{ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError}, + r1cs::{ConstraintSystem, ConstraintSystemRef}, }; use ark_crypto_primitives::snark::constraints::SNARKGadget; -use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARK}; -use ark_gm17::{constraints::GM17VerifierGadget, GM17}; -use ark_r1cs_std::ToConstraintFieldGadget; - -use ark_r1cs_std::alloc::AllocVar; -use ark_std::test_rng; +use ark_crypto_primitives::snark::FromFieldElementsGadget; +use ark_gm17::{constraints::GM17VerifierGadget, Proof, VerifyingKey, GM17}; +use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; use crate::Constraint; use ark_r1cs_std::fields::fp::FpVar; -use ark_relations::r1cs::Variable; -#[derive(Copy, Clone)] -struct DefaultCircuit { - pub public_input_size: usize, -} - -impl ConstraintSynthesizer for DefaultCircuit { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - for _ in 0..self.public_input_size { - let _ = FpVar::::new_input(ns!(cs, "alloc"), || Ok(F::one()))?; - // gadget.to_bits_le()?; +macro_rules! var { + ($f:expr, $offset:expr) => { + match $f { + FpVar::Var(ref fp) => { + let var = &fp.variable; + var.get_index_unchecked($offset).unwrap() + } + _ => unreachable!("expected variable, found constant"), } - Ok(()) - } + }; } type GM17Snark = GM17; type VerifierGadget = GM17VerifierGadget; +type G1 = as PairingEngine>::G1Affine; +type G2 = as PairingEngine>::G2Affine; + #[allow(clippy::type_complexity)] pub fn generate_verify_constraints( public_input_size: usize, @@ -51,12 +47,6 @@ pub fn generate_verify_constraints( Vec>, usize, ) { - let mut rng = test_rng(); - let circuit = DefaultCircuit { public_input_size }; - - let (pk, vk) = GM17Snark::circuit_specific_setup(circuit, &mut rng).unwrap(); - let proof = GM17Snark::prove(&pk, circuit, &mut rng).unwrap(); - let cs_sys = ConstraintSystem::::new(); let cs = ConstraintSystemRef::new(cs_sys); @@ -65,167 +55,117 @@ pub fn generate_verify_constraints( inputs.push(FpVar::new_input(ns!(cs, "alloc_input"), || Ok(BLS12Fq::one())).unwrap()); } - let input_indices = inputs - .iter() - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(); - - let input_gadget = ::Fr, ::Fq, GM17Snark, >>::InputVar::from_field_elements(&inputs) .unwrap(); - let proof_gadget = ::Fr, ::Fq, GM17Snark, - >>::ProofVar::new_witness(ns!(cs, "alloc_proof"), || Ok(proof)) + >>::new_proof_unchecked( + ns!(cs, "alloc_proof"), + || { + Ok(Proof { + a: G1::default(), + b: G2::default(), + c: G1::default(), + }) + }, + AllocationMode::Witness, + ) .unwrap(); - let proof_indices: Vec = vec![ - proof_gadget - .a - .to_constraint_field() - .unwrap() - .iter() - .take(2) // [x, y, infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - proof_gadget - .b - .to_constraint_field() - .unwrap() - .iter() - .take(4) // [[x0, y0], [x1, y1], infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - proof_gadget - .c - .to_constraint_field() - .unwrap() - .iter() - .take(2) // [x, y, infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - ] - .into_iter() - .flatten() - .collect(); - - let vk_gadget = ::Fr, ::Fq, GM17Snark, - >>::VerifyingKeyVar::new_witness(ns!(cs, "alloc_vk"), || Ok(vk.clone())) + >>::new_verification_key_unchecked( + ns!(cs, "alloc_vk"), + || { + Ok(VerifyingKey { + h_g2: G2::default(), + g_alpha_g1: G1::default(), + h_beta_g2: G2::default(), + g_gamma_g1: G1::default(), + h_gamma_g2: G2::default(), + query: vec![G1::default(); public_input_size + 1], + }) + }, + AllocationMode::Witness, + ) .unwrap(); - let vk_indices: Vec = vec![ - vk_gadget - .h_g2 - .to_constraint_field() - .unwrap() - .iter() - .take(4) // [[x0, y0], [x1, y1], infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - vk_gadget - .g_alpha_g1 - .to_constraint_field() - .unwrap() - .iter() - .take(2) // [x, y, infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - vk_gadget - .h_beta_g2 - .to_constraint_field() - .unwrap() - .iter() - .take(4) // [[x0, y0], [x1, y1], infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - vk_gadget - .g_gamma_g1 - .to_constraint_field() - .unwrap() - .iter() - .take(2) // [x, y, infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - vk_gadget - .h_gamma_g2 - .to_constraint_field() - .unwrap() - .iter() - .take(4) // [[x0, y0], [x1, y1], infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>(), - vk_gadget - .query - .iter() - .map(|q| { - q.to_constraint_field() - .unwrap() - .iter() - .take(2) // [x, y, infinity] - infinity - .map(|f| match f { - FpVar::Var(fp) => var_to_index(&fp.variable), - _ => unreachable!(), - }) - .collect::>() - }) - .flatten() - .collect::>(), - ] - .into_iter() - .flatten() - .collect::>(); - let res = ::Fr, ::Fq, GM17Snark, - >>::verify(&vk_gadget, &input_gadget, &proof_gadget) + >>::verify(&dummy_vk, &dummy_inputs, &dummy_proof) .unwrap(); + cs.finalize(); + + let num_instance_variables = cs.num_instance_variables(); + let input_indices = inputs.iter().map(|f| var!(f, 0)).collect::>(); + + let proof_indices: Vec = vec![ + var!(dummy_proof.a.x, num_instance_variables), + var!(dummy_proof.a.y, num_instance_variables), + var!(dummy_proof.b.x.c0, num_instance_variables), + var!(dummy_proof.b.x.c1, num_instance_variables), + var!(dummy_proof.b.y.c0, num_instance_variables), + var!(dummy_proof.b.y.c1, num_instance_variables), + var!(dummy_proof.c.x, num_instance_variables), + var!(dummy_proof.c.y, num_instance_variables), + ]; + + let mut vk_indices: Vec = vec![ + var!(dummy_vk.h_g2.x.c0, num_instance_variables), + var!(dummy_vk.h_g2.x.c1, num_instance_variables), + var!(dummy_vk.h_g2.y.c0, num_instance_variables), + var!(dummy_vk.h_g2.y.c1, num_instance_variables), + var!(dummy_vk.g_alpha_g1.x, num_instance_variables), + var!(dummy_vk.g_alpha_g1.y, num_instance_variables), + var!(dummy_vk.h_beta_g2.x.c0, num_instance_variables), + var!(dummy_vk.h_beta_g2.x.c1, num_instance_variables), + var!(dummy_vk.h_beta_g2.y.c0, num_instance_variables), + var!(dummy_vk.h_beta_g2.y.c1, num_instance_variables), + var!(dummy_vk.g_gamma_g1.x, num_instance_variables), + var!(dummy_vk.g_gamma_g1.y, num_instance_variables), + var!(dummy_vk.h_gamma_g2.x.c0, num_instance_variables), + var!(dummy_vk.h_gamma_g2.x.c1, num_instance_variables), + var!(dummy_vk.h_gamma_g2.y.c0, num_instance_variables), + var!(dummy_vk.h_gamma_g2.y.c1, num_instance_variables), + ]; + + vk_indices.extend( + dummy_vk + .query + .iter() + .map(|q| { + vec![ + var!(q.x, num_instance_variables), + var!(q.y, num_instance_variables), + ] + }) + .flatten(), + ); + let out_index = match &res { - Boolean::Is(x) => var_to_index(&x.variable()), - Boolean::Not(x) => var_to_index(&x.variable()), + Boolean::Is(x) => x + .variable() + .get_index_unchecked(num_instance_variables) + .unwrap(), + Boolean::Not(x) => x + .variable() + .get_index_unchecked(num_instance_variables) + .unwrap(), _ => unreachable!(), }; - // res.conditional_enforce_equal(&Boolean::TRUE, &Boolean::TRUE).unwrap(); - cs.finalize(); - let matrices = cs.to_matrices().unwrap(); let constraints: Vec> = matrices .a @@ -239,16 +179,12 @@ pub fn generate_verify_constraints( }) .collect(); - // println!("input_indices: {:?}", input_indices); - // println!("proof_indices: {:?}", proof_indices); - // println!("vk_indices: {:?}", vk_indices); - // println!("out_index: {:?}", out_index); - - assert!( - cs.is_satisfied().unwrap(), - "Constraint not satisfied: {}", - cs.which_is_unsatisfied().unwrap().unwrap_or_default() - ); + println!("num_instance_variables: {:?}", num_instance_variables); + println!("input_indices: {:?}", input_indices); + println!("proof_indices: {:?}", proof_indices); + println!("vk_indices: {:?}", vk_indices); + println!("out_index: {:?}", out_index); + println!("constraint_count: {:?}", cs.num_constraints()); ( out_index, @@ -265,11 +201,6 @@ fn generate_verify_constraints_test() { let _ = generate_verify_constraints(2); } -fn var_to_index(v: &Variable) -> usize { - v.get_index_unchecked(0) - .expect("Could not get variable index") -} - pub fn from_ark(c: Constraint) -> Constraint { Constraint { a: c.a From 97c7ec9730afba2598c91457cff14d8b5cfbdb71 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 21 Jun 2021 19:29:48 +0200 Subject: [PATCH 04/17] add instance variable count to total --- zokrates_embed/src/ark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 5cf4d92f..74f745ed 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -192,7 +192,7 @@ pub fn generate_verify_constraints( proof_indices, vk_indices, constraints, - cs.num_witness_variables(), + cs.num_witness_variables() + cs.num_instance_variables(), ) } From 0567ea09589cec45d589359021986e0348267791 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 23 Jun 2021 20:34:00 +0200 Subject: [PATCH 05/17] fix features --- zokrates_cli/src/ops/compute_witness.rs | 6 +- zokrates_core/src/embed.rs | 23 ++-- zokrates_core/src/imports.rs | 9 +- zokrates_core/src/ir/interpreter.rs | 9 +- zokrates_core/src/solvers/mod.rs | 6 +- .../src/static_analysis/propagation.rs | 2 + zokrates_embed/src/ark.rs | 127 +++++++++++++++++- zokrates_stdlib/stdlib/gadgets/verify.zok | 7 + .../tests/tests/gadgets/verify.json | 46 +++++++ .../tests/tests/gadgets/verify.zok | 5 + 10 files changed, 213 insertions(+), 27 deletions(-) create mode 100644 zokrates_stdlib/stdlib/gadgets/verify.zok create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify.json create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify.zok diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 9da9eb38..24e45433 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -82,9 +82,9 @@ fn cli_compute(ir_prog: ir::Prog, sub_matches: &ArgMatches) -> Resu let verbose = sub_matches.is_present("verbose"); // print deserialized flattened program if in verbose mode - if verbose { - println!("{}", ir_prog); - } + // if verbose { + // println!("{}", ir_prog); + // } let is_stdin = sub_matches.is_present("stdin"); let is_abi = sub_matches.is_present("abi"); diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 8a9365fc..5785c62e 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -6,17 +6,20 @@ use crate::solvers::Solver; use crate::typed_absy::types::{ ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier, }; -use ark_bls12_377::Bls12_377; use std::collections::HashMap; -use zokrates_embed::ark::{from_ark, generate_verify_constraints}; -use zokrates_embed::bellman::from_bellman; -use zokrates_embed::Constraint; use zokrates_field::{Bn128Field, Field}; cfg_if::cfg_if! { if #[cfg(feature = "bellman")] { use pairing_ce::bn256::Bn256; - use zokrates_embed::{bellman::generate_sha256_round_constraints}; + use zokrates_embed::{bellman::{from_bellman, generate_sha256_round_constraints}}; + } +} + +cfg_if::cfg_if! { + if #[cfg(feature = "ark")] { + use ark_bls12_377::Bls12_377; + use zokrates_embed::ark::{from_ark, generate_verify_constraints}; } } @@ -218,14 +221,6 @@ fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { } } -// fn flat_statement_from_constraint(c: Constraint) -> FlatStatement { -// let rhs_a = flat_expression_from_vec::(&c.a); -// let rhs_b = flat_expression_from_vec::(&c.b); -// let lhs = flat_expression_from_vec::(&c.c); -// -// FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) -// } - /// Returns a flat function which computes a sha256 round /// /// # Remarks @@ -380,7 +375,7 @@ pub fn verify(n: usize) -> FlatFunction { let constraint_statements: Vec> = constraints .into_iter() .map(|c| { - let c: Constraint = from_ark::(c); + let c = from_ark::(c); let rhs_a = flat_expression_from_vec::(c.a.as_slice()); let rhs_b = flat_expression_from_vec::(c.b.as_slice()); let lhs = flat_expression_from_vec::(c.c.as_slice()); diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 26f1f2d9..b94d5f87 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -120,6 +120,11 @@ impl Importer { } } } + #[cfg(feature = "ark")] + "verify" => SymbolDeclaration { + id: symbol.get_alias(), + symbol: Symbol::Flat(FlatEmbed::Verify), + }, "unpack" => SymbolDeclaration { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::Unpack), @@ -156,10 +161,6 @@ impl Importer { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::U8FromBits), }, - "verify" => SymbolDeclaration { - id: symbol.get_alias(), - symbol: Symbol::Flat(FlatEmbed::Verify), - }, s => { return Err(CompileErrorInner::ImportError( Error::new(format!("Embed {} not found", s)).with_pos(Some(pos)), diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index ed528e42..1dc71f8a 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -6,6 +6,7 @@ use pairing_ce::bn256::Bn256; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fmt; +use zokrates_embed::ark::generate_verify_witness; #[cfg(feature = "bellman")] use zokrates_embed::bellman::generate_sha256_round_witness; use zokrates_field::Field; @@ -234,9 +235,11 @@ impl Interpreter { .collect() } #[cfg(feature = "ark")] - Solver::Verify(_n) => { - todo!() - } + Solver::Verify(n) => generate_verify_witness( + &inputs[..*n], + &inputs[*n..*n + 8usize], + &inputs[*n + 8usize..], + ), }; assert_eq!(res.len(), expected_output_count); diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs index c4ff1dea..a6622931 100644 --- a/zokrates_core/src/solvers/mod.rs +++ b/zokrates_core/src/solvers/mod.rs @@ -1,3 +1,4 @@ +use num::Integer; use serde::{Deserialize, Serialize}; use std::fmt; @@ -37,7 +38,10 @@ impl Solver { #[cfg(feature = "bellman")] Solver::Sha256Round => (768, 26935), #[cfg(feature = "ark")] - Solver::Verify(n) => (26 + 3 * n, 0), // TODO: update output count + Solver::Verify(n) => ( + 26 + 3 * n, + (41991 + (3570 * n)) + ((n.div_ceil(&2usize) - 1) * 2816), + ), } } } diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 48d6157c..3a08ef74 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -548,7 +548,9 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { _ => unreachable!("should be a field value"), } } + #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => None, + #[cfg(feature = "ark")] FlatEmbed::Verify => None, }; diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 74f745ed..99e59325 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -1,5 +1,6 @@ use ark_bls12_377::{ constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fq as BLS12Fq, + Fq2 as BLS12Fq2, }; use ark_bw6_761::Fr as BW6Fr; use ark_ec::PairingEngine; @@ -17,6 +18,8 @@ use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; use crate::Constraint; use ark_r1cs_std::fields::fp::FpVar; +use std::str::FromStr; +use zokrates_field::{Field}; macro_rules! var { ($f:expr, $offset:expr) => { @@ -36,6 +39,32 @@ type VerifierGadget = GM17VerifierGadget; type G1 = as PairingEngine>::G1Affine; type G2 = as PairingEngine>::G2Affine; +macro_rules! g1 { + ($e:expr, $i0:expr, $i1:expr) => { + G1::new( + BLS12Fq::from_str(&*$e[$i0].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*$e[$i1].to_dec_string()).unwrap(), + false, + ) + }; +} + +macro_rules! g2 { + ($e:expr, $i0:expr, $i1:expr, $i2:expr, $i3:expr) => { + G2::new( + BLS12Fq2::new( + BLS12Fq::from_str(&*$e[$i0].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*$e[$i1].to_dec_string()).unwrap(), + ), + BLS12Fq2::new( + BLS12Fq::from_str(&*$e[$i2].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*$e[$i3].to_dec_string()).unwrap(), + ), + false, + ) + }; +} + #[allow(clippy::type_complexity)] pub fn generate_verify_constraints( public_input_size: usize, @@ -62,6 +91,7 @@ pub fn generate_verify_constraints( >>::InputVar::from_field_elements(&inputs) .unwrap(); + let dummy_inputs_len = dummy_inputs.clone().into_iter().len(); let dummy_proof = ::Fr, ::Fq, @@ -92,7 +122,7 @@ pub fn generate_verify_constraints( h_beta_g2: G2::default(), g_gamma_g1: G1::default(), h_gamma_g2: G2::default(), - query: vec![G1::default(); public_input_size + 1], + query: vec![G1::default(); dummy_inputs_len], }) }, AllocationMode::Witness, @@ -179,12 +209,18 @@ pub fn generate_verify_constraints( }) .collect(); + /* println!("num_instance_variables: {:?}", num_instance_variables); println!("input_indices: {:?}", input_indices); println!("proof_indices: {:?}", proof_indices); println!("vk_indices: {:?}", vk_indices); println!("out_index: {:?}", out_index); println!("constraint_count: {:?}", cs.num_constraints()); + println!( + "variable_count: {:?}", + cs.num_witness_variables() + cs.num_instance_variables() + ); + */ ( out_index, @@ -196,10 +232,97 @@ pub fn generate_verify_constraints( ) } +pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> Vec { + assert_eq!(proof.len(), 8); + assert_eq!(vk.len(), 18 + (2 * inputs.len())); + + let cs_sys = ConstraintSystem::::new(); + let cs = ConstraintSystemRef::new(cs_sys); + + let mut input_vec = Vec::new(); + for input in inputs { + input_vec.push( + FpVar::new_input(ns!(cs, "alloc_input"), || { + Ok(BLS12Fq::from_str(&*input.to_dec_string()).unwrap()) + }) + .unwrap(), + ); + } + + let inputs = ::Fr, + ::Fq, + GM17Snark, + >>::InputVar::from_field_elements(&input_vec) + .unwrap(); + + let proof = ::Fr, + ::Fq, + GM17Snark, + >>::new_proof_unchecked( + ns!(cs, "alloc_proof"), + || { + Ok(Proof { + a: g1!(proof, 0, 1), + b: g2!(proof, 2, 3, 4, 5), + c: g1!(proof, 6, 7), + }) + }, + AllocationMode::Witness, + ) + .unwrap(); + + let vk = ::Fr, + ::Fq, + GM17Snark, + >>::new_verification_key_unchecked( + ns!(cs, "alloc_vk"), + || { + Ok(VerifyingKey { + h_g2: g2!(vk, 0, 1, 2, 3), + g_alpha_g1: g1!(vk, 4, 5), + h_beta_g2: g2!(vk, 6, 7, 8, 9), + g_gamma_g1: g1!(vk, 10, 11), + h_gamma_g2: g2!(vk, 12, 13, 14, 15), + query: (16..vk.len()) + .collect::>() + .chunks(2) + .map(|c| g1!(vk, c[0], c[1])) + .collect(), + }) + }, + AllocationMode::Witness, + ) + .unwrap(); + + let _ = ::Fr, + ::Fq, + GM17Snark, + >>::verify(&vk, &inputs, &proof) + .unwrap(); + + cs.finalize(); + + let cs = cs.borrow().unwrap(); + let witness_variables: Vec = cs.witness_assignment.clone(); + + cs.instance_assignment + .clone() + .into_iter() + .chain(witness_variables) + .map(|fq| T::from_byte_vector(fq.into_repr().to_bytes_le())) + .collect() +} + +/* #[test] fn generate_verify_constraints_test() { - let _ = generate_verify_constraints(2); + let _ = generate_verify_constraints(1); } +*/ pub fn from_ark(c: Constraint) -> Constraint { Constraint { diff --git a/zokrates_stdlib/stdlib/gadgets/verify.zok b/zokrates_stdlib/stdlib/gadgets/verify.zok new file mode 100644 index 00000000..731161f9 --- /dev/null +++ b/zokrates_stdlib/stdlib/gadgets/verify.zok @@ -0,0 +1,7 @@ +#pragma curve bw6_761 + +from "EMBED" import verify + +def main(field[N] inputs, field[8] proof, field[V] vk) -> bool: + assert(18 + (2 * N) == V) + return verify(inputs, proof, vk) \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/gadgets/verify.json b/zokrates_stdlib/tests/tests/gadgets/verify.json new file mode 100644 index 00000000..b5f95506 --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify.json @@ -0,0 +1,46 @@ +{ + "entry_point": "./tests/tests/gadgets/verify.zok", + "curves": ["Bw6_761"], + "tests": [ + { + "input": { + "values": [ + "14854361253166356985827940126714566475275412573126716429346293669288261212877767002588736768495892518280555332082", + "213732210873464696846782550184555137228225514409080200587629835423679101735680889388490505365220726936653232900722", + "87538607630632344401950048588801759619324114043687193925268161368645768079512372989046887060116208844098222887523", + "5657143080315521889991799092902512094315245718355471372723437558193333983953910948320586493950523700874011063560", + "57443068623489368358651325326719858590550354409074784986003051193396111859230778144944186401073595967957696940521", + "239017299818740889416561988179003000999440599788233589838386981563280711497257601212385904595560069610856834048609", + "210817940648895568697680255986492415724502544301527123629003695092329489846191300997148203752109923795482648905049", + "104796720182429147963427519368170838521257629224027565408974396362211239635140389257768036297199752289691646178885", + "1", + "237849156256827398282019388933972533154056715710612980343582379691235964002811111531637163291964836316287473866944", + "121324456153144638357885760921484124420296650752569739652599982435599667566663818850130137668154167962818124679946", + "73600332144130508132510040050892177274732799381796146541825372722030832659283233558443467575385522990242420388929", + "44732797483932307692113794160403754043679743522093845554740681666841720206796756514002159097899004452746371432672", + "11133333007786916806537653763736510041397904969121754556887982143919681840159919608974969747422557814633960596319", + "90561577672782365102721874737156537447800052875073945376839636447536979602099666234669817779872333362600029687267", + "5450223346768511418345330845468131514992561567665451102957435878264997759483533580796977034429945593412389724558", + "235853237950439075722577332685219091953664185148611937130324227335365792837509030624805785387473218289296335533890", + "89396333230537847366322364436342481695658547414236326093675863540417141298105682739791578537835191912089484203681", + "115830385654423364502343021113073028365721746246232924567075277636234346135515984504152518055968175024342452068593", + "11263613907940703510226043272578077114062568830909561875804816268614922948545123959608046723806484765856945366386", + "85099371298035679603247495321780481321948685394995318303952199333118698031562067002765732094949837892213467834453", + "237849156256827398282019388933972533154056715710612980343582379691235964002811111531637163291964836316287473866944", + "121324456153144638357885760921484124420296650752569739652599982435599667566663818850130137668154167962818124679946", + "73600332144130508132510040050892177274732799381796146541825372722030832659283233558443467575385522990242420388929", + "44732797483932307692113794160403754043679743522093845554740681666841720206796756514002159097899004452746371432672", + "147751075268067473595930126919015490789314687953476809410426208666203744311411068892162888393693647317357680788622", + "253223744369647051774471619931702227054534749249995484100066505466186263584769989160049762529720081850824722544795", + "226753899873357669326157359116609350824063726018578587491538482132599227769745752321252816012800490263881222618536", + "176875521207730154886136120529839690202784860066517231969835480145708453592054364059780266900035568058186799176840" + ] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} diff --git a/zokrates_stdlib/tests/tests/gadgets/verify.zok b/zokrates_stdlib/tests/tests/gadgets/verify.zok new file mode 100644 index 00000000..13f89bad --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify.zok @@ -0,0 +1,5 @@ +from "gadgets/verify" import main as verify + +def main(private field[8] proof, private field[1] inputs, private field[20] vk) -> bool: + bool result = verify(inputs, proof, vk) + return result \ No newline at end of file From f57c3a486913e6a87586a25cf8fd84348148ecb2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 28 Jun 2021 13:38:45 +0200 Subject: [PATCH 06/17] working verifier --- zokrates_cli/src/ops/compute_witness.rs | 6 +- zokrates_core/src/proof_system/mod.rs | 6 +- zokrates_core/src/solvers/mod.rs | 6 +- zokrates_embed/src/ark.rs | 222 ++++++++++-------- .../gadgets/{verify.json => verify_1.json} | 4 +- .../gadgets/{verify.zok => verify_1.zok} | 2 +- .../tests/tests/gadgets/verify_2.json | 49 ++++ .../tests/tests/gadgets/verify_2.zok | 5 + .../tests/tests/gadgets/verify_5.json | 58 +++++ .../tests/tests/gadgets/verify_5.zok | 5 + 10 files changed, 257 insertions(+), 106 deletions(-) rename zokrates_stdlib/tests/tests/gadgets/{verify.json => verify_1.json} (98%) rename zokrates_stdlib/tests/tests/gadgets/{verify.zok => verify_1.zok} (67%) create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify_2.json create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify_2.zok create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify_5.json create mode 100644 zokrates_stdlib/tests/tests/gadgets/verify_5.zok diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 24e45433..9da9eb38 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -82,9 +82,9 @@ fn cli_compute(ir_prog: ir::Prog, sub_matches: &ArgMatches) -> Resu let verbose = sub_matches.is_present("verbose"); // print deserialized flattened program if in verbose mode - // if verbose { - // println!("{}", ir_prog); - // } + if verbose { + println!("{}", ir_prog); + } let is_stdin = sub_matches.is_present("stdin"); let is_abi = sub_matches.is_present("abi"); diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 81dd9f48..8b72187f 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -46,15 +46,15 @@ pub type Fq = String; pub type Fq2 = (String, String); #[derive(Serialize, Deserialize)] -pub struct G1Affine(Fq, Fq); +pub struct G1Affine(pub Fq, pub Fq); // When G2 is defined on Fq2 field #[derive(Serialize, Deserialize)] -pub struct G2Affine(Fq2, Fq2); +pub struct G2Affine(pub Fq2, pub Fq2); // When G2 is defined on a Fq field (BW6_761 curve) #[derive(Serialize, Deserialize)] -pub struct G2AffineFq(Fq, Fq); +pub struct G2AffineFq(pub Fq, pub Fq); impl ToString for G1Affine { fn to_string(&self) -> String { diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs index a6622931..e2416529 100644 --- a/zokrates_core/src/solvers/mod.rs +++ b/zokrates_core/src/solvers/mod.rs @@ -1,4 +1,3 @@ -use num::Integer; use serde::{Deserialize, Serialize}; use std::fmt; @@ -38,10 +37,7 @@ impl Solver { #[cfg(feature = "bellman")] Solver::Sha256Round => (768, 26935), #[cfg(feature = "ark")] - Solver::Verify(n) => ( - 26 + 3 * n, - (41991 + (3570 * n)) + ((n.div_ceil(&2usize) - 1) * 2816), - ), + Solver::Verify(n) => (26 + 3 * n, 41991 + 4972 * n), } } } diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 99e59325..560df849 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -12,14 +12,23 @@ use ark_relations::{ }; use ark_crypto_primitives::snark::constraints::SNARKGadget; -use ark_crypto_primitives::snark::FromFieldElementsGadget; use ark_gm17::{constraints::GM17VerifierGadget, Proof, VerifyingKey, GM17}; use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; use crate::Constraint; +use ark_crypto_primitives::SNARK; use ark_r1cs_std::fields::fp::FpVar; +use ark_r1cs_std::ToBitsGadget; +use ark_relations::r1cs::{ConstraintSynthesizer, SynthesisError}; +use ark_std::test_rng; use std::str::FromStr; -use zokrates_field::{Field}; +use zokrates_field::Field; + +type GM17Snark = GM17; +type VerifierGadget = GM17VerifierGadget; + +type G1 = as PairingEngine>::G1Affine; +type G2 = as PairingEngine>::G2Affine; macro_rules! var { ($f:expr, $offset:expr) => { @@ -33,12 +42,6 @@ macro_rules! var { }; } -type GM17Snark = GM17; -type VerifierGadget = GM17VerifierGadget; - -type G1 = as PairingEngine>::G1Affine; -type G2 = as PairingEngine>::G2Affine; - macro_rules! g1 { ($e:expr, $i0:expr, $i1:expr) => { G1::new( @@ -65,6 +68,20 @@ macro_rules! g2 { }; } +#[derive(Copy, Clone)] +struct DefaultCircuit { + pub public_input_size: usize, +} + +impl ConstraintSynthesizer for DefaultCircuit { + fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { + for _ in 0..self.public_input_size { + let _ = FpVar::::new_input(ns!(cs, "alloc_input"), || Ok(F::one()))?; + } + Ok(()) + } +} + #[allow(clippy::type_complexity)] pub fn generate_verify_constraints( public_input_size: usize, @@ -79,53 +96,44 @@ pub fn generate_verify_constraints( let cs_sys = ConstraintSystem::::new(); let cs = ConstraintSystemRef::new(cs_sys); - let mut inputs = Vec::new(); + let mut rng = test_rng(); + let circuit = DefaultCircuit { public_input_size }; + + let (pk, vk) = GM17Snark::circuit_specific_setup(circuit, &mut rng).unwrap(); + let proof = GM17Snark::prove(&pk, circuit, &mut rng).unwrap(); + + let mut fp_vars = Vec::new(); for _ in 0..public_input_size { - inputs.push(FpVar::new_input(ns!(cs, "alloc_input"), || Ok(BLS12Fq::one())).unwrap()); + let fp = FpVar::new_input(ns!(cs, "alloc_input"), || Ok(BLS12Fq::one())).unwrap(); + fp_vars.push(fp); } - let dummy_inputs = >> = + fp_vars.iter().map(|i| i.to_bits_le().unwrap()).collect(); + + let inputs = ::Fr, ::Fq, GM17Snark, - >>::InputVar::from_field_elements(&inputs) - .unwrap(); + >>::InputVar::new(input_booleans); - let dummy_inputs_len = dummy_inputs.clone().into_iter().len(); - let dummy_proof = ::Fr, ::Fq, GM17Snark, >>::new_proof_unchecked( ns!(cs, "alloc_proof"), - || { - Ok(Proof { - a: G1::default(), - b: G2::default(), - c: G1::default(), - }) - }, + || Ok(proof), AllocationMode::Witness, ) .unwrap(); - let dummy_vk = ::Fr, ::Fq, GM17Snark, >>::new_verification_key_unchecked( - ns!(cs, "alloc_vk"), - || { - Ok(VerifyingKey { - h_g2: G2::default(), - g_alpha_g1: G1::default(), - h_beta_g2: G2::default(), - g_gamma_g1: G1::default(), - h_gamma_g2: G2::default(), - query: vec![G1::default(); dummy_inputs_len], - }) - }, - AllocationMode::Witness, + ns!(cs, "alloc_vk"), || Ok(vk), AllocationMode::Witness ) .unwrap(); @@ -133,47 +141,46 @@ pub fn generate_verify_constraints( ::Fr, ::Fq, GM17Snark, - >>::verify(&dummy_vk, &dummy_inputs, &dummy_proof) + >>::verify(&vk, &inputs, &proof) .unwrap(); cs.finalize(); let num_instance_variables = cs.num_instance_variables(); - let input_indices = inputs.iter().map(|f| var!(f, 0)).collect::>(); + let input_indices = fp_vars.iter().map(|f| var!(f, 0)).collect::>(); let proof_indices: Vec = vec![ - var!(dummy_proof.a.x, num_instance_variables), - var!(dummy_proof.a.y, num_instance_variables), - var!(dummy_proof.b.x.c0, num_instance_variables), - var!(dummy_proof.b.x.c1, num_instance_variables), - var!(dummy_proof.b.y.c0, num_instance_variables), - var!(dummy_proof.b.y.c1, num_instance_variables), - var!(dummy_proof.c.x, num_instance_variables), - var!(dummy_proof.c.y, num_instance_variables), + var!(proof.a.x, num_instance_variables), + var!(proof.a.y, num_instance_variables), + var!(proof.b.x.c0, num_instance_variables), + var!(proof.b.x.c1, num_instance_variables), + var!(proof.b.y.c0, num_instance_variables), + var!(proof.b.y.c1, num_instance_variables), + var!(proof.c.x, num_instance_variables), + var!(proof.c.y, num_instance_variables), ]; let mut vk_indices: Vec = vec![ - var!(dummy_vk.h_g2.x.c0, num_instance_variables), - var!(dummy_vk.h_g2.x.c1, num_instance_variables), - var!(dummy_vk.h_g2.y.c0, num_instance_variables), - var!(dummy_vk.h_g2.y.c1, num_instance_variables), - var!(dummy_vk.g_alpha_g1.x, num_instance_variables), - var!(dummy_vk.g_alpha_g1.y, num_instance_variables), - var!(dummy_vk.h_beta_g2.x.c0, num_instance_variables), - var!(dummy_vk.h_beta_g2.x.c1, num_instance_variables), - var!(dummy_vk.h_beta_g2.y.c0, num_instance_variables), - var!(dummy_vk.h_beta_g2.y.c1, num_instance_variables), - var!(dummy_vk.g_gamma_g1.x, num_instance_variables), - var!(dummy_vk.g_gamma_g1.y, num_instance_variables), - var!(dummy_vk.h_gamma_g2.x.c0, num_instance_variables), - var!(dummy_vk.h_gamma_g2.x.c1, num_instance_variables), - var!(dummy_vk.h_gamma_g2.y.c0, num_instance_variables), - var!(dummy_vk.h_gamma_g2.y.c1, num_instance_variables), + var!(vk.h_g2.x.c0, num_instance_variables), + var!(vk.h_g2.x.c1, num_instance_variables), + var!(vk.h_g2.y.c0, num_instance_variables), + var!(vk.h_g2.y.c1, num_instance_variables), + var!(vk.g_alpha_g1.x, num_instance_variables), + var!(vk.g_alpha_g1.y, num_instance_variables), + var!(vk.h_beta_g2.x.c0, num_instance_variables), + var!(vk.h_beta_g2.x.c1, num_instance_variables), + var!(vk.h_beta_g2.y.c0, num_instance_variables), + var!(vk.h_beta_g2.y.c1, num_instance_variables), + var!(vk.g_gamma_g1.x, num_instance_variables), + var!(vk.g_gamma_g1.y, num_instance_variables), + var!(vk.h_gamma_g2.x.c0, num_instance_variables), + var!(vk.h_gamma_g2.x.c1, num_instance_variables), + var!(vk.h_gamma_g2.y.c0, num_instance_variables), + var!(vk.h_gamma_g2.y.c1, num_instance_variables), ]; vk_indices.extend( - dummy_vk - .query + vk.query .iter() .map(|q| { vec![ @@ -209,19 +216,6 @@ pub fn generate_verify_constraints( }) .collect(); - /* - println!("num_instance_variables: {:?}", num_instance_variables); - println!("input_indices: {:?}", input_indices); - println!("proof_indices: {:?}", proof_indices); - println!("vk_indices: {:?}", vk_indices); - println!("out_index: {:?}", out_index); - println!("constraint_count: {:?}", cs.num_constraints()); - println!( - "variable_count: {:?}", - cs.num_witness_variables() + cs.num_instance_variables() - ); - */ - ( out_index, input_indices, @@ -239,22 +233,23 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> let cs_sys = ConstraintSystem::::new(); let cs = ConstraintSystemRef::new(cs_sys); - let mut input_vec = Vec::new(); + let mut fp_vars = Vec::new(); for input in inputs { - input_vec.push( - FpVar::new_input(ns!(cs, "alloc_input"), || { - Ok(BLS12Fq::from_str(&*input.to_dec_string()).unwrap()) - }) - .unwrap(), - ); + let input_field: BLS12Fq = BLS12Fq::from_str(input.to_dec_string().as_str()).unwrap(); + let fp = FpVar::new_input(ns!(cs, "alloc_input"), || Ok(input_field)).unwrap(); + fp_vars.push(fp); } + let input_booleans: Vec>> = fp_vars + .into_iter() + .map(|i| i.to_bits_le().unwrap()) + .collect(); + let inputs = ::Fr, ::Fq, GM17Snark, - >>::InputVar::from_field_elements(&input_vec) - .unwrap(); + >>::InputVar::new(input_booleans); let proof = ::Fr, @@ -316,13 +311,56 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> .map(|fq| T::from_byte_vector(fq.into_repr().to_bytes_le())) .collect() } - -/* -#[test] -fn generate_verify_constraints_test() { - let _ = generate_verify_constraints(1); -} -*/ +// +// #[test] +// fn generate_verify_constraints_test() { +// let _ = generate_verify_constraints(0); +// let _ = generate_verify_constraints(1); +// let _ = generate_verify_constraints(2); +// let _ = generate_verify_constraints(3); +// } +// +// #[test] +// fn generate_verify_witness_test() { +// let inputs = [Bw6_761Field::try_from_dec_str("1").unwrap()]; +// +// let proof = [ +// Bw6_761Field::try_from_dec_str("235782943111137747530705097136902819013408845361203175534778158383169533838434449255860464757085033350571842898348").unwrap(), +// Bw6_761Field::try_from_dec_str("165331200638255581426424843336405231597247782079004588915091938378328147868982661937191476394972887856514105171163").unwrap(), +// Bw6_761Field::try_from_dec_str("254232159831445544309193578749463370103753380550537149146142458926739764205591902671028001365299904981732549136683").unwrap(), +// Bw6_761Field::try_from_dec_str("110312323157092528819028093312347351137226193437841103950521979205975893813298913605994406937897967164905526329").unwrap(), +// Bw6_761Field::try_from_dec_str("92280397906394491698354903378414754820599196865399227396875767801540756083841866092570985429394716805577869077320").unwrap(), +// Bw6_761Field::try_from_dec_str("222376854776830339884944565405903085055220167393343147071200792467030923517478950522963886729324485932937864818308").unwrap(), +// Bw6_761Field::try_from_dec_str("166743706972793452960182372942649700997661741034432782404177255897479938072993375303879840122831003023380175217916").unwrap(), +// Bw6_761Field::try_from_dec_str("18241406009053346360181174307452353181071423946478108185071609940159980631851949302336828153867681522722723293022").unwrap() +// ]; +// +// let vk = [ +// Bw6_761Field::try_from_dec_str("195958723741148274853455159201485888818691815489993268749601350896046313859202060813450393651648043990458085546444").unwrap(), +// Bw6_761Field::try_from_dec_str("250586460666268137658218641890677997621978277070882765940531847948228319942427751723561925927172535045539183567512").unwrap(), +// Bw6_761Field::try_from_dec_str("57234023875145056535872139814081896160035766307948448121984762577416591136138301518701641437360482429441983035003").unwrap(), +// Bw6_761Field::try_from_dec_str("121354278543550641612200697783815693391285241292446633969973883979058168011709728550967337052029015353984616443838").unwrap(), +// Bw6_761Field::try_from_dec_str("135646801808269634260317971016961224255462547427375299328984758093466241297387693004994926726553046102004047340443").unwrap(), +// Bw6_761Field::try_from_dec_str("195568746810845500554149528092548239960661449012126888654840599195256227437456693344562709998175426801251472283163").unwrap(), +// Bw6_761Field::try_from_dec_str("76643185476572704963146246347086453256291196504794788777518008941873692890848784834169129586710009695562569789959").unwrap(), +// Bw6_761Field::try_from_dec_str("14407414746636140435653754439538456360783775597216728853315098252325800116296090722143648811029811922230403987642").unwrap(), +// Bw6_761Field::try_from_dec_str("241948018763885192315660730393291298686330622866040876232946054588870352441939487336082531324175120194138393276854").unwrap(), +// Bw6_761Field::try_from_dec_str("216905906087737597184922995184221169940829775146684973188909001659019536927834329277848699472206295867448317914180").unwrap(), +// Bw6_761Field::try_from_dec_str("127980131940757792489522902422610952616070039736870084796440882268680289963781343048894476650287858658933965223336").unwrap(), +// Bw6_761Field::try_from_dec_str("169029061244756455288512803317939880636727782082563463287674108474881061361652255168002034068840462861372798016506").unwrap(), +// Bw6_761Field::try_from_dec_str("195958723741148274853455159201485888818691815489993268749601350896046313859202060813450393651648043990458085546444").unwrap(), +// Bw6_761Field::try_from_dec_str("250586460666268137658218641890677997621978277070882765940531847948228319942427751723561925927172535045539183567512").unwrap(), +// Bw6_761Field::try_from_dec_str("57234023875145056535872139814081896160035766307948448121984762577416591136138301518701641437360482429441983035003").unwrap(), +// Bw6_761Field::try_from_dec_str("121354278543550641612200697783815693391285241292446633969973883979058168011709728550967337052029015353984616443838").unwrap(), +// Bw6_761Field::try_from_dec_str("32195860399927859397562455120174283256312634316227644355523312506401814372948826718688654459074592342744796675279").unwrap(), +// Bw6_761Field::try_from_dec_str("166911092056770617566930877485561483108518987792750382293738717177408821285936224491024516087699049333713921575672").unwrap(), +// Bw6_761Field::try_from_dec_str("196418598772862889574615860540297776905473069168713196436807788640920896318323041466544668158806161593231021557450").unwrap(), +// Bw6_761Field::try_from_dec_str("225560192455589244304893893333701602605197247902671499720170402331956986544121723047250430395938168862941096435629").unwrap() +// ]; +// +// let res = generate_verify_witness(&inputs, &proof, &vk); +// println!("{:?}", res.len()); +// } pub fn from_ark(c: Constraint) -> Constraint { Constraint { diff --git a/zokrates_stdlib/tests/tests/gadgets/verify.json b/zokrates_stdlib/tests/tests/gadgets/verify_1.json similarity index 98% rename from zokrates_stdlib/tests/tests/gadgets/verify.json rename to zokrates_stdlib/tests/tests/gadgets/verify_1.json index b5f95506..8cdc2ace 100644 --- a/zokrates_stdlib/tests/tests/gadgets/verify.json +++ b/zokrates_stdlib/tests/tests/gadgets/verify_1.json @@ -1,10 +1,11 @@ { - "entry_point": "./tests/tests/gadgets/verify.zok", + "entry_point": "./tests/tests/gadgets/verify_1.zok", "curves": ["Bw6_761"], "tests": [ { "input": { "values": [ + "1", "14854361253166356985827940126714566475275412573126716429346293669288261212877767002588736768495892518280555332082", "213732210873464696846782550184555137228225514409080200587629835423679101735680889388490505365220726936653232900722", "87538607630632344401950048588801759619324114043687193925268161368645768079512372989046887060116208844098222887523", @@ -13,7 +14,6 @@ "239017299818740889416561988179003000999440599788233589838386981563280711497257601212385904595560069610856834048609", "210817940648895568697680255986492415724502544301527123629003695092329489846191300997148203752109923795482648905049", "104796720182429147963427519368170838521257629224027565408974396362211239635140389257768036297199752289691646178885", - "1", "237849156256827398282019388933972533154056715710612980343582379691235964002811111531637163291964836316287473866944", "121324456153144638357885760921484124420296650752569739652599982435599667566663818850130137668154167962818124679946", "73600332144130508132510040050892177274732799381796146541825372722030832659283233558443467575385522990242420388929", diff --git a/zokrates_stdlib/tests/tests/gadgets/verify.zok b/zokrates_stdlib/tests/tests/gadgets/verify_1.zok similarity index 67% rename from zokrates_stdlib/tests/tests/gadgets/verify.zok rename to zokrates_stdlib/tests/tests/gadgets/verify_1.zok index 13f89bad..ff35f3d7 100644 --- a/zokrates_stdlib/tests/tests/gadgets/verify.zok +++ b/zokrates_stdlib/tests/tests/gadgets/verify_1.zok @@ -1,5 +1,5 @@ from "gadgets/verify" import main as verify -def main(private field[8] proof, private field[1] inputs, private field[20] vk) -> bool: +def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: bool result = verify(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_2.json b/zokrates_stdlib/tests/tests/gadgets/verify_2.json new file mode 100644 index 00000000..dcf741e1 --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify_2.json @@ -0,0 +1,49 @@ +{ + "entry_point": "./tests/tests/gadgets/verify_2.zok", + "curves": ["Bw6_761"], + "tests": [ + { + "input": { + "values": [ + "2", + "4", + "30886639936493049016175318852868223421962513695924799011862965798142544864756272917016480650319179059444391880142", + "210714472424410627451557273311118253425679108293022860127144278352441005505195339659420709617036779682326673533186", + "101969549978420613687361685686211943788361418391955806064423246725556175258043096446227634997412743489772585976407", + "225606981549539274850150853435430709464645103097569777238240148161962808333007149588258118157237589076622092111900", + "94477902787810056005140833707514971680416163466937669331638397632516292559333058429168736236263588445181668773613", + "156965166665593649649919836247487186182263277589020558979047044043456286367751723077006781061358137877318135673282", + "137741518433065408317198878994358008499493756319076293122811213051853618947340414216838530582726247267590705502194", + "126547036337175013106414910386451161000910611736141896590177615068467376299665795605927145787930213987505973766731", + "26150522755032959261786285436959898551137848025504557005325333189168466417284586793885098543725273736029879389211", + "169754513648720531797744265077389392707096818238531464510797707592538650668826008029773773893361012602508598834793", + "172926009578431040673671475398833553033375949638930965254433842547261096474109828672139964685904707258254717562981", + "190737508410333459842769941580905855813961948279753848892816073188168697419955701512184037596994386514528425558736", + "1619785665530270858283718034422422029553639813181597813279549759777153426792287594479505827096186872882300711765", + "63694115876363306907024906479487765094262979049817897093877772048737865300854356915611214233650510384715733840309", + "138256625715993632167333368395637908886726696039897946710436000177289042559378071109224721507617736881530800812544", + "107857276706363405428900669135705736327281608718185524590709570009027542794964888233568166787710632979062032163927", + "117681951719142414345371029336876269027160875021843115377112400246872843732924494507290756295050251515524804614493", + "16932482238351125436073535332269385696327441869886865463514408400096260901383164481505901002564992831623879258663", + "46308513493241827384377341904914105301671994851198058483103383539450400464257917932036866988024757095122827891763", + "12774065758179916688827174319525442607170697024774973507481660009802587305759263737719583503498828398179974682702", + "26150522755032959261786285436959898551137848025504557005325333189168466417284586793885098543725273736029879389211", + "169754513648720531797744265077389392707096818238531464510797707592538650668826008029773773893361012602508598834793", + "172926009578431040673671475398833553033375949638930965254433842547261096474109828672139964685904707258254717562981", + "190737508410333459842769941580905855813961948279753848892816073188168697419955701512184037596994386514528425558736", + "187872074241198211214687054253180244660204447307195753216396863454451962530721491538379804696965671145239859590846", + "172889367615248592096001816975404506869611319851954669628812891122278364377518978073247194031011246327549860771430", + "227539811502856876734690781228675876891342950061206768786526280217867721882979938383152839106086209430522325241347", + "33214331578997688306993838825659395665609935174693430136691944882187065031251282996759071511854109007793069549563", + "231745969633345194328768544928321593376710672347115907704852838281813505601170157293937606734791368236398411854640", + "47237328152391646101146711114931457284784793248831449686265996627039097119070481703804420386021717476164037563466" + ] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_2.zok b/zokrates_stdlib/tests/tests/gadgets/verify_2.zok new file mode 100644 index 00000000..8629b7a5 --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify_2.zok @@ -0,0 +1,5 @@ +from "gadgets/verify" import main as verify + +def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: + bool result = verify(inputs, proof, vk) + return result \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_5.json b/zokrates_stdlib/tests/tests/gadgets/verify_5.json new file mode 100644 index 00000000..5862f82b --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify_5.json @@ -0,0 +1,58 @@ +{ + "entry_point": "./tests/tests/gadgets/verify_5.zok", + "curves": ["Bw6_761"], + "tests": [ + { + "input": { + "values": [ + "2", + "2", + "2", + "2", + "8", + "60457684924193218954780799695448128402450659922819148866042534731462934804174889585425668379894806827192129355035", + "30692976080216123852486339295726836787768525847434467843252380267593056117653493955651719058012291818530914713503", + "125357500613234885873309304302314409734224357144836572740733227274842238671614205545693580811504410323545780196986", + "247651569074486453849718457544382537302063316144666696072138162914150063434773021124866593709430271032906775848230", + "205925817697152648573187530836257591106879527302418969217282393297385329815356611501846344314549412686571096624542", + "52408210490520029867007596145203947635265945726032430791270964404506413872638222587937059680769423104224418341783", + "245391920863498220927838330312555206148254951255756591670548373412908886220063896460749603543488483619267089689381", + "78589112605630898410537770266153128219408270888620016803188045523021815277982064356841045190284469829851165791293", + "177010185638377511324501604520563739739317808509681430951164029757345810095174696221494505373089763385490312116358", + "153053794329278051178743982884522858761476481700312111393093980133181276780354993379856934110282786295862092443919", + "119352601414532465114802089751399530705471140760948692288569726825270783170792459863146836606243083937386903791326", + "154395739702801688661668736325735092854144372763349598896957725187031688340840056329057020108410010039817499025290", + "219300867221825583189537695275783744511701200221265601874271468574900788700976161865886103325397401233680596662586", + "6184162650897786738969218350774078215930829358700672611442020481749290685465136203052430712512726892174302053960", + "223615432567648858214064557325028920329759681028000034077399269834838357009569712943919669143358231307616009815434", + "175981229674044997402551815995123920812483064905277870260193130162059294237262155034620065210131116619520563506519", + "149763821034046861511733819294494872607002147076380551480035933618221202037885306159876853613449195409389418630899", + "63613896436066139625271941484202721828670668029032907443649108037543119043920396499152980372905932782160074585332", + "83664647128245200609718804963435898883339854035469313658046832013326011731523365594256699720796643575140884572905", + "144568623182910160643612162930255558274463299944237682869943691750723939109705466332836308875557772911097578331002", + "177010185638377511324501604520563739739317808509681430951164029757345810095174696221494505373089763385490312116358", + "153053794329278051178743982884522858761476481700312111393093980133181276780354993379856934110282786295862092443919", + "119352601414532465114802089751399530705471140760948692288569726825270783170792459863146836606243083937386903791326", + "154395739702801688661668736325735092854144372763349598896957725187031688340840056329057020108410010039817499025290", + "149057616125424973478283591473814309565673764317022249169395023211664620308712452144732942791215282170059517214134", + "41780114592407788188439225711342125468082786659527520800331438243958377257657588645284569742745602805176661321513", + "221720891820590314635918157317325200201212159883016241641294528146177946855934688201173659819769674033460232363042", + "50797017918692117248188277962054664678983362179572320962314605303222488912037808946253081883636411158993624881368", + "45015881196637283857089803245084152220024891684216432418680197321055655838083895789012460620698622411348666936603", + "6614931577154387449192604140382084380965299734550787093003728565193454839715263838958636766466130999302518638149", + "245269024464910939632469903406535269950072210280644644046910525955649284275684019199442256400616717695144071175450", + "43420687027898212877864397162744483839228857355048382441491263977288496076621257227893835793326940537504242772685", + "83272518748948630820579332810320118472860479700707035306680609335770289292207880205558249065217561951629308682324", + "6938552589263177251253935997174459628120498877543020100980702178088439767196046212767463370826879237199769600513", + "170649759404749298159628447642105098367401676132263627894428382159110486377464596992614660456131317719055604455895", + "52917028619173381482821776446008133295138882162362339762583394451153359715914188291769779536313083815565710768404" + ] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_5.zok b/zokrates_stdlib/tests/tests/gadgets/verify_5.zok new file mode 100644 index 00000000..1907c7be --- /dev/null +++ b/zokrates_stdlib/tests/tests/gadgets/verify_5.zok @@ -0,0 +1,5 @@ +from "gadgets/verify" import main as verify + +def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: + bool result = verify(inputs, proof, vk) + return result \ No newline at end of file From d0983b62a7ed1ee8245924a13e5c741f2a6b2df1 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 28 Jun 2021 13:41:06 +0200 Subject: [PATCH 07/17] changelog --- changelogs/unreleased/918-dark64 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/918-dark64 diff --git a/changelogs/unreleased/918-dark64 b/changelogs/unreleased/918-dark64 new file mode 100644 index 00000000..512d4c1b --- /dev/null +++ b/changelogs/unreleased/918-dark64 @@ -0,0 +1 @@ +Add verifier gadget to stdlib for recursive proof verification \ No newline at end of file From e73f2448f8eeb07da6cf0379e7863e35655e728e Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 28 Jun 2021 14:25:12 +0200 Subject: [PATCH 08/17] remove comments, add assertions --- zokrates_core/src/embed.rs | 6 +++- zokrates_core/src/ir/interpreter.rs | 15 ++++++--- zokrates_embed/src/ark.rs | 50 ----------------------------- 3 files changed, 15 insertions(+), 56 deletions(-) diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 5785c62e..3a101f19 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -7,7 +7,7 @@ use crate::typed_absy::types::{ ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier, }; use std::collections::HashMap; -use zokrates_field::{Bn128Field, Field}; +use zokrates_field::Field; cfg_if::cfg_if! { if #[cfg(feature = "bellman")] { @@ -230,6 +230,7 @@ fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { /// - arguments #[cfg(feature = "bellman")] pub fn sha256_round() -> FlatFunction { + use zokrates_field::Bn128Field; assert_eq!(T::id(), Bn128Field::id()); // Define iterators for all indices at hand @@ -318,6 +319,9 @@ pub fn sha256_round() -> FlatFunction { #[cfg(feature = "ark")] pub fn verify(n: usize) -> FlatFunction { + use zokrates_field::Bw6_761Field; + assert_eq!(T::id(), Bw6_761Field::id()); + let (out_index, input_indices, proof_indices, vk_indices, constraints, variable_count) = generate_verify_constraints(n); diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 1dc71f8a..e3c4c145 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -235,11 +235,16 @@ impl Interpreter { .collect() } #[cfg(feature = "ark")] - Solver::Verify(n) => generate_verify_witness( - &inputs[..*n], - &inputs[*n..*n + 8usize], - &inputs[*n + 8usize..], - ), + Solver::Verify(n) => { + use zokrates_field::Bw6_761Field; + assert_eq!(T::id(), Bw6_761Field::id()); + + generate_verify_witness( + &inputs[..*n], + &inputs[*n..*n + 8usize], + &inputs[*n + 8usize..], + ) + } }; assert_eq!(res.len(), expected_output_count); diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 560df849..a89b34db 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -311,56 +311,6 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> .map(|fq| T::from_byte_vector(fq.into_repr().to_bytes_le())) .collect() } -// -// #[test] -// fn generate_verify_constraints_test() { -// let _ = generate_verify_constraints(0); -// let _ = generate_verify_constraints(1); -// let _ = generate_verify_constraints(2); -// let _ = generate_verify_constraints(3); -// } -// -// #[test] -// fn generate_verify_witness_test() { -// let inputs = [Bw6_761Field::try_from_dec_str("1").unwrap()]; -// -// let proof = [ -// Bw6_761Field::try_from_dec_str("235782943111137747530705097136902819013408845361203175534778158383169533838434449255860464757085033350571842898348").unwrap(), -// Bw6_761Field::try_from_dec_str("165331200638255581426424843336405231597247782079004588915091938378328147868982661937191476394972887856514105171163").unwrap(), -// Bw6_761Field::try_from_dec_str("254232159831445544309193578749463370103753380550537149146142458926739764205591902671028001365299904981732549136683").unwrap(), -// Bw6_761Field::try_from_dec_str("110312323157092528819028093312347351137226193437841103950521979205975893813298913605994406937897967164905526329").unwrap(), -// Bw6_761Field::try_from_dec_str("92280397906394491698354903378414754820599196865399227396875767801540756083841866092570985429394716805577869077320").unwrap(), -// Bw6_761Field::try_from_dec_str("222376854776830339884944565405903085055220167393343147071200792467030923517478950522963886729324485932937864818308").unwrap(), -// Bw6_761Field::try_from_dec_str("166743706972793452960182372942649700997661741034432782404177255897479938072993375303879840122831003023380175217916").unwrap(), -// Bw6_761Field::try_from_dec_str("18241406009053346360181174307452353181071423946478108185071609940159980631851949302336828153867681522722723293022").unwrap() -// ]; -// -// let vk = [ -// Bw6_761Field::try_from_dec_str("195958723741148274853455159201485888818691815489993268749601350896046313859202060813450393651648043990458085546444").unwrap(), -// Bw6_761Field::try_from_dec_str("250586460666268137658218641890677997621978277070882765940531847948228319942427751723561925927172535045539183567512").unwrap(), -// Bw6_761Field::try_from_dec_str("57234023875145056535872139814081896160035766307948448121984762577416591136138301518701641437360482429441983035003").unwrap(), -// Bw6_761Field::try_from_dec_str("121354278543550641612200697783815693391285241292446633969973883979058168011709728550967337052029015353984616443838").unwrap(), -// Bw6_761Field::try_from_dec_str("135646801808269634260317971016961224255462547427375299328984758093466241297387693004994926726553046102004047340443").unwrap(), -// Bw6_761Field::try_from_dec_str("195568746810845500554149528092548239960661449012126888654840599195256227437456693344562709998175426801251472283163").unwrap(), -// Bw6_761Field::try_from_dec_str("76643185476572704963146246347086453256291196504794788777518008941873692890848784834169129586710009695562569789959").unwrap(), -// Bw6_761Field::try_from_dec_str("14407414746636140435653754439538456360783775597216728853315098252325800116296090722143648811029811922230403987642").unwrap(), -// Bw6_761Field::try_from_dec_str("241948018763885192315660730393291298686330622866040876232946054588870352441939487336082531324175120194138393276854").unwrap(), -// Bw6_761Field::try_from_dec_str("216905906087737597184922995184221169940829775146684973188909001659019536927834329277848699472206295867448317914180").unwrap(), -// Bw6_761Field::try_from_dec_str("127980131940757792489522902422610952616070039736870084796440882268680289963781343048894476650287858658933965223336").unwrap(), -// Bw6_761Field::try_from_dec_str("169029061244756455288512803317939880636727782082563463287674108474881061361652255168002034068840462861372798016506").unwrap(), -// Bw6_761Field::try_from_dec_str("195958723741148274853455159201485888818691815489993268749601350896046313859202060813450393651648043990458085546444").unwrap(), -// Bw6_761Field::try_from_dec_str("250586460666268137658218641890677997621978277070882765940531847948228319942427751723561925927172535045539183567512").unwrap(), -// Bw6_761Field::try_from_dec_str("57234023875145056535872139814081896160035766307948448121984762577416591136138301518701641437360482429441983035003").unwrap(), -// Bw6_761Field::try_from_dec_str("121354278543550641612200697783815693391285241292446633969973883979058168011709728550967337052029015353984616443838").unwrap(), -// Bw6_761Field::try_from_dec_str("32195860399927859397562455120174283256312634316227644355523312506401814372948826718688654459074592342744796675279").unwrap(), -// Bw6_761Field::try_from_dec_str("166911092056770617566930877485561483108518987792750382293738717177408821285936224491024516087699049333713921575672").unwrap(), -// Bw6_761Field::try_from_dec_str("196418598772862889574615860540297776905473069168713196436807788640920896318323041466544668158806161593231021557450").unwrap(), -// Bw6_761Field::try_from_dec_str("225560192455589244304893893333701602605197247902671499720170402331956986544121723047250430395938168862941096435629").unwrap() -// ]; -// -// let res = generate_verify_witness(&inputs, &proof, &vk); -// println!("{:?}", res.len()); -// } pub fn from_ark(c: Constraint) -> Constraint { Constraint { From 82c98a45e0d3a5e2a96ffcc39dc44ae6aa4c43da Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 28 Jun 2021 20:13:26 +0200 Subject: [PATCH 09/17] remove gadget term --- changelogs/unreleased/918-dark64 | 2 +- zokrates_stdlib/stdlib/{gadgets => snark}/verify.zok | 0 zokrates_stdlib/tests/tests/{gadgets => snark}/verify_1.json | 2 +- zokrates_stdlib/tests/tests/{gadgets => snark}/verify_1.zok | 0 zokrates_stdlib/tests/tests/{gadgets => snark}/verify_2.json | 2 +- zokrates_stdlib/tests/tests/{gadgets => snark}/verify_2.zok | 0 zokrates_stdlib/tests/tests/{gadgets => snark}/verify_5.json | 2 +- zokrates_stdlib/tests/tests/{gadgets => snark}/verify_5.zok | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename zokrates_stdlib/stdlib/{gadgets => snark}/verify.zok (100%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_1.json (98%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_1.zok (100%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_2.json (98%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_2.zok (100%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_5.json (98%) rename zokrates_stdlib/tests/tests/{gadgets => snark}/verify_5.zok (100%) diff --git a/changelogs/unreleased/918-dark64 b/changelogs/unreleased/918-dark64 index 512d4c1b..4877a0bf 100644 --- a/changelogs/unreleased/918-dark64 +++ b/changelogs/unreleased/918-dark64 @@ -1 +1 @@ -Add verifier gadget to stdlib for recursive proof verification \ No newline at end of file +Add SNARK verification to stdlib \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/gadgets/verify.zok b/zokrates_stdlib/stdlib/snark/verify.zok similarity index 100% rename from zokrates_stdlib/stdlib/gadgets/verify.zok rename to zokrates_stdlib/stdlib/snark/verify.zok diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_1.json b/zokrates_stdlib/tests/tests/snark/verify_1.json similarity index 98% rename from zokrates_stdlib/tests/tests/gadgets/verify_1.json rename to zokrates_stdlib/tests/tests/snark/verify_1.json index 8cdc2ace..1c5a3492 100644 --- a/zokrates_stdlib/tests/tests/gadgets/verify_1.json +++ b/zokrates_stdlib/tests/tests/snark/verify_1.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/gadgets/verify_1.zok", + "entry_point": "./tests/tests/snark/verify_1.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_1.zok b/zokrates_stdlib/tests/tests/snark/verify_1.zok similarity index 100% rename from zokrates_stdlib/tests/tests/gadgets/verify_1.zok rename to zokrates_stdlib/tests/tests/snark/verify_1.zok diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_2.json b/zokrates_stdlib/tests/tests/snark/verify_2.json similarity index 98% rename from zokrates_stdlib/tests/tests/gadgets/verify_2.json rename to zokrates_stdlib/tests/tests/snark/verify_2.json index dcf741e1..67187729 100644 --- a/zokrates_stdlib/tests/tests/gadgets/verify_2.json +++ b/zokrates_stdlib/tests/tests/snark/verify_2.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/gadgets/verify_2.zok", + "entry_point": "./tests/tests/snark/verify_2.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_2.zok b/zokrates_stdlib/tests/tests/snark/verify_2.zok similarity index 100% rename from zokrates_stdlib/tests/tests/gadgets/verify_2.zok rename to zokrates_stdlib/tests/tests/snark/verify_2.zok diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_5.json b/zokrates_stdlib/tests/tests/snark/verify_5.json similarity index 98% rename from zokrates_stdlib/tests/tests/gadgets/verify_5.json rename to zokrates_stdlib/tests/tests/snark/verify_5.json index 5862f82b..9189e26d 100644 --- a/zokrates_stdlib/tests/tests/gadgets/verify_5.json +++ b/zokrates_stdlib/tests/tests/snark/verify_5.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/gadgets/verify_5.zok", + "entry_point": "./tests/tests/snark/verify_5.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/gadgets/verify_5.zok b/zokrates_stdlib/tests/tests/snark/verify_5.zok similarity index 100% rename from zokrates_stdlib/tests/tests/gadgets/verify_5.zok rename to zokrates_stdlib/tests/tests/snark/verify_5.zok From a3cbd70ae055a6aba2641348ffda16b9b0e70b2e Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 28 Jun 2021 20:17:54 +0200 Subject: [PATCH 10/17] fix tests --- zokrates_stdlib/tests/tests/snark/verify_1.zok | 2 +- zokrates_stdlib/tests/tests/snark/verify_2.zok | 2 +- zokrates_stdlib/tests/tests/snark/verify_5.zok | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zokrates_stdlib/tests/tests/snark/verify_1.zok b/zokrates_stdlib/tests/tests/snark/verify_1.zok index ff35f3d7..00dd284f 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_1.zok +++ b/zokrates_stdlib/tests/tests/snark/verify_1.zok @@ -1,4 +1,4 @@ -from "gadgets/verify" import main as verify +from "snark/verify" import main as verify def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: bool result = verify(inputs, proof, vk) diff --git a/zokrates_stdlib/tests/tests/snark/verify_2.zok b/zokrates_stdlib/tests/tests/snark/verify_2.zok index 8629b7a5..fdba99f6 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_2.zok +++ b/zokrates_stdlib/tests/tests/snark/verify_2.zok @@ -1,4 +1,4 @@ -from "gadgets/verify" import main as verify +from "snark/verify" import main as verify def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: bool result = verify(inputs, proof, vk) diff --git a/zokrates_stdlib/tests/tests/snark/verify_5.zok b/zokrates_stdlib/tests/tests/snark/verify_5.zok index 1907c7be..842cdeb1 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_5.zok +++ b/zokrates_stdlib/tests/tests/snark/verify_5.zok @@ -1,4 +1,4 @@ -from "gadgets/verify" import main as verify +from "snark/verify" import main as verify def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: bool result = verify(inputs, proof, vk) From b4ebb1f7c181e78fcca89962c851e50cc92b2249 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 5 Jul 2021 12:18:44 +0200 Subject: [PATCH 11/17] cleanup --- .../tests/tests/verify}/verify_1.json | 2 +- .../tests/tests/verify}/verify_1.zok | 2 +- .../tests/tests/verify}/verify_2.json | 2 +- .../tests/tests/verify}/verify_2.zok | 2 +- .../tests/tests/verify}/verify_5.json | 2 +- .../tests/tests/verify}/verify_5.zok | 2 +- zokrates_embed/src/ark.rs | 150 +++++++++--------- zokrates_stdlib/stdlib/snark/verify.zok | 7 - 8 files changed, 82 insertions(+), 87 deletions(-) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_1.json (98%) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_1.zok (78%) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_2.json (98%) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_2.zok (78%) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_5.json (98%) rename {zokrates_stdlib/tests/tests/snark => zokrates_core_test/tests/tests/verify}/verify_5.zok (78%) delete mode 100644 zokrates_stdlib/stdlib/snark/verify.zok diff --git a/zokrates_stdlib/tests/tests/snark/verify_1.json b/zokrates_core_test/tests/tests/verify/verify_1.json similarity index 98% rename from zokrates_stdlib/tests/tests/snark/verify_1.json rename to zokrates_core_test/tests/tests/verify/verify_1.json index 1c5a3492..d718549d 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_1.json +++ b/zokrates_core_test/tests/tests/verify/verify_1.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/snark/verify_1.zok", + "entry_point": "./tests/tests/verify/verify_1.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/snark/verify_1.zok b/zokrates_core_test/tests/tests/verify/verify_1.zok similarity index 78% rename from zokrates_stdlib/tests/tests/snark/verify_1.zok rename to zokrates_core_test/tests/tests/verify/verify_1.zok index 00dd284f..4c73ebee 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_1.zok +++ b/zokrates_core_test/tests/tests/verify/verify_1.zok @@ -1,4 +1,4 @@ -from "snark/verify" import main as verify +from "EMBED" import verify def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: bool result = verify(inputs, proof, vk) diff --git a/zokrates_stdlib/tests/tests/snark/verify_2.json b/zokrates_core_test/tests/tests/verify/verify_2.json similarity index 98% rename from zokrates_stdlib/tests/tests/snark/verify_2.json rename to zokrates_core_test/tests/tests/verify/verify_2.json index 67187729..6e364e85 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_2.json +++ b/zokrates_core_test/tests/tests/verify/verify_2.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/snark/verify_2.zok", + "entry_point": "./tests/tests/verify/verify_2.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/snark/verify_2.zok b/zokrates_core_test/tests/tests/verify/verify_2.zok similarity index 78% rename from zokrates_stdlib/tests/tests/snark/verify_2.zok rename to zokrates_core_test/tests/tests/verify/verify_2.zok index fdba99f6..cebea31b 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_2.zok +++ b/zokrates_core_test/tests/tests/verify/verify_2.zok @@ -1,4 +1,4 @@ -from "snark/verify" import main as verify +from "EMBED" import verify def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: bool result = verify(inputs, proof, vk) diff --git a/zokrates_stdlib/tests/tests/snark/verify_5.json b/zokrates_core_test/tests/tests/verify/verify_5.json similarity index 98% rename from zokrates_stdlib/tests/tests/snark/verify_5.json rename to zokrates_core_test/tests/tests/verify/verify_5.json index 9189e26d..22b770e3 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_5.json +++ b/zokrates_core_test/tests/tests/verify/verify_5.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/snark/verify_5.zok", + "entry_point": "./tests/tests/verify/verify_5.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_stdlib/tests/tests/snark/verify_5.zok b/zokrates_core_test/tests/tests/verify/verify_5.zok similarity index 78% rename from zokrates_stdlib/tests/tests/snark/verify_5.zok rename to zokrates_core_test/tests/tests/verify/verify_5.zok index 842cdeb1..da998b15 100644 --- a/zokrates_stdlib/tests/tests/snark/verify_5.zok +++ b/zokrates_core_test/tests/tests/verify/verify_5.zok @@ -1,4 +1,4 @@ -from "snark/verify" import main as verify +from "EMBED" import verify def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: bool result = verify(inputs, proof, vk) diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index a89b34db..63326373 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -30,44 +30,6 @@ type VerifierGadget = GM17VerifierGadget; type G1 = as PairingEngine>::G1Affine; type G2 = as PairingEngine>::G2Affine; -macro_rules! var { - ($f:expr, $offset:expr) => { - match $f { - FpVar::Var(ref fp) => { - let var = &fp.variable; - var.get_index_unchecked($offset).unwrap() - } - _ => unreachable!("expected variable, found constant"), - } - }; -} - -macro_rules! g1 { - ($e:expr, $i0:expr, $i1:expr) => { - G1::new( - BLS12Fq::from_str(&*$e[$i0].to_dec_string()).unwrap(), - BLS12Fq::from_str(&*$e[$i1].to_dec_string()).unwrap(), - false, - ) - }; -} - -macro_rules! g2 { - ($e:expr, $i0:expr, $i1:expr, $i2:expr, $i3:expr) => { - G2::new( - BLS12Fq2::new( - BLS12Fq::from_str(&*$e[$i0].to_dec_string()).unwrap(), - BLS12Fq::from_str(&*$e[$i1].to_dec_string()).unwrap(), - ), - BLS12Fq2::new( - BLS12Fq::from_str(&*$e[$i2].to_dec_string()).unwrap(), - BLS12Fq::from_str(&*$e[$i3].to_dec_string()).unwrap(), - ), - false, - ) - }; -} - #[derive(Copy, Clone)] struct DefaultCircuit { pub public_input_size: usize, @@ -147,36 +109,39 @@ pub fn generate_verify_constraints( cs.finalize(); let num_instance_variables = cs.num_instance_variables(); - let input_indices = fp_vars.iter().map(|f| var!(f, 0)).collect::>(); + let input_indices = fp_vars + .iter() + .map(|f| var_to_index(&f, 0)) + .collect::>(); let proof_indices: Vec = vec![ - var!(proof.a.x, num_instance_variables), - var!(proof.a.y, num_instance_variables), - var!(proof.b.x.c0, num_instance_variables), - var!(proof.b.x.c1, num_instance_variables), - var!(proof.b.y.c0, num_instance_variables), - var!(proof.b.y.c1, num_instance_variables), - var!(proof.c.x, num_instance_variables), - var!(proof.c.y, num_instance_variables), + var_to_index(&proof.a.x, num_instance_variables), + var_to_index(&proof.a.y, num_instance_variables), + var_to_index(&proof.b.x.c0, num_instance_variables), + var_to_index(&proof.b.x.c1, num_instance_variables), + var_to_index(&proof.b.y.c0, num_instance_variables), + var_to_index(&proof.b.y.c1, num_instance_variables), + var_to_index(&proof.c.x, num_instance_variables), + var_to_index(&proof.c.y, num_instance_variables), ]; let mut vk_indices: Vec = vec![ - var!(vk.h_g2.x.c0, num_instance_variables), - var!(vk.h_g2.x.c1, num_instance_variables), - var!(vk.h_g2.y.c0, num_instance_variables), - var!(vk.h_g2.y.c1, num_instance_variables), - var!(vk.g_alpha_g1.x, num_instance_variables), - var!(vk.g_alpha_g1.y, num_instance_variables), - var!(vk.h_beta_g2.x.c0, num_instance_variables), - var!(vk.h_beta_g2.x.c1, num_instance_variables), - var!(vk.h_beta_g2.y.c0, num_instance_variables), - var!(vk.h_beta_g2.y.c1, num_instance_variables), - var!(vk.g_gamma_g1.x, num_instance_variables), - var!(vk.g_gamma_g1.y, num_instance_variables), - var!(vk.h_gamma_g2.x.c0, num_instance_variables), - var!(vk.h_gamma_g2.x.c1, num_instance_variables), - var!(vk.h_gamma_g2.y.c0, num_instance_variables), - var!(vk.h_gamma_g2.y.c1, num_instance_variables), + var_to_index(&vk.h_g2.x.c0, num_instance_variables), + var_to_index(&vk.h_g2.x.c1, num_instance_variables), + var_to_index(&vk.h_g2.y.c0, num_instance_variables), + var_to_index(&vk.h_g2.y.c1, num_instance_variables), + var_to_index(&vk.g_alpha_g1.x, num_instance_variables), + var_to_index(&vk.g_alpha_g1.y, num_instance_variables), + var_to_index(&vk.h_beta_g2.x.c0, num_instance_variables), + var_to_index(&vk.h_beta_g2.x.c1, num_instance_variables), + var_to_index(&vk.h_beta_g2.y.c0, num_instance_variables), + var_to_index(&vk.h_beta_g2.y.c1, num_instance_variables), + var_to_index(&vk.g_gamma_g1.x, num_instance_variables), + var_to_index(&vk.g_gamma_g1.y, num_instance_variables), + var_to_index(&vk.h_gamma_g2.x.c0, num_instance_variables), + var_to_index(&vk.h_gamma_g2.x.c1, num_instance_variables), + var_to_index(&vk.h_gamma_g2.y.c0, num_instance_variables), + var_to_index(&vk.h_gamma_g2.y.c1, num_instance_variables), ]; vk_indices.extend( @@ -184,8 +149,8 @@ pub fn generate_verify_constraints( .iter() .map(|q| { vec![ - var!(q.x, num_instance_variables), - var!(q.y, num_instance_variables), + var_to_index(&q.x, num_instance_variables), + var_to_index(&q.y, num_instance_variables), ] }) .flatten(), @@ -259,9 +224,9 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> ns!(cs, "alloc_proof"), || { Ok(Proof { - a: g1!(proof, 0, 1), - b: g2!(proof, 2, 3, 4, 5), - c: g1!(proof, 6, 7), + a: new_g1(&proof[0..2]), + b: new_g2(&proof[2..6]), + c: new_g1(&proof[6..8]), }) }, AllocationMode::Witness, @@ -276,15 +241,15 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> ns!(cs, "alloc_vk"), || { Ok(VerifyingKey { - h_g2: g2!(vk, 0, 1, 2, 3), - g_alpha_g1: g1!(vk, 4, 5), - h_beta_g2: g2!(vk, 6, 7, 8, 9), - g_gamma_g1: g1!(vk, 10, 11), - h_gamma_g2: g2!(vk, 12, 13, 14, 15), + h_g2: new_g2(&vk[0..4]), + g_alpha_g1: new_g1(&vk[4..6]), + h_beta_g2: new_g2(&vk[6..10]), + g_gamma_g1: new_g1(&vk[10..12]), + h_gamma_g2: new_g2(&vk[12..16]), query: (16..vk.len()) .collect::>() .chunks(2) - .map(|c| g1!(vk, c[0], c[1])) + .map(|c| new_g1(&vk[c[0]..c[1] + 1])) .collect(), }) }, @@ -312,6 +277,43 @@ pub fn generate_verify_witness(inputs: &[T], proof: &[T], vk: &[T]) -> .collect() } +#[inline] +fn var_to_index(var: &FpVar, offset: usize) -> usize { + match var { + FpVar::Var(ref fp) => { + let var = &fp.variable; + var.get_index_unchecked(offset).unwrap() + } + _ => unreachable!("expected variable, but found a constant"), + } +} + +#[inline] +fn new_g1(flat: &[T]) -> G1 { + assert_eq!(flat.len(), 2); + G1::new( + BLS12Fq::from_str(&*flat[0].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*flat[1].to_dec_string()).unwrap(), + false, + ) +} + +#[inline] +fn new_g2(flat: &[T]) -> G2 { + assert_eq!(flat.len(), 4); + G2::new( + BLS12Fq2::new( + BLS12Fq::from_str(&*flat[0].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*flat[1].to_dec_string()).unwrap(), + ), + BLS12Fq2::new( + BLS12Fq::from_str(&*flat[2].to_dec_string()).unwrap(), + BLS12Fq::from_str(&*flat[3].to_dec_string()).unwrap(), + ), + false, + ) +} + pub fn from_ark(c: Constraint) -> Constraint { Constraint { a: c.a diff --git a/zokrates_stdlib/stdlib/snark/verify.zok b/zokrates_stdlib/stdlib/snark/verify.zok deleted file mode 100644 index 731161f9..00000000 --- a/zokrates_stdlib/stdlib/snark/verify.zok +++ /dev/null @@ -1,7 +0,0 @@ -#pragma curve bw6_761 - -from "EMBED" import verify - -def main(field[N] inputs, field[8] proof, field[V] vk) -> bool: - assert(18 + (2 * N) == V) - return verify(inputs, proof, vk) \ No newline at end of file From ce3a137432b2ff332f5505ac837d1f1d02ef462c Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 5 Jul 2021 15:58:53 +0200 Subject: [PATCH 12/17] rename verify embed, update changelog --- changelogs/unreleased/918-dark64 | 2 +- zokrates_core/src/imports.rs | 28 ++++++++++++++----- .../snark_verify_bls12_377_1.json} | 2 +- .../snark_verify_bls12_377_1.zok} | 4 +-- .../snark_verify_bls12_377_2.json} | 2 +- .../snark_verify_bls12_377_2.zok} | 4 +-- .../snark_verify_bls12_377_5.json} | 2 +- .../snark_verify_bls12_377_5.zok} | 4 +-- 8 files changed, 31 insertions(+), 17 deletions(-) rename zokrates_core_test/tests/tests/{verify/verify_1.json => snark/snark_verify_bls12_377_1.json} (98%) rename zokrates_core_test/tests/tests/{verify/verify_1.zok => snark/snark_verify_bls12_377_1.zok} (50%) rename zokrates_core_test/tests/tests/{verify/verify_2.json => snark/snark_verify_bls12_377_2.json} (98%) rename zokrates_core_test/tests/tests/{verify/verify_2.zok => snark/snark_verify_bls12_377_2.zok} (50%) rename zokrates_core_test/tests/tests/{verify/verify_5.json => snark/snark_verify_bls12_377_5.json} (98%) rename zokrates_core_test/tests/tests/{verify/verify_5.zok => snark/snark_verify_bls12_377_5.zok} (50%) diff --git a/changelogs/unreleased/918-dark64 b/changelogs/unreleased/918-dark64 index 4877a0bf..5c8b59e9 100644 --- a/changelogs/unreleased/918-dark64 +++ b/changelogs/unreleased/918-dark64 @@ -1 +1 @@ -Add SNARK verification to stdlib \ No newline at end of file +Introduce the `snark_verify_bls12_377` embed for one-layer composition of SNARK proofs (over `BLS12-377`/`BW6-761` pair of curves where `BW6-761` is used as an outer curve to `BLS12-377`) \ No newline at end of file diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index b94d5f87..7da5a59d 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -16,7 +16,7 @@ use std::path::{Path, PathBuf}; use typed_arena::Arena; use zokrates_common::Resolver; -use zokrates_field::{Bn128Field, Field}; +use zokrates_field::{Bn128Field, Bw6_761Field, Field}; #[derive(PartialEq, Debug)] pub struct Error { @@ -106,8 +106,8 @@ impl Importer { if T::id() != Bn128Field::id() { return Err(CompileErrorInner::ImportError( Error::new(format!( - "Embed sha256round cannot be used with curve {}", - T::name() + "Embed `sha256round` must be used with curve `{}`", + Bn128Field::name() )) .with_pos(Some(pos)), ) @@ -121,10 +121,24 @@ impl Importer { } } #[cfg(feature = "ark")] - "verify" => SymbolDeclaration { - id: symbol.get_alias(), - symbol: Symbol::Flat(FlatEmbed::Verify), - }, + "snark_verify_bls12_377" => { + if T::id() != Bw6_761Field::id() { + return Err(CompileErrorInner::ImportError( + Error::new(format!( + "Embed `snark_verify_bls12_377` must be used with curve `{}`", + Bw6_761Field::name() + )) + .with_pos(Some(pos)), + ) + .in_file(location) + .into()); + } else { + SymbolDeclaration { + id: symbol.get_alias(), + symbol: Symbol::Flat(FlatEmbed::Verify), + } + } + } "unpack" => SymbolDeclaration { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::Unpack), diff --git a/zokrates_core_test/tests/tests/verify/verify_1.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json similarity index 98% rename from zokrates_core_test/tests/tests/verify/verify_1.json rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json index d718549d..c844890a 100644 --- a/zokrates_core_test/tests/tests/verify/verify_1.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/verify/verify_1.zok", + "entry_point": "./tests/tests/snark/snark_verify_bls12_377_1.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_core_test/tests/tests/verify/verify_1.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok similarity index 50% rename from zokrates_core_test/tests/tests/verify/verify_1.zok rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok index 4c73ebee..d0dcb74c 100644 --- a/zokrates_core_test/tests/tests/verify/verify_1.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok @@ -1,5 +1,5 @@ -from "EMBED" import verify +from "EMBED" import snark_verify_bls12_377 def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: - bool result = verify(inputs, proof, vk) + bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/verify/verify_2.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json similarity index 98% rename from zokrates_core_test/tests/tests/verify/verify_2.json rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json index 6e364e85..00a7b238 100644 --- a/zokrates_core_test/tests/tests/verify/verify_2.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/verify/verify_2.zok", + "entry_point": "./tests/tests/snark/snark_verify_bls12_377_2.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_core_test/tests/tests/verify/verify_2.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok similarity index 50% rename from zokrates_core_test/tests/tests/verify/verify_2.zok rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok index cebea31b..b9de1f7a 100644 --- a/zokrates_core_test/tests/tests/verify/verify_2.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok @@ -1,5 +1,5 @@ -from "EMBED" import verify +from "EMBED" import snark_verify_bls12_377 def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: - bool result = verify(inputs, proof, vk) + bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/verify/verify_5.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json similarity index 98% rename from zokrates_core_test/tests/tests/verify/verify_5.json rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json index 22b770e3..8c05a0ba 100644 --- a/zokrates_core_test/tests/tests/verify/verify_5.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/verify/verify_5.zok", + "entry_point": "./tests/tests/snark/snark_verify_bls12_377_5.zok", "curves": ["Bw6_761"], "tests": [ { diff --git a/zokrates_core_test/tests/tests/verify/verify_5.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok similarity index 50% rename from zokrates_core_test/tests/tests/verify/verify_5.zok rename to zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok index da998b15..6ec49a40 100644 --- a/zokrates_core_test/tests/tests/verify/verify_5.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok @@ -1,5 +1,5 @@ -from "EMBED" import verify +from "EMBED" import snark_verify_bls12_377 def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: - bool result = verify(inputs, proof, vk) + bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file From 878faf2ba3359d61635bc5a1dd6e401c80eaa1e5 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 14:04:16 +0200 Subject: [PATCH 13/17] renaming, improve error message on curve-specific embed import --- zokrates_core/src/embed.rs | 10 +++++----- zokrates_core/src/imports.rs | 12 +++++++----- zokrates_core/src/proof_system/mod.rs | 6 +++--- zokrates_core/src/static_analysis/propagation.rs | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 3a101f19..d7100c5a 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -40,7 +40,7 @@ pub enum FlatEmbed { #[cfg(feature = "bellman")] Sha256Round, #[cfg(feature = "ark")] - Verify, + SnarkVerifyBls12377, } impl FlatEmbed { @@ -121,7 +121,7 @@ impl FlatEmbed { 256usize, ))]), #[cfg(feature = "ark")] - FlatEmbed::Verify => DeclarationSignature::new() + FlatEmbed::SnarkVerifyBls12377 => DeclarationSignature::new() .generics(vec![ Some(Constant::Generic(GenericIdentifier { name: "N", @@ -182,7 +182,7 @@ impl FlatEmbed { #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => "_SHA256_ROUND", #[cfg(feature = "ark")] - FlatEmbed::Verify => "_VERIFY", + FlatEmbed::SnarkVerifyBls12377 => "_SNARK_VERIFY_BLS12_377", } } @@ -193,7 +193,7 @@ impl FlatEmbed { #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => sha256_round(), #[cfg(feature = "ark")] - FlatEmbed::Verify => verify(generics[0] as usize), + FlatEmbed::SnarkVerifyBls12377 => snark_verify_bls12_377(generics[0] as usize), _ => unreachable!(), } } @@ -318,7 +318,7 @@ pub fn sha256_round() -> FlatFunction { } #[cfg(feature = "ark")] -pub fn verify(n: usize) -> FlatFunction { +pub fn snark_verify_bls12_377(n: usize) -> FlatFunction { use zokrates_field::Bw6_761Field; assert_eq!(T::id(), Bw6_761Field::id()); diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 7da5a59d..ec12e7bf 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -106,8 +106,9 @@ impl Importer { if T::id() != Bn128Field::id() { return Err(CompileErrorInner::ImportError( Error::new(format!( - "Embed `sha256round` must be used with curve `{}`", - Bn128Field::name() + "`sha256round` is expected to be compiled over `{}` curve, but found `{}`", + Bn128Field::name(), + T::name() )) .with_pos(Some(pos)), ) @@ -125,8 +126,9 @@ impl Importer { if T::id() != Bw6_761Field::id() { return Err(CompileErrorInner::ImportError( Error::new(format!( - "Embed `snark_verify_bls12_377` must be used with curve `{}`", - Bw6_761Field::name() + "`snark_verify_bls12_377` is expected to be compiled over `{}` curve, but found `{}`", + Bw6_761Field::name(), + T::name() )) .with_pos(Some(pos)), ) @@ -135,7 +137,7 @@ impl Importer { } else { SymbolDeclaration { id: symbol.get_alias(), - symbol: Symbol::Flat(FlatEmbed::Verify), + symbol: Symbol::Flat(FlatEmbed::SnarkVerifyBls12377), } } } diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index 8b72187f..81dd9f48 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -46,15 +46,15 @@ pub type Fq = String; pub type Fq2 = (String, String); #[derive(Serialize, Deserialize)] -pub struct G1Affine(pub Fq, pub Fq); +pub struct G1Affine(Fq, Fq); // When G2 is defined on Fq2 field #[derive(Serialize, Deserialize)] -pub struct G2Affine(pub Fq2, pub Fq2); +pub struct G2Affine(Fq2, Fq2); // When G2 is defined on a Fq field (BW6_761 curve) #[derive(Serialize, Deserialize)] -pub struct G2AffineFq(pub Fq, pub Fq); +pub struct G2AffineFq(Fq, Fq); impl ToString for G1Affine { fn to_string(&self) -> String { diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 3a08ef74..bbc470ec 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -551,7 +551,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => None, #[cfg(feature = "ark")] - FlatEmbed::Verify => None, + FlatEmbed::SnarkVerifyBls12377 => None, }; match r { From 6f0821f1299b68542dc9826c35a709195191e8b7 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 15:46:56 +0200 Subject: [PATCH 14/17] remove unreachable variant, add comments to snark verification tests --- .../tests/tests/snark/snark_verify_bls12_377_1.zok | 6 ++++++ .../tests/tests/snark/snark_verify_bls12_377_2.zok | 6 ++++++ .../tests/tests/snark/snark_verify_bls12_377_5.zok | 10 ++++++++++ zokrates_embed/src/ark.rs | 6 +----- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok index d0dcb74c..9e4e45a8 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok @@ -1,5 +1,11 @@ from "EMBED" import snark_verify_bls12_377 +// Verifies a proof with 1 public input (0 inputs + 1 output) +// Circuit used in this test: +// +// def main() -> field: +// return 1 + def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok index b9de1f7a..d8bd4919 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok @@ -1,5 +1,11 @@ from "EMBED" import snark_verify_bls12_377 +// Verifies a proof with 2 public inputs (1 input + 1 output) +// Circuit used in this test: +// +// def main(field a) -> field: +// return a * a + def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok index 6ec49a40..365105be 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok @@ -1,5 +1,15 @@ from "EMBED" import snark_verify_bls12_377 +// Verifies a proof with 5 public inputs (4 inputs + 1 output) +// Circuit used in this test: +// +// def main(field[4] a) -> field: +// field out = 0 +// for u32 i in 0..4 do +// out = out + a[i] +// endfor +// return out + def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_embed/src/ark.rs b/zokrates_embed/src/ark.rs index 63326373..47e14529 100644 --- a/zokrates_embed/src/ark.rs +++ b/zokrates_embed/src/ark.rs @@ -58,7 +58,7 @@ pub fn generate_verify_constraints( let cs_sys = ConstraintSystem::::new(); let cs = ConstraintSystemRef::new(cs_sys); - let mut rng = test_rng(); + let mut rng = test_rng(); // has a fixed seed let circuit = DefaultCircuit { public_input_size }; let (pk, vk) = GM17Snark::circuit_specific_setup(circuit, &mut rng).unwrap(); @@ -161,10 +161,6 @@ pub fn generate_verify_constraints( .variable() .get_index_unchecked(num_instance_variables) .unwrap(), - Boolean::Not(x) => x - .variable() - .get_index_unchecked(num_instance_variables) - .unwrap(), _ => unreachable!(), }; From 41d30c5d7dbec011b16d9e67f59bcc6cd8ee2849 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 15:58:59 +0200 Subject: [PATCH 15/17] update test description --- .../tests/tests/snark/snark_verify_bls12_377_1.zok | 7 ++++++- .../tests/tests/snark/snark_verify_bls12_377_2.zok | 7 ++++++- .../tests/tests/snark/snark_verify_bls12_377_5.zok | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok index 9e4e45a8..b4df2dca 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok @@ -1,10 +1,15 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 1 public input (0 inputs + 1 output) -// Circuit used in this test: +// Circuit used in this test (compiled using `bls12_377` curve): // // def main() -> field: // return 1 +// +// Arguments: +// inputs - public inputs of the circuit +// proof - flattened proof to an array of field elements +// vk - flattened verification key to an array of field elements def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok index d8bd4919..1bdb7bdd 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok @@ -1,10 +1,15 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 2 public inputs (1 input + 1 output) -// Circuit used in this test: +// Circuit used in this test (compiled using `bls12_377` curve): // // def main(field a) -> field: // return a * a +// +// Arguments: +// inputs - public inputs of the circuit +// proof - flattened proof to an array of field elements +// vk - flattened verification key to an array of field elements def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok index 365105be..48514273 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok @@ -1,7 +1,7 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 5 public inputs (4 inputs + 1 output) -// Circuit used in this test: +// Circuit used in this test (compiled using `bls12_377` curve): // // def main(field[4] a) -> field: // field out = 0 @@ -9,6 +9,11 @@ from "EMBED" import snark_verify_bls12_377 // out = out + a[i] // endfor // return out +// +// Arguments: +// inputs - public inputs of the circuit +// proof - flattened proof to an array of field elements +// vk - flattened verification key to an array of field elements def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) From acd0af6473c74108be72425313e79f43b985b300 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 16:15:20 +0200 Subject: [PATCH 16/17] rename solver --- zokrates_core/src/embed.rs | 2 +- zokrates_core/src/ir/interpreter.rs | 2 +- zokrates_core/src/solvers/mod.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index d7100c5a..d5a6344b 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -400,7 +400,7 @@ pub fn snark_verify_bls12_377(n: usize) -> FlatFunction { .chain(vk_argument_indices) .map(|i| FlatVariable::new(i).into()) .collect(), - solver: Solver::Verify(n), + solver: Solver::SnarkVerifyBls12377(n), }); let statements: Vec<_> = std::iter::once(directive_statement) diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index e3c4c145..54b7dc43 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -235,7 +235,7 @@ impl Interpreter { .collect() } #[cfg(feature = "ark")] - Solver::Verify(n) => { + Solver::SnarkVerifyBls12377(n) => { use zokrates_field::Bw6_761Field; assert_eq!(T::id(), Bw6_761Field::id()); diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs index e2416529..d8387f26 100644 --- a/zokrates_core/src/solvers/mod.rs +++ b/zokrates_core/src/solvers/mod.rs @@ -14,7 +14,7 @@ pub enum Solver { #[cfg(feature = "bellman")] Sha256Round, #[cfg(feature = "ark")] - Verify(usize), + SnarkVerifyBls12377(usize), } impl fmt::Display for Solver { @@ -37,7 +37,7 @@ impl Solver { #[cfg(feature = "bellman")] Solver::Sha256Round => (768, 26935), #[cfg(feature = "ark")] - Solver::Verify(n) => (26 + 3 * n, 41991 + 4972 * n), + Solver::SnarkVerifyBls12377(n) => (26 + 3 * n, 41991 + 4972 * n), } } } From bda8c0b0b6175bd225cab7adb82a90951712a536 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 17:52:37 +0200 Subject: [PATCH 17/17] add instructions to snark verification tests --- .../tests/snark/snark_verify_bls12_377_1.json | 2 +- .../tests/snark/snark_verify_bls12_377_1.zok | 31 +++++++++++++++---- .../tests/snark/snark_verify_bls12_377_2.json | 4 +-- .../tests/snark/snark_verify_bls12_377_2.zok | 31 +++++++++++++++---- .../tests/snark/snark_verify_bls12_377_5.json | 10 +++--- .../tests/snark/snark_verify_bls12_377_5.zok | 31 +++++++++++++++---- 6 files changed, 83 insertions(+), 26 deletions(-) diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json index c844890a..0a6e7a71 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.json @@ -5,7 +5,6 @@ { "input": { "values": [ - "1", "14854361253166356985827940126714566475275412573126716429346293669288261212877767002588736768495892518280555332082", "213732210873464696846782550184555137228225514409080200587629835423679101735680889388490505365220726936653232900722", "87538607630632344401950048588801759619324114043687193925268161368645768079512372989046887060116208844098222887523", @@ -14,6 +13,7 @@ "239017299818740889416561988179003000999440599788233589838386981563280711497257601212385904595560069610856834048609", "210817940648895568697680255986492415724502544301527123629003695092329489846191300997148203752109923795482648905049", "104796720182429147963427519368170838521257629224027565408974396362211239635140389257768036297199752289691646178885", + "1", "237849156256827398282019388933972533154056715710612980343582379691235964002811111531637163291964836316287473866944", "121324456153144638357885760921484124420296650752569739652599982435599667566663818850130137668154167962818124679946", "73600332144130508132510040050892177274732799381796146541825372722030832659283233558443467575385522990242420388929", diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok index b4df2dca..ac406215 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_1.zok @@ -1,16 +1,35 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 1 public input (0 inputs + 1 output) -// Circuit used in this test (compiled using `bls12_377` curve): +// Circuit used in this test: // // def main() -> field: // return 1 // -// Arguments: -// inputs - public inputs of the circuit -// proof - flattened proof to an array of field elements -// vk - flattened verification key to an array of field elements +// Save the circuit as "circuit.zok" and run the following commands (in order): +// $ zokrates compile -i ./circuit.zok -c bls12_377 +// $ zokrates compute-witness +// $ zokrates setup -b ark -s gm17 +// $ zokrates generate-proof -b ark -s gm17 +// +// To get flattened inputs needed for this test, use the following script: +// #!/usr/bin/env node +// +// const path = require("path"); +// const fs = require("fs"); +// +// let output = [] +// for (let i = 2; i < process.argv.length; i++) { +// const source = fs.readFileSync(path.resolve(process.argv[i]), 'utf8') +// const flat = [...source.matchAll(/0x[a-z0-9]+/gm)].map(n => BigInt(n).toString(10)); +// output.push(...flat) +// } +// +// console.log(JSON.stringify(output)); +// +// Save this script as "flatten.js" and run the following command: +// $ node flatten.js proof.json verification.key -def main(private field[1] inputs, private field[8] proof, private field[20] vk) -> bool: +def main(private field[8] proof, private field[1] inputs, private field[20] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json index 00a7b238..096e63d2 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.json @@ -5,8 +5,6 @@ { "input": { "values": [ - "2", - "4", "30886639936493049016175318852868223421962513695924799011862965798142544864756272917016480650319179059444391880142", "210714472424410627451557273311118253425679108293022860127144278352441005505195339659420709617036779682326673533186", "101969549978420613687361685686211943788361418391955806064423246725556175258043096446227634997412743489772585976407", @@ -15,6 +13,8 @@ "156965166665593649649919836247487186182263277589020558979047044043456286367751723077006781061358137877318135673282", "137741518433065408317198878994358008499493756319076293122811213051853618947340414216838530582726247267590705502194", "126547036337175013106414910386451161000910611736141896590177615068467376299665795605927145787930213987505973766731", + "2", + "4", "26150522755032959261786285436959898551137848025504557005325333189168466417284586793885098543725273736029879389211", "169754513648720531797744265077389392707096818238531464510797707592538650668826008029773773893361012602508598834793", "172926009578431040673671475398833553033375949638930965254433842547261096474109828672139964685904707258254717562981", diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok index 1bdb7bdd..47ec38d6 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_2.zok @@ -1,16 +1,35 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 2 public inputs (1 input + 1 output) -// Circuit used in this test (compiled using `bls12_377` curve): +// Circuit used in this test: // // def main(field a) -> field: // return a * a // -// Arguments: -// inputs - public inputs of the circuit -// proof - flattened proof to an array of field elements -// vk - flattened verification key to an array of field elements +// Save the circuit as "circuit.zok" and run the following commands (in order): +// $ zokrates compile -i ./circuit.zok -c bls12_377 +// $ zokrates compute-witness -a 2 +// $ zokrates setup -b ark -s gm17 +// $ zokrates generate-proof -b ark -s gm17 +// +// To get flattened inputs needed for this test, use the following script: +// #!/usr/bin/env node +// +// const path = require("path"); +// const fs = require("fs"); +// +// let output = [] +// for (let i = 2; i < process.argv.length; i++) { +// const source = fs.readFileSync(path.resolve(process.argv[i]), 'utf8') +// const flat = [...source.matchAll(/0x[a-z0-9]+/gm)].map(n => BigInt(n).toString(10)); +// output.push(...flat) +// } +// +// console.log(JSON.stringify(output)); +// +// Save this script as "flatten.js" and run the following command: +// $ node flatten.js proof.json verification.key -def main(private field[2] inputs, private field[8] proof, private field[22] vk) -> bool: +def main(private field[8] proof, private field[2] inputs, private field[22] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json index 8c05a0ba..bbd9e48c 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.json @@ -5,11 +5,6 @@ { "input": { "values": [ - "2", - "2", - "2", - "2", - "8", "60457684924193218954780799695448128402450659922819148866042534731462934804174889585425668379894806827192129355035", "30692976080216123852486339295726836787768525847434467843252380267593056117653493955651719058012291818530914713503", "125357500613234885873309304302314409734224357144836572740733227274842238671614205545693580811504410323545780196986", @@ -18,6 +13,11 @@ "52408210490520029867007596145203947635265945726032430791270964404506413872638222587937059680769423104224418341783", "245391920863498220927838330312555206148254951255756591670548373412908886220063896460749603543488483619267089689381", "78589112605630898410537770266153128219408270888620016803188045523021815277982064356841045190284469829851165791293", + "2", + "2", + "2", + "2", + "8", "177010185638377511324501604520563739739317808509681430951164029757345810095174696221494505373089763385490312116358", "153053794329278051178743982884522858761476481700312111393093980133181276780354993379856934110282786295862092443919", "119352601414532465114802089751399530705471140760948692288569726825270783170792459863146836606243083937386903791326", diff --git a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok index 48514273..3e828495 100644 --- a/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok +++ b/zokrates_core_test/tests/tests/snark/snark_verify_bls12_377_5.zok @@ -1,7 +1,7 @@ from "EMBED" import snark_verify_bls12_377 // Verifies a proof with 5 public inputs (4 inputs + 1 output) -// Circuit used in this test (compiled using `bls12_377` curve): +// Circuit used in this test: // // def main(field[4] a) -> field: // field out = 0 @@ -10,11 +10,30 @@ from "EMBED" import snark_verify_bls12_377 // endfor // return out // -// Arguments: -// inputs - public inputs of the circuit -// proof - flattened proof to an array of field elements -// vk - flattened verification key to an array of field elements +// Save the circuit as "circuit.zok" and run the following commands (in order): +// $ zokrates compile -i ./circuit.zok -c bls12_377 +// $ zokrates compute-witness -a 2 2 2 2 +// $ zokrates setup -b ark -s gm17 +// $ zokrates generate-proof -b ark -s gm17 +// +// To get flattened inputs needed for this test, use the following script: +// #!/usr/bin/env node +// +// const path = require("path"); +// const fs = require("fs"); +// +// let output = [] +// for (let i = 2; i < process.argv.length; i++) { +// const source = fs.readFileSync(path.resolve(process.argv[i]), 'utf8') +// const flat = [...source.matchAll(/0x[a-z0-9]+/gm)].map(n => BigInt(n).toString(10)); +// output.push(...flat) +// } +// +// console.log(JSON.stringify(output)); +// +// Save this script as "flatten.js" and run the following command: +// $ node flatten.js proof.json verification.key -def main(private field[5] inputs, private field[8] proof, private field[28] vk) -> bool: +def main(private field[8] proof, private field[5] inputs, private field[28] vk) -> bool: bool result = snark_verify_bls12_377(inputs, proof, vk) return result \ No newline at end of file