From 59f62d2ffa8f5e365d5564db39b91841e56d4e06 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 7 Jun 2021 13:13:21 +0200 Subject: [PATCH] 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::*;