diff --git a/Cargo.lock b/Cargo.lock index 7376e456..ccf8b105 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1246,7 +1246,6 @@ version = "0.1.0" dependencies = [ "bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)", "sapling-crypto 0.0.4 (git+https://github.com/matterinc/sapling-crypto?tag=0.0.4)", - "zokrates_field 0.3.2", ] [[package]] diff --git a/zokrates_core/src/helpers/rust.rs b/zokrates_core/src/helpers/rust.rs index 67f0ffe9..06c9cb24 100644 --- a/zokrates_core/src/helpers/rust.rs +++ b/zokrates_core/src/helpers/rust.rs @@ -57,8 +57,13 @@ impl Executable for RustHelper { RustHelper::Sha256Round => { let i = &inputs[0..512]; let h = &inputs[512..]; + let i: Vec<_> = i.iter().map(|x| x.clone().into_bellman()).collect(); + let h: Vec<_> = h.iter().map(|x| x.clone().into_bellman()).collect(); assert!(h.len() == 256); - Ok(generate_sha256_round_witness(i, h)) + Ok(generate_sha256_round_witness::(&i, &h) + .into_iter() + .map(|x| T::from_bellman(x)) + .collect()) } } } diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 358c036e..90cc46aa 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -138,7 +138,7 @@ impl Importer { for import in destination.imports.iter() { let pos = import.pos(); let import = &import.value; - // handle the case of special libsnark and packing imports + // handle the case of special bellman and packing imports if import.source.starts_with("BELLMAN") { match import.source.as_ref() { "BELLMAN/sha256round" => { diff --git a/zokrates_core/src/standard.rs b/zokrates_core/src/standard.rs index e533920c..7695f66d 100644 --- a/zokrates_core/src/standard.rs +++ b/zokrates_core/src/standard.rs @@ -3,16 +3,17 @@ use flat_absy::{FlatParameter, FlatVariable}; use helpers::{DirectiveStatement, Helper, RustHelper}; use reduce::Reduce; use types::{Signature, Type}; +use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint}; use zokrates_field::field::Field; -impl From> for FlatStatement { - fn from(c: zokrates_embed::Constraint) -> FlatStatement { +impl From> for FlatStatement { + fn from(c: zokrates_embed::BellmanConstraint) -> FlatStatement { let rhs_a = match c .a .into_iter() .map(|(key, val)| { FlatExpression::Mult( - box FlatExpression::Number(val), + box FlatExpression::Number(T::from_bellman(val)), box FlatExpression::Identifier(FlatVariable::new(key)), ) }) @@ -30,7 +31,7 @@ impl From> for FlatStatement { .into_iter() .map(|(key, val)| { FlatExpression::Mult( - box FlatExpression::Number(val), + box FlatExpression::Number(T::from_bellman(val)), box FlatExpression::Identifier(FlatVariable::new(key)), ) }) @@ -48,7 +49,7 @@ impl From> for FlatStatement { .into_iter() .map(|(key, val)| { FlatExpression::Mult( - box FlatExpression::Number(val), + box FlatExpression::Number(T::from_bellman(val)), box FlatExpression::Identifier(FlatVariable::new(key)), ) }) @@ -66,7 +67,8 @@ impl From> for FlatStatement { } pub fn sha_round() -> FlatFunction { - let (r1cs, input, current_hash, output) = zokrates_embed::generate_sha256_round_constraints(); + let (r1cs, input, current_hash, output) = + generate_sha256_round_constraints::(); let variable_count = r1cs.aux_count + 1; // auxiliary and ONE @@ -219,13 +221,6 @@ mod tests { private: vec![true; 768], }; - //use rand::Rng; - - // let mut rng = rand::thread_rng(); - // let input: Vec<_> = (0..768).map(|_| { - // rng.gen_range(0, 2) - // }).collect(); - let input = (0..512).map(|_| 0).chain((0..256).map(|_| 1)).collect(); prog.execute(&input).unwrap(); diff --git a/zokrates_embed/Cargo.toml b/zokrates_embed/Cargo.toml index 4d92695b..176710c6 100644 --- a/zokrates_embed/Cargo.toml +++ b/zokrates_embed/Cargo.toml @@ -6,5 +6,4 @@ edition = "2018" [dependencies] sapling-crypto = { git = 'https://github.com/matterinc/sapling-crypto', tag = "0.0.4" } -bellman = { git = 'https://github.com/matterinc/bellman', tag = "0.2.0" } -zokrates_field = { path = "../zokrates_field" } \ No newline at end of file +bellman = { git = 'https://github.com/matterinc/bellman', tag = "0.2.0" } \ No newline at end of file diff --git a/zokrates_embed/src/lib.rs b/zokrates_embed/src/lib.rs index 98dea5fb..21b963df 100644 --- a/zokrates_embed/src/lib.rs +++ b/zokrates_embed/src/lib.rs @@ -1,15 +1,15 @@ +use bellman::pairing::ff::Field; use bellman::pairing::Engine; use bellman::ConstraintSystem; use bellman::{Index, LinearCombination, SynthesisError, Variable}; use sapling_crypto::circuit::boolean::{AllocatedBit, Boolean}; use sapling_crypto::circuit::sha256::sha256_compression_function; use sapling_crypto::circuit::uint32::UInt32; -use zokrates_field::field::Field; #[derive(Debug)] -struct BellmanR1CS { - aux_count: usize, - constraints: Vec>, +pub struct BellmanR1CS { + pub aux_count: usize, + pub constraints: Vec>, } impl BellmanR1CS { @@ -22,40 +22,29 @@ impl BellmanR1CS { } #[derive(Debug)] -struct BellmanWitness { +pub struct BellmanWitness { pub values: Vec, } #[derive(Debug, PartialEq)] -struct BellmanConstraint { +pub struct BellmanConstraint { pub a: Vec<(usize, E::Fr)>, pub b: Vec<(usize, E::Fr)>, pub c: Vec<(usize, E::Fr)>, } -#[derive(Debug, PartialEq)] -pub struct Constraint { - pub a: Vec<(usize, T)>, - pub b: Vec<(usize, T)>, - pub c: Vec<(usize, T)>, -} - -#[derive(Debug)] -pub struct R1CS { - pub aux_count: usize, - pub constraints: Vec>, -} - -fn sha256_round>( +fn sha256_round>( mut cs: CS, - input: Option<&Vec>, - current_hash: Option<&Vec>, + input: &Vec>, + current_hash: &Vec>, ) -> Result<(Vec, Vec, Vec), SynthesisError> { - let input_bits = (0..512) - .map(|i| { - AllocatedBit::alloc::( - &mut cs.namespace(|| format!("input_{}", i)), - Some(input.as_ref().unwrap()[i] == T::from(1)), + let input_bits = input + .iter() + .enumerate() + .map(|(index, i)| { + AllocatedBit::alloc::( + &mut cs.namespace(|| format!("input_{}", index)), + Some(*i == Some(::one())), ) .unwrap() }) @@ -66,11 +55,13 @@ fn sha256_round>( .map(|i| Boolean::Is(i.clone())) .collect::>(); - let current_hash_bits = (0..256) - .map(|i| { - AllocatedBit::alloc::( - &mut cs.namespace(|| format!("current_hash_{}", i)), - Some(current_hash.as_ref().unwrap()[i] == T::from(1)), + 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() }) @@ -88,8 +79,7 @@ fn sha256_round>( }) .collect::>(); - let res = - sha256_compression_function::(&mut cs, &input, ¤t_hash).unwrap(); + let res = sha256_compression_function::(&mut cs, &input, ¤t_hash).unwrap(); let output_bits = res .into_iter() @@ -100,59 +90,23 @@ fn sha256_round>( Ok(( input_bits .into_iter() - .map(|b| BellmanR1CS::::var_to_index(b.get_variable())) + .map(|b| var_to_index(b.get_variable())) .collect(), current_hash_bits .into_iter() - .map(|b| BellmanR1CS::::var_to_index(b.get_variable())) + .map(|b| var_to_index(b.get_variable())) .collect(), output_bits .into_iter() - .map(|b| BellmanR1CS::::var_to_index(b.get_variable())) + .map(|b| var_to_index(b.get_variable())) .collect(), )) } -impl R1CS { - fn from_bellman(cs: BellmanR1CS) -> Self { - R1CS { - aux_count: cs.aux_count, - constraints: cs - .constraints - .into_iter() - .map(|c| Constraint::from_bellman(c)) - .collect(), - } - } -} - -impl Constraint { - fn from_bellman(cs: BellmanConstraint) -> Self { - let res = Constraint { - a: cs - .a - .into_iter() - .map(|(variable, coefficient)| (variable, T::from_bellman(coefficient))) - .collect(), - b: cs - .b - .into_iter() - .map(|(variable, coefficient)| (variable, T::from_bellman(coefficient))) - .collect(), - c: cs - .c - .into_iter() - .map(|(variable, coefficient)| (variable, T::from_bellman(coefficient))) - .collect(), - }; - res - } -} - impl ConstraintSystem for BellmanWitness { type Root = Self; - fn alloc(&mut self, _annotation: A, f: F) -> Result + fn alloc(&mut self, _: A, f: F) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, @@ -165,7 +119,7 @@ impl ConstraintSystem for BellmanWitness { Ok(var) } - fn alloc_input(&mut self, _annotation: A, _f: F) -> Result + fn alloc_input(&mut self, _: A, _: F) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, @@ -174,7 +128,7 @@ impl ConstraintSystem for BellmanWitness { unreachable!("Bellman helpers are not allowed to allocate public variables") } - fn enforce(&mut self, _annotation: A, _a: LA, _b: LB, _c: LC) + fn enforce(&mut self, _: A, _: LA, _: LB, _: LC) where A: FnOnce() -> AR, AR: Into, @@ -185,7 +139,7 @@ impl ConstraintSystem for BellmanWitness { // do nothing } - fn push_namespace(&mut self, _name_fn: N) + fn push_namespace(&mut self, _: N) where NR: Into, N: FnOnce() -> NR, @@ -205,7 +159,7 @@ impl ConstraintSystem for BellmanWitness { impl ConstraintSystem for BellmanR1CS { type Root = Self; - fn alloc(&mut self, _annotation: A, _f: F) -> Result + fn alloc(&mut self, _: A, _: F) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, @@ -218,7 +172,7 @@ impl ConstraintSystem for BellmanR1CS { Ok(var) } - fn alloc_input(&mut self, _annotation: A, _f: F) -> Result + fn alloc_input(&mut self, _: A, _: F) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, @@ -227,7 +181,7 @@ impl ConstraintSystem for BellmanR1CS { unreachable!("Bellman helpers are not allowed to allocate public variables") } - fn enforce(&mut self, _annotation: A, a: LA, b: LB, c: LC) + fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) where A: FnOnce() -> AR, AR: Into, @@ -242,29 +196,23 @@ impl ConstraintSystem for BellmanR1CS { let a = a .as_ref() .into_iter() - .map(|(variable, coefficient)| { - (BellmanR1CS::::var_to_index(*variable), *coefficient) - }) + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) .collect(); let b = b .as_ref() .into_iter() - .map(|(variable, coefficient)| { - (BellmanR1CS::::var_to_index(*variable), *coefficient) - }) + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) .collect(); let c = c .as_ref() .into_iter() - .map(|(variable, coefficient)| { - (BellmanR1CS::::var_to_index(*variable), *coefficient) - }) + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) .collect(); self.constraints.push(BellmanConstraint { a, b, c }); } - fn push_namespace(&mut self, _name_fn: N) + fn push_namespace(&mut self, _: N) where NR: Into, N: FnOnce() -> NR, @@ -281,83 +229,55 @@ impl ConstraintSystem for BellmanR1CS { } } -pub fn generate_xor_constraints() -> (R1CS, usize) { +pub fn generate_sha256_round_constraints( +) -> (BellmanR1CS, Vec, Vec, Vec) { let mut cs = BellmanR1CS::new(); - let i0 = Boolean::Is(AllocatedBit::alloc::(&mut cs, None).unwrap()); - let i1 = Boolean::Is(AllocatedBit::alloc::(&mut cs, None).unwrap()); - - let res = Boolean::xor(&mut cs, &i0, &i1).unwrap(); - let res = - BellmanR1CS::::var_to_index(res.get_variable().unwrap().get_variable()); - - let cs = R1CS::from_bellman(cs); - - (cs, res) -} - -pub fn generate_xor_witness(i1: bool, i2: bool) -> Vec { - let mut cs = BellmanWitness { - values: vec![T::from(1).into_bellman()], - }; - - let i0 = Boolean::Is(AllocatedBit::alloc::(&mut cs, Some(i1)).unwrap()); - let i1 = Boolean::Is(AllocatedBit::alloc::(&mut cs, Some(i2)).unwrap()); - - Boolean::xor(&mut cs, &i0, &i1).unwrap(); - - cs.values.into_iter().map(|v| T::from_bellman(v)).collect() -} - -pub fn generate_sha256_round_constraints() -> (R1CS, Vec, Vec, Vec) -{ - let mut cs = BellmanR1CS::new(); - - let (input_bits, current_hash_bits, output_bits) = sha256_round::( - &mut cs, - Some(&vec![T::from(0); 512]), - Some(&vec![T::from(0); 256]), - ) - .unwrap(); + let (input_bits, current_hash_bits, output_bits) = + sha256_round(&mut cs, &vec![None; 512], &vec![None; 256]).unwrap(); // res is now the allocated bits for input, current_hash and sha256_output - let cs = R1CS::::from_bellman(cs); - (cs, input_bits, current_hash_bits, output_bits) } -pub fn generate_sha256_round_witness(input: &[T], current_hash: &[T]) -> Vec { +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 { - values: vec![T::from(1).into_bellman()], + let mut cs: BellmanWitness = BellmanWitness { + values: vec![::one()], }; - sha256_round(&mut cs, Some(&input.to_vec()), Some(¤t_hash.to_vec())).unwrap(); + sha256_round( + &mut cs, + &input.iter().map(|x| Some(x.clone())).collect(), + ¤t_hash.iter().map(|x| Some(x.clone())).collect(), + ) + .unwrap(); - cs.values.into_iter().map(|v| T::from_bellman(v)).collect() + cs.values } -impl BellmanR1CS { - fn var_to_index(v: Variable) -> usize { - match v.get_unchecked() { - Index::Aux(i) => i + 1, - Index::Input(0) => 0, - _ => unreachable!(), - } +fn var_to_index(v: Variable) -> usize { + match v.get_unchecked() { + Index::Aux(i) => i + 1, + Index::Input(0) => 0, + _ => unreachable!(), } } #[cfg(test)] mod tests { use super::*; - use zokrates_field::field::FieldPrime; + use bellman::pairing::bn256::{Bn256, Fr}; #[test] fn generate_constraints() { - let (_c, input, current_hash, output) = generate_sha256_round_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); @@ -365,45 +285,21 @@ mod tests { #[test] fn generate_witness() { - let witness = generate_sha256_round_witness( - &vec![FieldPrime::from(0); 512], - &vec![FieldPrime::from(0); 256], - ); + let witness = + generate_sha256_round_witness::(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]); assert_eq!(witness.len(), 26935); } - #[test] - fn xor() { - let (_, indice) = generate_xor_constraints::(); - - assert_eq!( - FieldPrime::from(0), - generate_xor_witness::(true, true)[indice] - ); - assert_eq!( - FieldPrime::from(1), - generate_xor_witness::(true, false)[indice] - ); - assert_eq!( - FieldPrime::from(1), - generate_xor_witness::(false, true)[indice] - ); - assert_eq!( - FieldPrime::from(0), - generate_xor_witness::(false, false)[indice] - ); - } - #[test] fn test_cs() { use sapling_crypto::circuit::test::TestConstraintSystem; - let mut cs = TestConstraintSystem::new(); + let mut cs: TestConstraintSystem = TestConstraintSystem::new(); - let _ = sha256_round::( + let _ = sha256_round( &mut cs, - Some(&vec![FieldPrime::from(0); 512]), - Some(&vec![FieldPrime::from(1); 256]), + &vec![Some(Fr::zero()); 512], + &vec![Some(Fr::one()); 256], ) .unwrap();