diff --git a/.circleci/config.yml b/.circleci/config.yml index 0bfef41ee..655d5b522 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,7 +45,7 @@ jobs: - run: name: Run tests no_output_timeout: 1h - command: RUSTFLAGS="-D warnings" ./test.sh + command: RUSTFLAGS="-D warnings" RUST_BACKTRACE=1 ./test.sh - save-sccache-cache wasm_test: docker: @@ -79,7 +79,7 @@ jobs: - run: name: Run integration tests no_output_timeout: "30m" - command: RUSTFLAGS="-D warnings" ./integration_test.sh + command: RUSTFLAGS="-D warnings" RUST_BACKTRACE=1 ./integration_test.sh - save-sccache-cache deploy: docker: diff --git a/Cargo.lock b/Cargo.lock index c6dff4f88..cb6ac7d6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,8 +437,9 @@ dependencies = [ [[package]] name = "bellman_ce" version = "0.3.2" -source = "git+https://github.com/georgwiese/bellman?rev=b356c7001f30da23bfad2b43eb0b7ca9804c8252#b356c7001f30da23bfad2b43eb0b7ca9804c8252" +source = "git+https://github.com/georgwiese/bellman?rev=dbed83d1971c29e8fdb07d341e8593fef8ba5eab#dbed83d1971c29e8fdb07d341e8593fef8ba5eab" dependencies = [ + "arrayvec 0.7.2", "bit-vec", "blake2s_const", "blake2s_simd", @@ -446,33 +447,17 @@ dependencies = [ "cfg-if 1.0.0", "crossbeam", "futures", - "hex 0.4.3", + "hex 0.3.2", "lazy_static", "num_cpus", "pairing_ce 0.28.2", "rand 0.4.6", "serde", + "smallvec", "tiny-keccak 1.5.0", "web-sys", ] -[[package]] -name = "bellman_ce" -version = "0.3.2" -source = "git+https://github.com/matter-labs/bellman#09474aa6fcb200a7da96f46495452fae92503ed8" -dependencies = [ - "bit-vec", - "blake2s_simd", - "byteorder", - "cfg-if 1.0.0", - "futures", - "hex 0.4.3", - "num_cpus", - "pairing_ce 0.28.2", - "rand 0.4.6", - "serde", -] - [[package]] name = "bellman_ce" version = "0.3.5" @@ -572,7 +557,7 @@ dependencies = [ [[package]] name = "blake2s_const" version = "0.6.0" -source = "git+https://github.com/georgwiese/bellman?rev=b356c7001f30da23bfad2b43eb0b7ca9804c8252#b356c7001f30da23bfad2b43eb0b7ca9804c8252" +source = "git+https://github.com/georgwiese/bellman?rev=dbed83d1971c29e8fdb07d341e8593fef8ba5eab#dbed83d1971c29e8fdb07d341e8593fef8ba5eab" dependencies = [ "arrayref", "arrayvec 0.5.2", @@ -2587,6 +2572,12 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + [[package]] name = "solc" version = "0.1.0" @@ -3182,7 +3173,23 @@ dependencies = [ name = "zokrates_bellman" version = "0.1.0" dependencies = [ - "bellman_ce 0.3.2 (git+https://github.com/georgwiese/bellman?rev=b356c7001f30da23bfad2b43eb0b7ca9804c8252)", + "bellman_ce 0.3.5", + "getrandom", + "hex 0.4.3", + "pairing_ce 0.21.1", + "phase2", + "rand 0.4.6", + "zokrates_ast", + "zokrates_field", + "zokrates_interpreter", + "zokrates_proof_systems", +] + +[[package]] +name = "zokrates_bellman_plonk" +version = "0.1.0" +dependencies = [ + "bellman_ce 0.3.2", "getrandom", "hex 0.4.3", "phase2", @@ -3238,6 +3245,7 @@ dependencies = [ "zokrates_ark", "zokrates_ast", "zokrates_bellman", + "zokrates_bellman_plonk", "zokrates_circom", "zokrates_common", "zokrates_core", @@ -3313,7 +3321,8 @@ dependencies = [ "ark-ec", "ark-ff", "ark-serialize", - "bellman_ce 0.3.2 (git+https://github.com/matter-labs/bellman)", + "bellman_ce 0.3.2", + "bellman_ce 0.3.5", "bincode", "lazy_static", "num-bigint 0.2.6", diff --git a/Cargo.toml b/Cargo.toml index 92c7358e2..9ac09a8be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "zokrates_interpreter", "zokrates_embed", "zokrates_bellman", + "zokrates_bellman_plonk", "zokrates_proof_systems", "zokrates_js", "zokrates_circom" diff --git a/zokrates_bellman/Cargo.toml b/zokrates_bellman/Cargo.toml index 12cb4a9bc..852b1fbed 100644 --- a/zokrates_bellman/Cargo.toml +++ b/zokrates_bellman/Cargo.toml @@ -4,16 +4,16 @@ version = "0.1.0" edition = "2021" [features] -wasm = ["bellman_ce/nolog", "bellman_ce/wasm"] -multicore = ["bellman_ce/multicore", "phase2/multicore"] +wasm = ["bellman/nolog", "bellman/wasm"] +multicore = ["bellman/multicore", "phase2/multicore"] [dependencies] zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } -bellman_ce = { git = "https://github.com/georgwiese/bellman", rev="b356c7001f30da23bfad2b43eb0b7ca9804c8252", default-features = false, features = ["plonk", "multicore"] } -# pairing = { package = "pairing_ce", version = "^0.21" } +bellman = { package = "bellman_ce", version = "^0.3", default-features = false } +pairing = { package = "pairing_ce", version = "^0.21" } phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false } rand_0_4 = { version = "0.4", package = "rand" }# getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] } diff --git a/zokrates_bellman/src/groth16.rs b/zokrates_bellman/src/groth16.rs index 6718ec019..d8afaf50d 100644 --- a/zokrates_bellman/src/groth16.rs +++ b/zokrates_bellman/src/groth16.rs @@ -2,17 +2,20 @@ use bellman::groth16::{ prepare_verifying_key, verify_proof, Parameters, PreparedVerifyingKey, Proof as BellmanProof, VerifyingKey, }; -use bellman::pairing::{ff::to_hex, CurveAffine, Engine}; +use pairing::{ff::to_hex, CurveAffine, Engine}; use zokrates_field::BellmanFieldExtensions; use zokrates_field::Field; use zokrates_proof_systems::{ - Backend, G1Affine, G2Affine, NonUniversalBackend, Proof, SetupKeypair, + Backend, G1Affine, G2Affine, MpcBackend, NonUniversalBackend, Proof, SetupKeypair, }; use crate::Bellman; use crate::Computation; use crate::{parse_g1, parse_g2, serialization}; +use phase2::MPCParameters; +use rand_0_4::Rng; +use std::io::{Read, Write}; use zokrates_ast::ir::{ProgIterator, Statement, Witness}; use zokrates_proof_systems::groth16::{ProofPoints, VerificationKey, G16}; use zokrates_proof_systems::Scheme; @@ -97,60 +100,60 @@ impl NonUniversalBackend for Bellman } } -// impl MpcBackend for Bellman { -// fn initialize>>( -// program: ProgIterator, -// phase1_radix: &mut R, -// output: &mut W, -// ) -> Result<(), String> { -// let circuit = Computation::without_witness(program); -// let params = MPCParameters::new(circuit, phase1_radix).map_err(|e| e.to_string())?; -// params.write(output).map_err(|e| e.to_string())?; -// Ok(()) -// } - -// fn contribute( -// params: &mut R, -// rng: &mut G, -// output: &mut W, -// ) -> Result<[u8; 64], String> { -// let mut params = -// MPCParameters::::read(params, true).map_err(|e| e.to_string())?; - -// let hash = params.contribute(rng); -// params.write(output).map_err(|e| e.to_string())?; - -// Ok(hash) -// } - -// fn verify>>( -// params: &mut P, -// program: ProgIterator, -// phase1_radix: &mut R, -// ) -> Result, String> { -// let params = -// MPCParameters::::read(params, true).map_err(|e| e.to_string())?; - -// let circuit = Computation::without_witness(program); -// let hashes = params -// .verify(circuit, phase1_radix) -// .map_err(|_| "parameters malformed".to_string())?; - -// Ok(hashes) -// } - -// fn export_keypair(params: &mut R) -> Result, String> { -// let params = -// MPCParameters::::read(params, true).map_err(|e| e.to_string())?; - -// let params = params.get_params(); -// let mut pk: Vec = Vec::new(); -// params.write(&mut pk).map_err(|e| e.to_string())?; - -// let vk = serialization::parameters_to_verification_key::(params); -// Ok(SetupKeypair::new(vk, pk)) -// } -// } +impl MpcBackend for Bellman { + fn initialize>>( + program: ProgIterator, + phase1_radix: &mut R, + output: &mut W, + ) -> Result<(), String> { + let circuit = Computation::without_witness(program); + let params = MPCParameters::new(circuit, phase1_radix).map_err(|e| e.to_string())?; + params.write(output).map_err(|e| e.to_string())?; + Ok(()) + } + + fn contribute( + params: &mut R, + rng: &mut G, + output: &mut W, + ) -> Result<[u8; 64], String> { + let mut params = + MPCParameters::::read(params, true).map_err(|e| e.to_string())?; + + let hash = params.contribute(rng); + params.write(output).map_err(|e| e.to_string())?; + + Ok(hash) + } + + fn verify>>( + params: &mut P, + program: ProgIterator, + phase1_radix: &mut R, + ) -> Result, String> { + let params = + MPCParameters::::read(params, true).map_err(|e| e.to_string())?; + + let circuit = Computation::without_witness(program); + let hashes = params + .verify(circuit, phase1_radix) + .map_err(|_| "parameters malformed".to_string())?; + + Ok(hashes) + } + + fn export_keypair(params: &mut R) -> Result, String> { + let params = + MPCParameters::::read(params, true).map_err(|e| e.to_string())?; + + let params = params.get_params(); + let mut pk: Vec = Vec::new(); + params.write(&mut pk).map_err(|e| e.to_string())?; + + let vk = parameters_to_verification_key::(params); + Ok(SetupKeypair::new(vk, pk)) + } +} pub fn parameters_to_verification_key( parameters: &Parameters, diff --git a/zokrates_bellman/src/lib.rs b/zokrates_bellman/src/lib.rs index 04022152e..6ceee8157 100644 --- a/zokrates_bellman/src/lib.rs +++ b/zokrates_bellman/src/lib.rs @@ -1,7 +1,4 @@ pub mod groth16; -pub mod plonk; - -extern crate bellman_ce as bellman; use bellman::groth16::Proof; use bellman::groth16::{ @@ -200,7 +197,7 @@ impl>> Co pub mod serialization { use super::*; - use bellman::{pairing::from_hex, CurveAffine, Engine}; + use bellman::{pairing::from_hex, pairing::CurveAffine, pairing::Engine}; use zokrates_proof_systems::{G1Affine, G2Affine}; pub fn to_g1( @@ -243,7 +240,7 @@ pub mod serialization { mod parse { use super::*; - use bellman::{pairing::CurveAffine, PrimeField}; + use bellman::{pairing::ff::PrimeField, pairing::CurveAffine}; use zokrates_proof_systems::{Fq2, Fr, G1Affine, G2Affine, GAffine}; fn to_hex(bytes: &[u8]) -> String { @@ -277,7 +274,7 @@ mod parse { pub fn parse_fr( e: &::Fr, ) -> Fr { - use crate::bellman::PrimeFieldRepr; + use bellman::pairing::ff::PrimeFieldRepr; let mut bytes: Vec = Vec::new(); e.into_repr().write_le(&mut bytes).unwrap(); bytes.reverse(); diff --git a/zokrates_bellman_plonk/Cargo.toml b/zokrates_bellman_plonk/Cargo.toml new file mode 100644 index 000000000..a2c28eee3 --- /dev/null +++ b/zokrates_bellman_plonk/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "zokrates_bellman_plonk" +version = "0.1.0" +edition = "2021" + +[features] +wasm = ["bellman_ce/nolog", "bellman_ce/wasm"] +multicore = ["bellman_ce/multicore", "phase2/multicore"] + +[dependencies] +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } + +bellman_ce = { git = "https://github.com/georgwiese/bellman", rev="dbed83d1971c29e8fdb07d341e8593fef8ba5eab", default-features = false, features = ["plonk", "multicore"] } +phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false } +rand_0_4 = { version = "0.4", package = "rand" }# +getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] } +hex = "0.4.2" + +[dev-dependencies] +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter", features = ["bellman"] } + + + + + diff --git a/zokrates_bellman_plonk/src/lib.rs b/zokrates_bellman_plonk/src/lib.rs new file mode 100644 index 000000000..f7f5ca9bc --- /dev/null +++ b/zokrates_bellman_plonk/src/lib.rs @@ -0,0 +1,472 @@ +pub mod plonk; + +extern crate bellman_ce as bellman; + +use bellman::groth16::Proof; +use bellman::groth16::{ + create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, + Parameters, +}; +use bellman::pairing::ff::ScalarEngine; +use bellman::{ + Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable as BellmanVariable, +}; +use std::collections::BTreeMap; +use zokrates_ast::common::Variable; +use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; +use zokrates_field::BellmanPlonkFieldExtensions; +use zokrates_field::Field; + +use rand_0_4::ChaChaRng; + +pub use self::parse::*; + +pub struct Bellman; + +#[derive(Clone)] +pub struct Computation>> { + program: ProgIterator, + witness: Option>, +} + +impl>> Computation { + pub fn with_witness(program: ProgIterator, witness: Witness) -> Self { + Computation { + program, + witness: Some(witness), + } + } + + pub fn without_witness(program: ProgIterator) -> Self { + Computation { + program, + witness: None, + } + } +} + +fn bellman_combination>( + l: CanonicalLinComb, + cs: &mut CS, + symbols: &mut BTreeMap, + witness: &mut Witness, +) -> LinearCombination { + l.0.into_iter() + .map(|(k, v)| { + ( + v.into_bellman(), + *symbols.entry(k).or_insert_with(|| { + match k.is_output() { + true => cs.alloc_input( + || format!("{}", k), + || { + Ok(witness + .0 + .remove(&k) + .ok_or(SynthesisError::AssignmentMissing)? + .into_bellman()) + }, + ), + false => cs.alloc( + || format!("{}", k), + || { + Ok(witness + .0 + .remove(&k) + .ok_or(SynthesisError::AssignmentMissing)? + .into_bellman()) + }, + ), + } + .unwrap() + }), + ) + }) + .fold(LinearCombination::zero(), |acc, e| acc + e) +} + +impl>> + Circuit for Computation +{ + fn synthesize>( + self, + cs: &mut CS, + ) -> Result<(), SynthesisError> { + // mapping from IR variables + let mut symbols = BTreeMap::new(); + + let mut witness = self.witness.unwrap_or_else(Witness::empty); + + assert!(symbols.insert(Variable::one(), CS::one()).is_none()); + + symbols.extend(self.program.arguments.iter().enumerate().map(|(index, p)| { + let wire = match p.private { + true => cs.alloc( + || format!("PRIVATE_INPUT_{}", index), + || { + Ok(witness + .0 + .remove(&p.id) + .ok_or(SynthesisError::AssignmentMissing)? + .into_bellman()) + }, + ), + false => cs.alloc_input( + || format!("PUBLIC_INPUT_{}", index), + || { + Ok(witness + .0 + .remove(&p.id) + .ok_or(SynthesisError::AssignmentMissing)? + .into_bellman()) + }, + ), + } + .unwrap(); + (p.id, wire) + })); + + for statement in self.program.statements { + if let Statement::Constraint(quad, lin, _) = statement { + let a = &bellman_combination( + quad.left.into_canonical(), + cs, + &mut symbols, + &mut witness, + ); + let b = &bellman_combination( + quad.right.into_canonical(), + cs, + &mut symbols, + &mut witness, + ); + let c = &bellman_combination(lin.into_canonical(), cs, &mut symbols, &mut witness); + + cs.enforce(|| "Constraint", |lc| lc + a, |lc| lc + b, |lc| lc + c); + } + } + + Ok(()) + } +} + +impl>> + Computation +{ + fn get_random_seed(&self) -> Result<[u32; 8], getrandom::Error> { + let mut seed = [0u8; 32]; + getrandom::getrandom(&mut seed)?; + + use std::mem::transmute; + // This is safe because we are just reinterpreting the bytes (u8[32] -> u32[8]), + // byte order or the actual content does not matter here as this is used + // as a random seed for the rng. + let seed: [u32; 8] = unsafe { transmute(seed) }; + Ok(seed) + } + + pub fn prove(self, params: &Parameters) -> Proof { + use rand_0_4::SeedableRng; + let seed = self.get_random_seed().unwrap(); + let rng = &mut ChaChaRng::from_seed(seed.as_ref()); + + // extract public inputs + let public_inputs = self.public_inputs_values(); + + let proof = create_random_proof(self, params, rng).unwrap(); + + let pvk = prepare_verifying_key(¶ms.vk); + + assert!(verify_proof(&pvk, &proof, &public_inputs).unwrap()); + + proof + } + + pub fn public_inputs_values(&self) -> Vec<::Fr> { + self.program + .public_inputs_values(self.witness.as_ref().unwrap()) + .iter() + .map(|v| v.clone().into_bellman()) + .collect() + } + + pub fn setup(self) -> Parameters { + use rand_0_4::SeedableRng; + let seed = self.get_random_seed().unwrap(); + let rng = &mut ChaChaRng::from_seed(seed.as_ref()); + // run setup phase + generate_random_parameters(self, rng).unwrap() + } +} + +pub mod serialization { + use super::*; + use bellman::{pairing::from_hex, pairing::CurveAffine, pairing::Engine}; + use zokrates_proof_systems::{G1Affine, G2Affine}; + + pub fn to_g1( + g1: G1Affine, + ) -> ::G1Affine { + if g1.is_infinity { + return ::G1Affine::zero(); + } + + ::G1Affine::from_xy_unchecked( + from_hex(&g1.x).unwrap(), + from_hex(&g1.y).unwrap(), + ) + } + pub fn to_g2( + g2: G2Affine, + ) -> ::G2Affine { + match g2 { + G2Affine::Fq2(g2) => { + if g2.is_infinity { + return ::G2Affine::zero(); + } + + let x = T::new_fq2(&(g2.x).0, &(g2.x).1); + let y = T::new_fq2(&(g2.y).0, &(g2.y).1); + ::G2Affine::from_xy_unchecked(x, y) + } + _ => unreachable!(), + } + } + + pub fn to_fr( + e: String, + ) -> ::Fr { + T::try_from_str(e.trim_start_matches("0x"), 16) + .unwrap() + .into_bellman() + } +} + +mod parse { + use super::*; + use bellman::{pairing::ff::PrimeField, pairing::CurveAffine}; + use zokrates_proof_systems::{Fq2, Fr, G1Affine, G2Affine, GAffine}; + + fn to_hex(bytes: &[u8]) -> String { + let mut hex = hex::encode(bytes); + hex.insert_str(0, "0x"); + hex + } + + pub fn parse_g1( + e: &::G1Affine, + ) -> G1Affine { + if e.is_zero() { + return G1Affine::infinity(); + } + + let uncompressed = e.into_uncompressed(); + let bytes: &[u8] = uncompressed.as_ref(); + + let mut iter = bytes.chunks(bytes.len() / 2); + + let x = to_hex(iter.next().unwrap()); + let y = to_hex(iter.next().unwrap()); + + G1Affine { + x, + y, + is_infinity: false, + } + } + + pub fn parse_fr( + e: &::Fr, + ) -> Fr { + use bellman::pairing::ff::PrimeFieldRepr; + let mut bytes: Vec = Vec::new(); + e.into_repr().write_le(&mut bytes).unwrap(); + bytes.reverse(); + + format!("0x{}", hex::encode(&bytes)) + } + + pub fn parse_g2( + e: &::G2Affine, + ) -> G2Affine { + if e.is_zero() { + return G2Affine::Fq2(GAffine::infinity()); + } + + let uncompressed = e.into_uncompressed(); + let bytes: &[u8] = uncompressed.as_ref(); + + let mut iter = bytes.chunks(bytes.len() / 4); + let x1 = to_hex(iter.next().unwrap()); + let x0 = to_hex(iter.next().unwrap()); + let y1 = to_hex(iter.next().unwrap()); + let y0 = to_hex(iter.next().unwrap()); + + G2Affine::Fq2(GAffine::new(Fq2(x0, x1), Fq2(y0, y1))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use zokrates_ast::ir::LinComb; + use zokrates_field::Bn128Field; + use zokrates_interpreter::Interpreter; + + mod prove { + use super::*; + use zokrates_ast::flat::Parameter; + use zokrates_ast::ir::Prog; + + #[test] + fn empty() { + let program: Prog = Prog::default(); + + let interpreter = Interpreter::default(); + + let witness = interpreter.execute(program.clone(), &[]).unwrap(); + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn identity() { + let program: Prog = Prog { + arguments: vec![Parameter::private(Variable::new(0))], + return_count: 1, + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bn128Field::from(0)]) + .unwrap(); + + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn public_identity() { + let program: Prog = Prog { + arguments: vec![Parameter::public(Variable::new(0))], + return_count: 1, + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bn128Field::from(0)]) + .unwrap(); + + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn no_arguments() { + let program: Prog = Prog { + arguments: vec![], + return_count: 1, + statements: vec![Statement::constraint(Variable::one(), Variable::public(0))], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter.execute(program.clone(), &[]).unwrap(); + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn unordered_variables() { + // public variables must be ordered from 0 + // private variables can be unordered + let program: Prog = Prog { + arguments: vec![ + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), + ], + return_count: 2, + statements: vec![ + Statement::constraint( + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), + ), + Statement::constraint( + LinComb::from(Variable::one()) + LinComb::from(Variable::new(42)), + Variable::public(1), + ), + ], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bn128Field::from(3), Bn128Field::from(4)]) + .unwrap(); + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn one() { + let program: Prog = Prog { + arguments: vec![Parameter::public(Variable::new(42))], + return_count: 1, + statements: vec![Statement::constraint( + LinComb::from(Variable::new(42)) + LinComb::one(), + Variable::public(0), + )], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bn128Field::from(3)]) + .unwrap(); + + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + + #[test] + fn with_directives() { + let program: Prog = Prog { + arguments: vec![ + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), + ], + return_count: 1, + statements: vec![Statement::constraint( + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), + )], + }; + + let interpreter = Interpreter::default(); + + let witness = interpreter + .execute(program.clone(), &[Bn128Field::from(3), Bn128Field::from(4)]) + .unwrap(); + let computation = Computation::with_witness(program, witness); + + let params = computation.clone().setup(); + let _proof = computation.prove(¶ms); + } + } +} diff --git a/zokrates_bellman/src/plonk.rs b/zokrates_bellman_plonk/src/plonk.rs similarity index 91% rename from zokrates_bellman/src/plonk.rs rename to zokrates_bellman_plonk/src/plonk.rs index d14e05afb..db99b48de 100644 --- a/zokrates_bellman/src/plonk.rs +++ b/zokrates_bellman_plonk/src/plonk.rs @@ -6,7 +6,7 @@ use bellman::plonk::{ Proof as BellmanProof, SetupPolynomials, VerificationKey as BellmanVerificationKey, }; -use zokrates_field::BellmanFieldExtensions; +use zokrates_field::BellmanPlonkFieldExtensions; use zokrates_field::Field; use zokrates_proof_systems::{Backend, Proof, SetupKeypair, UniversalBackend}; @@ -19,7 +19,7 @@ use zokrates_ast::ir::{ProgIterator, Statement, Witness}; use zokrates_proof_systems::plonk::{Plonk, ProofPoints, VerificationKey}; use zokrates_proof_systems::Scheme; -impl UniversalBackend for Bellman { +impl UniversalBackend for Bellman { fn universal_setup(size: u32) -> Vec { let crs: Crs = Crs::::dummy_crs(2usize.pow(size) as usize); @@ -69,7 +69,7 @@ impl UniversalBackend for Bellman { } } -impl Backend for Bellman { +impl Backend for Bellman { fn generate_proof>>( program: ProgIterator, witness: Witness, @@ -94,6 +94,9 @@ impl Backend for Bellman { None, &Crs::::dummy_crs(2usize.pow(10)), None, + // The multithreaded bellman_ce implementation does not work properly with any number of CPUs, + // so we hard-code 4 threads here... + Some(4), ) .unwrap(); @@ -131,7 +134,7 @@ impl Backend for Bellman { } } -fn deserialize_vk( +fn deserialize_vk( vk: >::VerificationKey, ) -> BellmanVerificationKey { BellmanVerificationKey { @@ -169,7 +172,7 @@ fn deserialize_vk( } } -fn serialize_vk( +fn serialize_vk( vk: BellmanVerificationKey, ) -> >::VerificationKey { let domain = bellman::plonk::domains::Domain::< @@ -201,11 +204,11 @@ fn serialize_vk( .try_into() .map_err(|_| ()) .unwrap(), - omega: omega, + omega, } } -fn deserialize_proof( +fn deserialize_proof( proof: Proof, ) -> BellmanProof { let inputs = proof.inputs; @@ -252,7 +255,7 @@ fn deserialize_proof( } } -fn serialize_proof( +fn serialize_proof( proof: BellmanProof, ) -> Proof { let public_inputs = proof.input_values.iter().map(parse_fr::).collect(); @@ -318,8 +321,8 @@ mod tests { println!("{}", &program); // generate a dummy universal setup of size 2**10 - let crs: Crs<::BellmanEngine, CrsForMonomialForm> = - Crs::<::BellmanEngine, CrsForMonomialForm>::dummy_crs(2usize.pow(10) as usize); + let crs: Crs<::BellmanEngine, CrsForMonomialForm> = + Crs::<::BellmanEngine, CrsForMonomialForm>::dummy_crs(2usize.pow(10) as usize); // transpile let hints = transpile(Computation::without_witness(program.clone())).unwrap(); @@ -348,7 +351,7 @@ mod tests { // generate a proof with no setup precomputations and no init params for the transcript, using Blake2s let proof: BellmanProof< - ::BellmanEngine, + ::BellmanEngine, PlonkCsWidth4WithNextStepParams, > = prove_by_steps::<_, _, Blake2sTranscript<_>>( computation, @@ -357,6 +360,9 @@ mod tests { None, &crs, None, + // The multithreaded bellman_ce implementation does not work properly with any number of CPUs, + // so we hard-code 4 threads here... + Some(4), ) .unwrap(); diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index 81e9a7472..2da8b226a 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [features] default = ["bellman", "ark"] -bellman = ["zokrates_bellman", "zokrates_core/bellman", "zokrates_common/bellman"] +bellman = ["zokrates_bellman", "zokrates_bellman_plonk", "zokrates_core/bellman", "zokrates_common/bellman"] ark = ["zokrates_ark", "zokrates_core/ark", "zokrates_common/ark"] [dependencies] @@ -41,6 +41,7 @@ sha2 = "0.10.0" zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false } zokrates_ark = { version = "0.1", path = "../zokrates_ark", default-features = false, optional = true } zokrates_bellman = { version = "0.1", path = "../zokrates_bellman", default-features = false, optional = true } +zokrates_bellman_plonk = { version = "0.1", path = "../zokrates_bellman_plonk", default-features = false, optional = true } [dev-dependencies] glob = "0.2.11" diff --git a/zokrates_cli/src/ops/generate_proof.rs b/zokrates_cli/src/ops/generate_proof.rs index a3685b575..cc30c5369 100644 --- a/zokrates_cli/src/ops/generate_proof.rs +++ b/zokrates_cli/src/ops/generate_proof.rs @@ -9,6 +9,8 @@ use zokrates_ark::Ark; use zokrates_ast::ir::{self, ProgEnum}; #[cfg(feature = "bellman")] use zokrates_bellman::Bellman; +#[cfg(feature = "bellman")] +use zokrates_bellman_plonk::Bellman as BellmanPlonk; use zokrates_common::constants; use zokrates_common::helpers::*; use zokrates_field::Field; @@ -108,9 +110,11 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { }, #[cfg(feature = "bellman")] Parameters(BackendParameter::Bellman, _, SchemeParameter::PLONK) => match prog { - ProgEnum::Bn128Program(p) => cli_generate_proof::<_, _, Plonk, Bellman>(p, sub_matches), + ProgEnum::Bn128Program(p) => { + cli_generate_proof::<_, _, Plonk, BellmanPlonk>(p, sub_matches) + } ProgEnum::Bls12_381Program(p) => { - cli_generate_proof::<_, _, Plonk, Bellman>(p, sub_matches) + cli_generate_proof::<_, _, Plonk, BellmanPlonk>(p, sub_matches) } _ => unreachable!(), }, diff --git a/zokrates_cli/src/ops/mpc/beacon.rs b/zokrates_cli/src/ops/mpc/beacon.rs index 5458b8753..b5af669e7 100644 --- a/zokrates_cli/src/ops/mpc/beacon.rs +++ b/zokrates_cli/src/ops/mpc/beacon.rs @@ -3,9 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_field::{BellmanFieldExtensions, Field}; -use zokrates_proof_systems::{MpcBackend, MpcScheme}; +use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("beacon") @@ -60,8 +61,8 @@ pub fn subcommand() -> App<'static, 'static> { pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { match sub_matches.value_of("curve").unwrap() { - // BN128 => cli_mpc_beacon::(sub_matches), - // BLS12_381 => cli_mpc_beacon::(sub_matches), + BN128 => cli_mpc_beacon::(sub_matches), + BLS12_381 => cli_mpc_beacon::(sub_matches), _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/mpc/contribute.rs b/zokrates_cli/src/ops/mpc/contribute.rs index 9ffd85d95..3490f381b 100644 --- a/zokrates_cli/src/ops/mpc/contribute.rs +++ b/zokrates_cli/src/ops/mpc/contribute.rs @@ -3,9 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_field::{BellmanFieldExtensions, Field}; -use zokrates_proof_systems::{MpcBackend, MpcScheme}; +use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("contribute") @@ -52,8 +53,8 @@ pub fn subcommand() -> App<'static, 'static> { pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { match sub_matches.value_of("curve").unwrap() { - // BN128 => cli_mpc_contribute::(sub_matches), - // BLS12_381 => cli_mpc_contribute::(sub_matches), + BN128 => cli_mpc_contribute::(sub_matches), + BLS12_381 => cli_mpc_contribute::(sub_matches), _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/mpc/export.rs b/zokrates_cli/src/ops/mpc/export.rs index 2f223ba1d..cf640fa1c 100644 --- a/zokrates_cli/src/ops/mpc/export.rs +++ b/zokrates_cli/src/ops/mpc/export.rs @@ -3,9 +3,10 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::fs::File; use std::io::{BufReader, Write}; use std::path::Path; +use zokrates_bellman::Bellman; use zokrates_common::constants::{BLS12_381, BN128}; -use zokrates_field::{BellmanFieldExtensions, Field}; -use zokrates_proof_systems::{MpcBackend, MpcScheme, TaggedVerificationKey}; +use zokrates_field::{BellmanFieldExtensions, Bls12_381Field, Bn128Field, Field}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, TaggedVerificationKey, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("export") @@ -54,8 +55,8 @@ pub fn subcommand() -> App<'static, 'static> { pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { match sub_matches.value_of("curve").unwrap() { - // BN128 => cli_mpc_export::(sub_matches), - // BLS12_381 => cli_mpc_export::(sub_matches), + BN128 => cli_mpc_export::(sub_matches), + BLS12_381 => cli_mpc_export::(sub_matches), _ => unreachable!(), } } diff --git a/zokrates_cli/src/ops/mpc/init.rs b/zokrates_cli/src/ops/mpc/init.rs index dcd83fe9f..71136366c 100644 --- a/zokrates_cli/src/ops/mpc/init.rs +++ b/zokrates_cli/src/ops/mpc/init.rs @@ -4,8 +4,9 @@ use std::fs::File; use std::io::{BufReader, BufWriter}; use std::path::Path; use zokrates_ast::ir::{self, ProgEnum}; +use zokrates_bellman::Bellman; use zokrates_field::{BellmanFieldExtensions, Field}; -use zokrates_proof_systems::{MpcBackend, MpcScheme}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("init") @@ -50,8 +51,8 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { let mut reader = BufReader::new(file); match ProgEnum::deserialize(&mut reader)? { - // ProgEnum::Bn128Program(p) => cli_mpc_init::<_, _, G16, Bellman>(p, sub_matches), - // ProgEnum::Bls12_381Program(p) => cli_mpc_init::<_, _, G16, Bellman>(p, sub_matches), + ProgEnum::Bn128Program(p) => cli_mpc_init::<_, _, G16, Bellman>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => cli_mpc_init::<_, _, G16, Bellman>(p, sub_matches), _ => Err("Current protocol only supports bn128/bls12_381 programs".into()), } } diff --git a/zokrates_cli/src/ops/mpc/verify.rs b/zokrates_cli/src/ops/mpc/verify.rs index 84d1a5172..6beca03db 100644 --- a/zokrates_cli/src/ops/mpc/verify.rs +++ b/zokrates_cli/src/ops/mpc/verify.rs @@ -4,8 +4,9 @@ use std::fs::File; use std::io::BufReader; use std::path::Path; use zokrates_ast::ir::{self, ProgEnum}; +use zokrates_bellman::Bellman; use zokrates_field::{BellmanFieldExtensions, Field}; -use zokrates_proof_systems::{MpcBackend, MpcScheme}; +use zokrates_proof_systems::{MpcBackend, MpcScheme, G16}; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("verify") @@ -50,8 +51,8 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { let mut reader = BufReader::new(file); match ProgEnum::deserialize(&mut reader)? { - // ProgEnum::Bn128Program(p) => cli_mpc_verify::<_, _, G16, Bellman>(p, sub_matches), - // ProgEnum::Bls12_381Program(p) => cli_mpc_verify::<_, _, G16, Bellman>(p, sub_matches), + ProgEnum::Bn128Program(p) => cli_mpc_verify::<_, _, G16, Bellman>(p, sub_matches), + ProgEnum::Bls12_381Program(p) => cli_mpc_verify::<_, _, G16, Bellman>(p, sub_matches), _ => Err("Current protocol only supports bn128/bls12_381 programs".into()), } } diff --git a/zokrates_cli/src/ops/setup.rs b/zokrates_cli/src/ops/setup.rs index c4f80415e..f5cfa7346 100644 --- a/zokrates_cli/src/ops/setup.rs +++ b/zokrates_cli/src/ops/setup.rs @@ -9,6 +9,8 @@ use zokrates_ark::Ark; use zokrates_ast::ir::{self, ProgEnum}; #[cfg(feature = "bellman")] use zokrates_bellman::Bellman; +#[cfg(feature = "bellman")] +use zokrates_bellman_plonk::Bellman as BellmanPlonk; use zokrates_common::constants; use zokrates_common::helpers::*; use zokrates_field::Field; @@ -179,10 +181,10 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { match prog { ProgEnum::Bn128Program(p) => { - cli_setup_universal::<_, _, Plonk, Bellman>(p, setup, sub_matches) + cli_setup_universal::<_, _, Plonk, BellmanPlonk>(p, setup, sub_matches) } ProgEnum::Bls12_381Program(p) => { - cli_setup_universal::<_, _, Plonk, Bellman>(p, setup, sub_matches) + cli_setup_universal::<_, _, Plonk, BellmanPlonk>(p, setup, sub_matches) } _ => unreachable!(), } diff --git a/zokrates_cli/src/ops/universal_setup.rs b/zokrates_cli/src/ops/universal_setup.rs index 3713e8ee8..d43ea5747 100644 --- a/zokrates_cli/src/ops/universal_setup.rs +++ b/zokrates_cli/src/ops/universal_setup.rs @@ -7,7 +7,7 @@ use std::path::Path; #[cfg(feature = "ark")] use zokrates_ark::Ark; #[cfg(feature = "bellman")] -use zokrates_bellman::Bellman; +use zokrates_bellman_plonk::Bellman as BellmanPlonk; use zokrates_common::constants; use zokrates_common::helpers::*; use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; @@ -78,14 +78,14 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { match parameters { #[cfg(feature = "bellman")] Parameters(BackendParameter::Bellman, CurveParameter::Bn128, SchemeParameter::PLONK) => { - cli_universal_setup::(sub_matches) + cli_universal_setup::(sub_matches) } #[cfg(feature = "bellman")] Parameters( BackendParameter::Bellman, CurveParameter::Bls12_381, SchemeParameter::PLONK, - ) => cli_universal_setup::(sub_matches), + ) => cli_universal_setup::(sub_matches), #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => { cli_universal_setup::(sub_matches) diff --git a/zokrates_cli/src/ops/verify.rs b/zokrates_cli/src/ops/verify.rs index 2b5fe631c..78ea52b13 100644 --- a/zokrates_cli/src/ops/verify.rs +++ b/zokrates_cli/src/ops/verify.rs @@ -8,6 +8,8 @@ use std::path::Path; use zokrates_ark::Ark; #[cfg(feature = "bellman")] use zokrates_bellman::Bellman; +#[cfg(feature = "bellman")] +use zokrates_bellman_plonk::Bellman as BellmanPlonk; use zokrates_common::constants; use zokrates_common::helpers::*; use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; @@ -122,14 +124,14 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { } #[cfg(feature = "bellman")] Parameters(BackendParameter::Bellman, CurveParameter::Bn128, SchemeParameter::PLONK) => { - cli_verify::(vk, proof) + cli_verify::(vk, proof) } #[cfg(feature = "bellman")] Parameters( BackendParameter::Bellman, CurveParameter::Bls12_381, SchemeParameter::PLONK, - ) => cli_verify::(vk, proof), + ) => cli_verify::(vk, proof), #[cfg(feature = "ark")] Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::G16) => { cli_verify::(vk, proof) diff --git a/zokrates_field/Cargo.toml b/zokrates_field/Cargo.toml index 14ce21586..3fc0a91b7 100644 --- a/zokrates_field/Cargo.toml +++ b/zokrates_field/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [features] default = ["bellman"] -bellman = ["bellman_ce"] +bellman = ["bellman_ce", "bellman_ce_plonk"] [dependencies] serde = "1.0" @@ -19,7 +19,8 @@ num-traits = { version = "0.2", default-features = false } num-integer = { version = "0.1", default-features = false } # bellman -bellman_ce = { git = "https://github.com/matter-labs/bellman", version = "^0.3", default-features = false, optional = true } +bellman_ce = { version = "^0.3", default-features = false, optional = true } +bellman_ce_plonk = { package = "bellman_ce", git = "https://github.com/georgwiese/bellman", rev="dbed83d1971c29e8fdb07d341e8593fef8ba5eab", default-features = false, features = ["plonk", "multicore"], optional = true } # ark ark-ff = { version = "^0.3.0", default-features = false } diff --git a/zokrates_field/src/bls12_381.rs b/zokrates_field/src/bls12_381.rs index 403d0b947..7867689ee 100644 --- a/zokrates_field/src/bls12_381.rs +++ b/zokrates_field/src/bls12_381.rs @@ -7,6 +7,16 @@ ark_extensions!(Bls12_381); #[cfg(feature = "bellman")] use bellman_ce::pairing::bls12_381::{Bls12, Fq2}; +#[cfg(feature = "bellman")] +use bellman_ce_plonk::pairing::bls12_381::{Bls12 as Bls12Plonk, Fq2 as Fq2Plonk}; + use crate::G2Type; #[cfg(feature = "bellman")] -bellman_extensions!(Bls12, Fq2); +bellman_extensions!(bellman_ce, BellmanFieldExtensions, Bls12, Fq2); +#[cfg(feature = "bellman")] +bellman_extensions!( + bellman_ce_plonk, + BellmanPlonkFieldExtensions, + Bls12Plonk, + Fq2Plonk +); diff --git a/zokrates_field/src/bn128.rs b/zokrates_field/src/bn128.rs index 4b6c9cbb3..946d09165 100644 --- a/zokrates_field/src/bn128.rs +++ b/zokrates_field/src/bn128.rs @@ -7,9 +7,19 @@ ark_extensions!(Bn254); #[cfg(feature = "bellman")] use bellman_ce::pairing::bn256::{Bn256, Fq2}; +#[cfg(feature = "bellman")] +use bellman_ce_plonk::pairing::bn256::{Bn256 as Bn256Plonk, Fq2 as Fq2Plonk}; + use crate::G2Type; #[cfg(feature = "bellman")] -bellman_extensions!(Bn256, Fq2); +bellman_extensions!(bellman_ce, BellmanFieldExtensions, Bn256, Fq2); +#[cfg(feature = "bellman")] +bellman_extensions!( + bellman_ce_plonk, + BellmanPlonkFieldExtensions, + Bn256Plonk, + Fq2Plonk +); #[cfg(test)] mod tests { @@ -306,7 +316,12 @@ mod tests { let rng = &mut thread_rng(); for _ in 0..1000 { let a: Fr = rng.gen(); - assert_eq!(FieldPrime::from_bellman(a).into_bellman(), a); + assert_eq!( + BellmanFieldExtensions::into_bellman( + ::from_bellman(a) + ), + a + ); } } @@ -317,8 +332,13 @@ mod tests { for _ in 0..1000 { let a: Fr = rng.gen(); // now test idempotence - let a = FieldPrime::from_bellman(a); - assert_eq!(FieldPrime::from_bellman(a.clone().into_bellman()), a); + let a = ::from_bellman(a); + assert_eq!( + ::from_bellman( + BellmanFieldExtensions::into_bellman(a.clone()) + ), + a + ); } } @@ -326,21 +346,24 @@ mod tests { fn one() { let a = FieldPrime::from(1); - assert_eq!(a.into_bellman(), Fr::one()); + assert_eq!(BellmanFieldExtensions::into_bellman(a), Fr::one()); } #[test] fn zero() { let a = FieldPrime::from(0); - assert_eq!(a.into_bellman(), Fr::zero()); + assert_eq!(BellmanFieldExtensions::into_bellman(a), Fr::zero()); } #[test] fn minus_one() { let mut a: Fr = Fr::one(); a.negate(); - assert_eq!(FieldPrime::from_bellman(a), FieldPrime::from(-1)); + assert_eq!( + ::from_bellman(a), + FieldPrime::from(-1) + ); } #[test] @@ -350,13 +373,13 @@ mod tests { let mut a: Fr = rng.gen(); let b: Fr = rng.gen(); - let aa = FieldPrime::from_bellman(a); - let bb = FieldPrime::from_bellman(b); + let aa = ::from_bellman(a); + let bb = ::from_bellman(b); let cc = aa + bb; a.add_assign(&b); - assert_eq!(FieldPrime::from_bellman(a), cc); + assert_eq!(::from_bellman(a), cc); } } } diff --git a/zokrates_field/src/lib.rs b/zokrates_field/src/lib.rs index dc1e6b907..7c45c5b58 100644 --- a/zokrates_field/src/lib.rs +++ b/zokrates_field/src/lib.rs @@ -8,6 +8,7 @@ extern crate num_bigint; #[cfg(feature = "bellman")] use bellman_ce::pairing::{ff::ScalarEngine, Engine}; +use bellman_ce_plonk::pairing::{ff::ScalarEngine as ScalarEnginePlonk, Engine as EnginePlonk}; use num_bigint::BigUint; use num_traits::{CheckedDiv, One, Zero}; @@ -33,6 +34,16 @@ pub trait BellmanFieldExtensions { fn new_fq2(c0: &str, c1: &str) -> ::Fqe; } +#[cfg(feature = "bellman")] +pub trait BellmanPlonkFieldExtensions { + /// An associated type to be able to operate with Bellman ff traits + type BellmanEngine: EnginePlonk; + + fn from_bellman(e: ::Fr) -> Self; + fn into_bellman(self) -> ::Fr; + fn new_fq2(c0: &str, c1: &str) -> ::Fqe; +} + pub trait ArkFieldExtensions { /// An associated type to be able to operate with ark ff traits type ArkEngine: ark_ec::PairingEngine; @@ -576,33 +587,32 @@ mod prime_field { #[cfg(feature = "bellman")] macro_rules! bellman_extensions { - ($bellman_type:ty, $fq2_type:ident) => { - use crate::BellmanFieldExtensions; - use bellman_ce::pairing::ff::ScalarEngine; + ($bellman_crate:ident, $trait:ident, $bellman_type:ty, $fq2_type:ident) => { + use crate::$trait; - impl BellmanFieldExtensions for FieldPrime { + impl $trait for FieldPrime { type BellmanEngine = $bellman_type; - fn from_bellman(e: ::Fr) -> Self { - use bellman_ce::pairing::ff::{PrimeField, PrimeFieldRepr}; + fn from_bellman(e: ::Fr) -> Self { + use $bellman_crate::pairing::ff::{PrimeField, PrimeFieldRepr}; let mut res: Vec = vec![]; e.into_repr().write_le(&mut res).unwrap(); Self::from_byte_vector(res) } - fn into_bellman(self) -> ::Fr { - use bellman_ce::pairing::ff::PrimeField; + fn into_bellman(self) -> ::Fr { + use $bellman_crate::pairing::ff::PrimeField; let s = self.to_dec_string(); - ::Fr::from_str(&s).unwrap() + ::Fr::from_str(&s).unwrap() } fn new_fq2( c0: &str, c1: &str, - ) -> ::Fqe { + ) -> ::Fqe { $fq2_type { - c0: bellman_ce::pairing::from_hex(c0).unwrap(), - c1: bellman_ce::pairing::from_hex(c1).unwrap(), + c0: $bellman_crate::pairing::from_hex(c0).unwrap(), + c1: $bellman_crate::pairing::from_hex(c1).unwrap(), } } } diff --git a/zokrates_proof_systems/src/lib.rs b/zokrates_proof_systems/src/lib.rs index d5b002b20..2af0aa4ad 100644 --- a/zokrates_proof_systems/src/lib.rs +++ b/zokrates_proof_systems/src/lib.rs @@ -45,16 +45,16 @@ impl> Proof { pub type Fr = String; pub type Fq = String; -#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq)] pub struct Fq2(pub String, pub String); impl fmt::Display for Fq2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({}, {})", self.0, self.1) + write!(f, "[{}, {}]", self.0, self.1) } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct GAffine { pub x: F, pub y: F, @@ -84,14 +84,14 @@ impl fmt::Display for GAffine { if self.is_infinity { write!(f, "Infinity") } else { - write!(f, "({}, {})", self.x, self.y) + write!(f, "[{}, {}]", self.x, self.y) } } } pub type G1Affine = GAffine; -#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Eq)] #[serde(untagged)] pub enum G2Affine { Fq2(G2AffineFq2), diff --git a/zokrates_proof_systems/src/scheme/gm17.rs b/zokrates_proof_systems/src/scheme/gm17.rs index 3c1538689..5720be63e 100644 --- a/zokrates_proof_systems/src/scheme/gm17.rs +++ b/zokrates_proof_systems/src/scheme/gm17.rs @@ -6,17 +6,17 @@ use serde::{Deserialize, Serialize}; use zokrates_field::Field; #[allow(clippy::upper_case_acronyms)] -#[derive(Serialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Debug, Clone, PartialEq, Eq)] pub struct GM17; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct ProofPoints { pub a: G1, pub b: G2, pub c: G1, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct VerificationKey { pub h: G2, pub g_alpha: G1, @@ -50,24 +50,35 @@ impl SolidityCompatibleScheme for GM17 { let input_loop = Regex::new(r#"(<%input_loop%>)"#).unwrap(); let input_argument = Regex::new(r#"(<%input_argument%>)"#).unwrap(); + let trim = |s: String| String::from(&s[1..s.len() - 1]); + template_text = vk_regex - .replace(template_text.as_str(), vk.h.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.h.to_string()).as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.g_alpha.to_string().as_str()) + .replace( + template_text.as_str(), + trim(vk.g_alpha.to_string()).as_str(), + ) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.h_beta.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.h_beta.to_string()).as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.g_gamma.to_string().as_str()) + .replace( + template_text.as_str(), + trim(vk.g_gamma.to_string()).as_str(), + ) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.h_gamma.to_string().as_str()) + .replace( + template_text.as_str(), + trim(vk.h_gamma.to_string()).as_str(), + ) .into_owned(); let query_count: usize = vk.query.len(); @@ -113,7 +124,7 @@ impl SolidityCompatibleScheme for GM17 { format!( "vk.query[{}] = Pairing.G1Point({});", i, - g1.to_string().as_str() + trim(g1.to_string()).as_str() ) .as_str(), ); diff --git a/zokrates_proof_systems/src/scheme/groth16.rs b/zokrates_proof_systems/src/scheme/groth16.rs index 548a49818..84377f1ba 100644 --- a/zokrates_proof_systems/src/scheme/groth16.rs +++ b/zokrates_proof_systems/src/scheme/groth16.rs @@ -5,17 +5,17 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use zokrates_field::Field; -#[derive(Serialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Debug, Clone, PartialEq, Eq)] pub struct G16; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct ProofPoints { pub a: G1, pub b: G2, pub c: G1, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct VerificationKey { pub alpha: G1, pub beta: G2, @@ -48,20 +48,22 @@ impl SolidityCompatibleScheme for G16 { let input_loop = Regex::new(r#"(<%input_loop%>)"#).unwrap(); let input_argument = Regex::new(r#"(<%input_argument%>)"#).unwrap(); + let trim = |s: String| String::from(&s[1..s.len() - 1]); + template_text = vk_regex - .replace(template_text.as_str(), vk.alpha.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.alpha.to_string()).as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.beta.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.beta.to_string()).as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.gamma.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.gamma.to_string()).as_str()) .into_owned(); template_text = vk_regex - .replace(template_text.as_str(), vk.delta.to_string().as_str()) + .replace(template_text.as_str(), trim(vk.delta.to_string()).as_str()) .into_owned(); let gamma_abc_count: usize = vk.gamma_abc.len(); @@ -110,7 +112,7 @@ impl SolidityCompatibleScheme for G16 { format!( "vk.gamma_abc[{}] = Pairing.G1Point({});", i, - g1.to_string().as_str() + trim(g1.to_string()).as_str() ) .as_str(), ); diff --git a/zokrates_proof_systems/src/scheme/marlin.rs b/zokrates_proof_systems/src/scheme/marlin.rs index 25c071010..0054014f2 100644 --- a/zokrates_proof_systems/src/scheme/marlin.rs +++ b/zokrates_proof_systems/src/scheme/marlin.rs @@ -7,7 +7,7 @@ use zokrates_field::Field; #[derive(Serialize, Debug, Clone)] pub struct Marlin; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct ProofPoints { pub commitments: Vec)>>, pub evaluations: Vec, @@ -46,7 +46,7 @@ impl From> for SolidityProof { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct KZGVerifierKey { /// The generator of G1. pub g: G1, @@ -58,7 +58,7 @@ pub struct KZGVerifierKey { pub beta_h: G2, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct VerificationKey { // Useful values to precompute for solidity contract pub fs_seed: Vec, @@ -96,6 +96,8 @@ impl SolidityCompatibleScheme for Marlin { let (template, solidity_pairing_lib) = (String::from(CONTRACT_TEMPLATE), solidity_pairing_lib(false)); + let trim = |s: String| String::from(&s[1..s.len() - 1]); + // Replace public parameters in template let src = template .replace( @@ -109,7 +111,7 @@ impl SolidityCompatibleScheme for Marlin { populate_index_comms, "vk.index_comms[{}] = Pairing.G1Point({});", i, - &g.to_string() + &trim(g.to_string()) ) .unwrap(); if i < vk.index_comms.len() - 1 { @@ -118,10 +120,10 @@ impl SolidityCompatibleScheme for Marlin { } populate_index_comms }) - .replace("<%vk_kzg_g%>", &vk.vk.g.to_string()) - .replace("<%vk_kzg_gamma_g%>", &vk.vk.gamma_g.to_string()) - .replace("<%vk_kzg_h%>", &vk.vk.h.to_string()) - .replace("<%vk_kzg_beta_h%>", &vk.vk.beta_h.to_string()) + .replace("<%vk_kzg_g%>", &trim(vk.vk.g.to_string())) + .replace("<%vk_kzg_gamma_g%>", &trim(vk.vk.gamma_g.to_string())) + .replace("<%vk_kzg_h%>", &trim(vk.vk.h.to_string())) + .replace("<%vk_kzg_beta_h%>", &trim(vk.vk.beta_h.to_string())) .replace( "<%vk_degree_bounds_length%>", &vk.degree_bounds_and_shift_powers @@ -136,14 +138,16 @@ impl SolidityCompatibleScheme for Marlin { } else { vk.num_constraints.next_power_of_two() }; - vk.degree_bounds_and_shift_powers - .as_ref() - .unwrap() - .iter() - .find(|(b, _)| *b == h_domain_size - 2) - .unwrap() - .1 - .to_string() + trim( + vk.degree_bounds_and_shift_powers + .as_ref() + .unwrap() + .iter() + .find(|(b, _)| *b == h_domain_size - 2) + .unwrap() + .1 + .to_string(), + ) }) .replace("<%vk_g2_shift%>", &{ let k_domain_size = if vk.num_non_zero.is_power_of_two() { @@ -151,14 +155,16 @@ impl SolidityCompatibleScheme for Marlin { } else { vk.num_non_zero.next_power_of_two() }; - vk.degree_bounds_and_shift_powers - .as_ref() - .unwrap() - .iter() - .find(|(b, _)| *b == k_domain_size - 2) - .unwrap() - .1 - .to_string() + trim( + vk.degree_bounds_and_shift_powers + .as_ref() + .unwrap() + .iter() + .find(|(b, _)| *b == k_domain_size - 2) + .unwrap() + .1 + .to_string(), + ) }) .replace("<%fs_init_seed_len%>", &(vk.fs_seed.len() / 32).to_string()) .replace("<%fs_init_seed_overflow_len%>", &{ diff --git a/zokrates_proof_systems/src/scheme/plonk.rs b/zokrates_proof_systems/src/scheme/plonk.rs index 52d19ad0c..8230e2171 100644 --- a/zokrates_proof_systems/src/scheme/plonk.rs +++ b/zokrates_proof_systems/src/scheme/plonk.rs @@ -9,10 +9,10 @@ use zokrates_field::{Bn128Field, Field}; use crate::solidity_renderers::plonk_solidity_renderer::render_verification_key; -#[derive(Serialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Debug, Clone, PartialEq, Eq)] pub struct Plonk; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct VerificationKey { pub n: u32, pub num_inputs: u32, @@ -26,7 +26,7 @@ pub struct VerificationKey { pub omega: Fr, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct ProofPoints { pub num_inputs: u32, pub n: u32, @@ -66,7 +66,7 @@ impl ToToken for Plonk { proof .wire_commitments .iter() - .map(|x| encode_g1_element(x)) + .map(encode_g1_element) .collect(), ); @@ -76,7 +76,7 @@ impl ToToken for Plonk { proof .quotient_poly_commitments .iter() - .map(|x| encode_g1_element(x)) + .map(encode_g1_element) .collect(), ); @@ -84,7 +84,7 @@ impl ToToken for Plonk { proof .wire_values_at_z .iter() - .map(|x| encode_fr_element_as_tuple(x)) + .map(encode_fr_element_as_tuple) .collect(), ); @@ -92,7 +92,7 @@ impl ToToken for Plonk { proof .wire_values_at_z_omega .iter() - .map(|x| encode_fr_element_as_tuple(x)) + .map(encode_fr_element_as_tuple) .collect(), ); @@ -107,7 +107,7 @@ impl ToToken for Plonk { proof .permutation_polynomials_at_z .iter() - .map(|x| encode_fr_element_as_tuple(x)) + .map(encode_fr_element_as_tuple) .collect(), ); diff --git a/zokrates_proof_systems/src/solidity_renderers/plonk_solidity_renderer.rs b/zokrates_proof_systems/src/solidity_renderers/plonk_solidity_renderer.rs index 1c77c0f56..d3894510b 100644 --- a/zokrates_proof_systems/src/solidity_renderers/plonk_solidity_renderer.rs +++ b/zokrates_proof_systems/src/solidity_renderers/plonk_solidity_renderer.rs @@ -21,34 +21,34 @@ pub fn render_verification_key(vk: &>::Verification map.insert("omega".to_owned(), to_json(vk.omega.clone())); for (i, c) in vk.selector_commitments.iter().enumerate() { - let rendered = render_g1_affine_to_hex(&c); + let rendered = render_g1_affine_to_hex(c); - for j in 0..2 { + for (j, rendered_item) in rendered.iter().enumerate() { map.insert( format!("selector_commitment_{}_{}", i, j), - to_json(&rendered[j]), + to_json(rendered_item), ); } } for (i, c) in vk.next_step_selector_commitments.iter().enumerate() { - let rendered = render_g1_affine_to_hex(&c); + let rendered = render_g1_affine_to_hex(c); - for j in 0..2 { + for (j, rendered_item) in rendered.iter().enumerate() { map.insert( format!("next_step_selector_commitment_{}_{}", i, j), - to_json(&rendered[j]), + to_json(rendered_item), ); } } for (i, c) in vk.permutation_commitments.iter().enumerate() { - let rendered = render_g1_affine_to_hex(&c); + let rendered = render_g1_affine_to_hex(c); - for j in 0..2 { + for (j, rendered_item) in rendered.iter().enumerate() { map.insert( format!("permutation_commitment_{}_{}", i, j), - to_json(&rendered[j]), + to_json(rendered_item), ); } }