From 0be493fdd175dc72a49acdaa3051bc59b3947ce0 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 8 Apr 2019 14:56:07 +0200 Subject: [PATCH] fix following review: extract witness with write read, rename scheme to proving scheme, typos --- Cargo.lock | 2 +- zokrates_book/src/reference/schemes.md | 20 +-- zokrates_cli/Cargo.toml | 1 - zokrates_cli/src/bin.rs | 59 +++---- zokrates_cli/tests/integration.rs | 6 +- zokrates_core/Cargo.toml | 1 + zokrates_core/src/flat_absy/flat_variable.rs | 27 +-- zokrates_core/src/ir/interpreter.rs | 94 +--------- zokrates_core/src/ir/mod.rs | 5 +- zokrates_core/src/ir/witness.rs | 167 ++++++++++++++++++ zokrates_core/src/lib.rs | 1 - zokrates_core/src/libsnark.rs | 4 +- .../src/parser/tokenize/tokenizer.rs | 2 +- zokrates_core/src/proof_system/bn128/g16.rs | 74 +++++++- .../src/proof_system/bn128/utils/bellman.rs | 62 +------ zokrates_core/tests/utils/mod.rs | 6 +- zokrates_field/src/field.rs | 18 +- zokrates_stdlib/tests/test_template | 2 +- zokrates_stdlib/tests/utils/mod.rs | 4 +- 19 files changed, 313 insertions(+), 242 deletions(-) create mode 100644 zokrates_core/src/ir/witness.rs diff --git a/Cargo.lock b/Cargo.lock index 4b9c613b..c402e450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1149,7 +1149,6 @@ dependencies = [ "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1169,6 +1168,7 @@ dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.5.0 (git+https://github.com/matterinc/ff?tag=0.5)", "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/zokrates_book/src/reference/schemes.md b/zokrates_book/src/reference/schemes.md index eba9bc24..74e0b6e9 100644 --- a/zokrates_book/src/reference/schemes.md +++ b/zokrates_book/src/reference/schemes.md @@ -1,25 +1,25 @@ -# Schemes +# Provin schemes -ZoKrates supports different proof systems we refer to as schemes. All of the available schemes rely on the ALT_BN128 curve, which means that they're all compatible with Ethereum. +ZoKrates supports different proving schemes. All of the available schemes rely on the ALT_BN128 curve, which means that they're all compatible with Ethereum. We identify the schemes by the reference to the paper that introduced them. Currently the options available are: -| Name | Paper | CLI flag | -| ---- | ----- | -------- | -| PGHR13 | [Here](https://eprint.iacr.org/2013/279) | `--scheme pghr13` | -| G16 | [Here](https://eprint.iacr.org/2016/260) | `--scheme gm17` | -| GM17 | [Here](https://eprint.iacr.org/2017/540) | `--scheme gm17` | +| Name | Paper | CLI flag | Requires libsnark | +| ---- | ----- | -------- | --------- | +| PGHR13 | [Here](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | Yes | +| G16 | [Here](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | No | +| GM17 | [Here](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | Yes | -The default scheme is G16. +The default proving scheme is G16. When not using the default, the CLI flag has to be provided for the following commands: - `setup` - `export-verifier` - `generate-proof` -## Groth16 malleability +## G16 malleability -When using Groth16, developers should pay attention to the fact that an attacker seeing a valid proof can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice is *not* enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include: +When using G16, developers should pay attention to the fact that an attacker seeing a valid proof can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may *not* be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include: - signed proofs - nullifiers - usage of an ethereum address as a public input to the program diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index 58caabdc..cb859477 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -17,7 +17,6 @@ zokrates_field = { version = "0.3", path = "../zokrates_field" } zokrates_core = { version = "0.3", path = "../zokrates_core" } zokrates_fs_resolver = { version = "0.4", path = "../zokrates_fs_resolver"} serde_json = "1.0" -csv = "1" [dev-dependencies] glob = "0.2.11" diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 90875af7..57a19b35 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -31,7 +31,7 @@ fn cli() -> Result<(), String> { const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol"; const WITNESS_DEFAULT_PATH: &str = "witness"; const JSON_PROOF_PATH: &str = "proof.json"; - let default_scheme = env::var("ZOKRATES_BACKEND").unwrap_or(String::from("g16")); + let default_scheme = env::var("ZOKRATES_PROVING_SCHEME").unwrap_or(String::from("g16")); // cli specification using clap library let matches = App::new("ZoKrates") @@ -91,10 +91,10 @@ fn cli() -> Result<(), String> { .required(false) .default_value(VERIFICATION_KEY_DEFAULT_PATH) ) - .arg(Arg::with_name("scheme") + .arg(Arg::with_name("proving-scheme") .short("s") - .long("scheme") - .help("Backend to use in the setup. Available options are PGHR13 and GM17") + .long("proving-scheme") + .help("Proving scheme to use in the setup. Available options are G16 (default), PGHR13 and GM17") .value_name("FILE") .takes_value(true) .required(false) @@ -120,10 +120,10 @@ fn cli() -> Result<(), String> { .takes_value(true) .required(false) .default_value(VERIFICATION_CONTRACT_DEFAULT_PATH) - ).arg(Arg::with_name("scheme") + ).arg(Arg::with_name("proving-scheme") .short("s") - .long("scheme") - .help("Backend to use to export the verifier. Available options are PGHR13 and GM17") + .long("proving-scheme") + .help("Proving scheme to use to export the verifier. Available options are G16 (default), PGHR13 and GM17") .value_name("FILE") .takes_value(true) .required(false) @@ -191,10 +191,10 @@ fn cli() -> Result<(), String> { .takes_value(true) .required(false) .default_value(FLATTENED_CODE_DEFAULT_PATH) - ).arg(Arg::with_name("scheme") + ).arg(Arg::with_name("proving-scheme") .short("s") - .long("scheme") - .help("Backend to use to generate the proof. Available options are PGHR13 and GM17") + .long("proving-scheme") + .help("Proving scheme to use to generate the proof. Available options are G16 (default), PGHR13 and GM17") .value_name("FILE") .takes_value(true) .required(false) @@ -289,7 +289,7 @@ fn cli() -> Result<(), String> { let arguments: Vec<_> = match sub_matches.values_of("arguments") { // take inline arguments Some(p) => p - .map(|x| FieldPrime::try_from_str(x).map_err(|_| x.to_string())) + .map(|x| FieldPrime::try_from_dec_str(x).map_err(|_| x.to_string())) .collect(), // take stdin arguments None => { @@ -301,7 +301,9 @@ fn cli() -> Result<(), String> { input.retain(|x| x != '\n'); input .split(" ") - .map(|x| FieldPrime::try_from_str(x).map_err(|_| x.to_string())) + .map(|x| { + FieldPrime::try_from_dec_str(x).map_err(|_| x.to_string()) + }) .collect() } Err(_) => Err(String::from("???")), @@ -332,24 +334,12 @@ fn cli() -> Result<(), String> { let output_file = File::create(&output_path) .map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?; - // create a CSV writer - let mut wtr = csv::WriterBuilder::new() - .delimiter(b' ') - .flexible(true) - .has_headers(false) - .from_writer(output_file); - - // Write each line of the witness to the file - for line in witness.into_human_readable() { - wtr.serialize(line) - .map_err(|_| "Error writing witness to file".to_string())?; - } - - wtr.flush() - .map_err(|_| "Unable to flush buffer.".to_string())?; + witness + .write(output_file) + .map_err(|why| format!("could not save witness: {:?}", why))?; } ("setup", Some(sub_matches)) => { - let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?; + let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?; println!("Performing setup..."); @@ -372,7 +362,7 @@ fn cli() -> Result<(), String> { } ("export-verifier", Some(sub_matches)) => { { - let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?; + let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?; println!("Exporting verifier..."); @@ -398,7 +388,7 @@ fn cli() -> Result<(), String> { ("generate-proof", Some(sub_matches)) => { println!("Generating proof..."); - let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?; + let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?; // deserialize witness let witness_path = Path::new(sub_matches.value_of("witness").unwrap()); @@ -407,13 +397,8 @@ fn cli() -> Result<(), String> { Err(why) => panic!("couldn't open {}: {}", witness_path.display(), why), }; - let mut rdr = csv::ReaderBuilder::new() - .delimiter(b' ') - .flexible(true) - .has_headers(false) - .from_reader(witness_file); - - let witness = ir::Witness::from_human_readable(rdr.deserialize().map(|i| i.unwrap())); + let witness = ir::Witness::read(witness_file) + .map_err(|why| format!("could not load witness: {:?}", why))?; let pk_path = sub_matches.value_of("provingkey").unwrap(); let proof_path = sub_matches.value_of("proofpath").unwrap(); diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index a41a8317..f1d7c222 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -185,7 +185,7 @@ mod integration { proving_key_path.to_str().unwrap(), "-v", verification_key_path.to_str().unwrap(), - "--scheme", + "--proving-scheme", scheme, ]) .succeeds() @@ -199,7 +199,7 @@ mod integration { verification_key_path.to_str().unwrap(), "-o", verification_contract_path.to_str().unwrap(), - "--scheme", + "--proving-scheme", scheme, ]) .succeeds() @@ -231,7 +231,7 @@ mod integration { witness_path.to_str().unwrap(), "-p", proving_key_path.to_str().unwrap(), - "--scheme", + "--proving-scheme", scheme, ]) .succeeds() diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 10c03e3b..83f1ee11 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -33,6 +33,7 @@ rand = "0.4" wasmi = "0.4.2" parity-wasm = "0.35.3" rustc-hex = "1.0" +csv = "1" [dev-dependencies] glob = "0.2.11" diff --git a/zokrates_core/src/flat_absy/flat_variable.rs b/zokrates_core/src/flat_absy/flat_variable.rs index 4d9af49f..8a85998c 100644 --- a/zokrates_core/src/flat_absy/flat_variable.rs +++ b/zokrates_core/src/flat_absy/flat_variable.rs @@ -32,21 +32,28 @@ impl FlatVariable { (self.id as usize) - 1 } - pub fn from_human_readable(s: &str) -> Self { + pub fn try_from_human_readable(s: &str) -> Result { if s == "~one" { - return FlatVariable::one(); + return Ok(FlatVariable::one()); } + let mut public = s.split("~out_"); match public.nth(1) { - Some(v) => return FlatVariable::public(v.parse().unwrap()), - None => {} + Some(v) => { + let v = v.parse().map_err(|_| s)?; + Ok(FlatVariable::public(v)) + } + None => { + let mut private = s.split("_"); + match private.nth(1) { + Some(v) => { + let v = v.parse().map_err(|_| s)?; + Ok(FlatVariable::new(v)) + } + None => Err(s), + } + } } - let mut private = s.split("_"); - match private.nth(1) { - Some(v) => return FlatVariable::new(v.parse().unwrap()), - None => {} - } - unreachable!() } } diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index c8a9a787..e1c8b09b 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -1,75 +1,12 @@ +use flat_absy::flat_variable::FlatVariable; use helpers::Executable; -use ir::*; +use ir::{LinComb, Prog, QuadComb, Statement, Witness}; use std::collections::BTreeMap; +use std::fmt; use zokrates_field::field::Field; pub type ExecutionResult = Result, Error>; -#[derive(Clone, Debug, PartialEq)] -pub struct Witness(pub BTreeMap); - -impl Witness { - pub fn return_values(&self) -> Vec { - let out = self - .0 - .iter() - .filter(|(k, _)| k.is_output()) - .collect::>(); - - (0..out.len()) - .map(|i| *out.get(&FlatVariable::public(i)).unwrap()) - .cloned() - .collect() - } - - pub fn format_outputs(&self) -> String { - self.0 - .iter() - .filter_map(|(variable, value)| match variable { - variable if variable.is_output() => Some(format!("{} {}", variable, value)), - _ => None, - }) - .collect::>() - .join("\n") - } - - pub fn empty() -> Self { - Witness(BTreeMap::new()) - } - - pub fn into_human_readable(self) -> impl Iterator { - self.0 - .into_iter() - .map(|(var, val)| (var.to_string(), val.to_dec_string())) - } - - pub fn from_human_readable>(i: I) -> Witness { - Witness( - i.map(|(var, val)| { - ( - FlatVariable::from_human_readable(&var), - T::from_dec_string(val), - ) - }) - .collect(), - ) - } -} - -impl fmt::Display for Witness { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - self.0 - .iter() - .map(|(k, v)| format!("{} {}", k, v.to_dec_string())) - .collect::>() - .join("\n") - ) - } -} - impl Prog { pub fn execute + Clone>(&self, inputs: &Vec) -> ExecutionResult { let main = &self.main; @@ -188,28 +125,3 @@ impl fmt::Debug for Error { write!(f, "{}", self) } } - -#[cfg(test)] -mod tests { - - use super::*; - use zokrates_field::field::FieldPrime; - - #[test] - fn human_readable_witness() { - let witness = Witness( - vec![ - (FlatVariable::public(0), 3), - (FlatVariable::new(0), 2), - (FlatVariable::one(), 1), - ] - .into_iter() - .map(|(x, y)| (x, FieldPrime::from(y))) - .collect(), - ); - assert_eq!( - witness.clone(), - Witness::from_human_readable(witness.into_human_readable()) - ); - } -} diff --git a/zokrates_core/src/ir/mod.rs b/zokrates_core/src/ir/mod.rs index c09422ac..e7573183 100644 --- a/zokrates_core/src/ir/mod.rs +++ b/zokrates_core/src/ir/mod.rs @@ -1,18 +1,19 @@ use flat_absy::flat_parameter::FlatParameter; use flat_absy::FlatVariable; use helpers::Helper; -use std::collections::HashMap; use std::fmt; use zokrates_field::field::Field; mod expression; mod from_flat; mod interpreter; +mod witness; pub use self::expression::LinComb; use self::expression::QuadComb; -pub use self::interpreter::{Error, ExecutionResult, Witness}; +pub use self::interpreter::{Error, ExecutionResult}; +pub use self::witness::Witness; #[derive(Debug, Serialize, Deserialize, Clone)] pub enum Statement { diff --git a/zokrates_core/src/ir/witness.rs b/zokrates_core/src/ir/witness.rs new file mode 100644 index 00000000..47a04117 --- /dev/null +++ b/zokrates_core/src/ir/witness.rs @@ -0,0 +1,167 @@ +use flat_absy::FlatVariable; +use std::collections::{BTreeMap, HashMap}; +use std::fmt; +use std::io; +use std::io::{Read, Write}; +use zokrates_field::field::Field; + +#[derive(Clone, Debug, PartialEq)] +pub struct Witness(pub BTreeMap); + +impl Witness { + pub fn return_values(&self) -> Vec { + let out = self + .0 + .iter() + .filter(|(k, _)| k.is_output()) + .collect::>(); + + (0..out.len()) + .map(|i| *out.get(&FlatVariable::public(i)).unwrap()) + .cloned() + .collect() + } + + pub fn format_outputs(&self) -> String { + self.0 + .iter() + .filter_map(|(variable, value)| match variable { + variable if variable.is_output() => Some(format!("{} {}", variable, value)), + _ => None, + }) + .collect::>() + .join("\n") + } + + pub fn empty() -> Self { + Witness(BTreeMap::new()) + } + + pub fn write(&self, writer: W) -> io::Result<()> { + let mut wtr = csv::WriterBuilder::new() + .delimiter(b' ') + .flexible(true) + .has_headers(false) + .from_writer(writer); + + // Write each line of the witness to the file + for (variable, value) in &self.0 { + wtr.serialize((variable.to_string(), value.to_dec_string()))?; + } + + Ok(()) + } + + pub fn read(mut reader: R) -> io::Result { + let mut rdr = csv::ReaderBuilder::new() + .delimiter(b' ') + .flexible(true) + .has_headers(false) + .from_reader(&mut reader); + + let map = rdr + .deserialize::<(String, String)>() + .map(|r| { + r.map(|(variable, value)| { + let variable = + FlatVariable::try_from_human_readable(&variable).map_err(|why| { + io::Error::new( + io::ErrorKind::Other, + format!("Invalid variable in witness: {}", why), + ) + })?; + let value = T::try_from_dec_str(&value).map_err(|_| { + io::Error::new( + io::ErrorKind::Other, + format!("Invalid value in witness: {}", value), + ) + })?; + Ok((variable, value)) + }) + .map_err(|e| match e.into_kind() { + csv::ErrorKind::Io(e) => e, + e => io::Error::new(io::ErrorKind::Other, format!("{:?}", e)), + })? + }) + .collect::>>()?; + + Ok(Witness(map)) + } +} + +impl fmt::Display for Witness { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}", + self.0 + .iter() + .map(|(k, v)| format!("{} {}", k, v.to_dec_string())) + .collect::>() + .join("\n") + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use zokrates_field::field::FieldPrime; + + mod io { + use super::*; + use std::io::Cursor; + + #[test] + fn serialize_deserialize() { + let w = Witness( + vec![ + (FlatVariable::new(42), FieldPrime::from(42)), + (FlatVariable::public(8), FieldPrime::from(8)), + (FlatVariable::one(), FieldPrime::from(1)), + ] + .into_iter() + .collect(), + ); + + let mut buff = Cursor::new(vec![]); + + w.write(&mut buff).unwrap(); + buff.set_position(0); + + let r = Witness::read(buff).unwrap(); + + assert_eq!(w, r); + } + + #[test] + fn wrong_value() { + let mut buff = Cursor::new(vec![]); + + buff.write("_1 123bug".as_ref()).unwrap(); + buff.set_position(0); + + assert!(Witness::::read(buff).is_err()); + } + + #[test] + fn wrong_variable() { + let mut buff = Cursor::new(vec![]); + + buff.write("_1bug 123".as_ref()).unwrap(); + buff.set_position(0); + + assert!(Witness::::read(buff).is_err()); + } + + #[test] + #[should_panic] + fn not_csv() { + let mut buff = Cursor::new(vec![]); + buff.write("whatwhat".as_ref()).unwrap(); + buff.set_position(0); + + assert!(Witness::::read(buff).is_err()); + } + } +} diff --git a/zokrates_core/src/lib.rs b/zokrates_core/src/lib.rs index c43f2529..b5eadf1a 100644 --- a/zokrates_core/src/lib.rs +++ b/zokrates_core/src/lib.rs @@ -41,5 +41,4 @@ pub mod flat_absy; pub mod ir; #[cfg(feature = "libsnark")] pub mod libsnark; -// #[cfg(feature = "libsnark")] pub mod proof_system; diff --git a/zokrates_core/src/libsnark.rs b/zokrates_core/src/libsnark.rs index 3cb0740f..9fda4091 100644 --- a/zokrates_core/src/libsnark.rs +++ b/zokrates_core/src/libsnark.rs @@ -100,7 +100,7 @@ mod tests { ) .unwrap() .to_bytes_le(), - FieldPrime::try_from_str( + FieldPrime::try_from_dec_str( "5472060717959818805561601436314318772174077789324455915672259473661306552146" ) .unwrap() @@ -112,7 +112,7 @@ mod tests { fn serialization_bin() { assert_eq!( BigUint::parse_bytes(b"110000011001000100111001110010111000010011000110100000001010011011100001010000010001011011011010000001100000010101100001011101100101111000000101101010100100010110100001110001110010101000110100111100001000001000110000010110110110000111110011111101010010",2).unwrap().to_bytes_le(), - FieldPrime::try_from_str("5472060717959818805561601436314318772174077789324455915672259473661306552146").unwrap().into_byte_vector() + FieldPrime::try_from_dec_str("5472060717959818805561601436314318772174077789324455915672259473661306552146").unwrap().into_byte_vector() ); } diff --git a/zokrates_core/src/parser/tokenize/tokenizer.rs b/zokrates_core/src/parser/tokenize/tokenizer.rs index 31f6384d..5b41dae3 100644 --- a/zokrates_core/src/parser/tokenize/tokenizer.rs +++ b/zokrates_core/src/parser/tokenize/tokenizer.rs @@ -16,7 +16,7 @@ pub fn parse_num(input: &String, pos: &Position) -> (Token, String, } assert!(end > 0); ( - Token::Num(T::try_from_str(&input[0..end]).unwrap()), + Token::Num(T::try_from_dec_str(&input[0..end]).unwrap()), input[end..].to_string(), Position { line: pos.line, diff --git a/zokrates_core/src/proof_system/bn128/g16.rs b/zokrates_core/src/proof_system/bn128/g16.rs index 53ef2e40..871cbf22 100644 --- a/zokrates_core/src/proof_system/bn128/g16.rs +++ b/zokrates_core/src/proof_system/bn128/g16.rs @@ -1,6 +1,6 @@ use bellman::groth16::Parameters; use ir; -use proof_system::bn128::utils::bellman::{serialize_proof, serialize_vk, Computation}; +use proof_system::bn128::utils::bellman::Computation; use proof_system::bn128::utils::solidity::{SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB}; use proof_system::ProofSystem; use regex::Regex; @@ -22,7 +22,9 @@ impl ProofSystem for G16 { let parameters_file = File::create(PathBuf::from(pk_path)).unwrap(); parameters.write(parameters_file).unwrap(); let mut vk_file = File::create(PathBuf::from(vk_path)).unwrap(); - vk_file.write(serialize_vk(parameters.vk).as_ref()).unwrap(); + vk_file + .write(serialize::serialize_vk(parameters.vk).as_ref()) + .unwrap(); } fn generate_proof( @@ -47,7 +49,7 @@ impl ProofSystem for G16 { write!( proof_file, "{}", - serialize_proof(&proof, &computation.public_inputs_values()) + serialize::serialize_proof(&proof, &computation.public_inputs_values()) ) .unwrap(); true @@ -134,6 +136,72 @@ impl ProofSystem for G16 { } } +mod serialize { + + use bellman::groth16::{Proof, VerifyingKey}; + use pairing::bn256::{Bn256, Fr}; + + pub fn serialize_vk(vk: VerifyingKey) -> String { + format!( + "vk.alpha = {} + vk.beta = {} + vk.gamma = {} + vk.delta = {} + vk.gammaABC.len() = {} + {}", + vk.alpha_g1, + vk.beta_g2, + vk.gamma_g2, + vk.delta_g2, + vk.ic.len(), + vk.ic + .iter() + .enumerate() + .map(|(i, x)| format!("vk.gammaABC[{}] = {}", i, x)) + .collect::>() + .join("\n") + ) + .replace("G2(x=Fq2(Fq(", "[") + .replace("), y=Fq(", ", ") + .replace("G1(x=Fq(", "") + .replace(") + Fq(", ", ") + .replace("))", "") + .replace(") * u), y=Fq2(Fq(", "], [") + .replace(") * u", "]") + } + + pub fn serialize_proof(p: &Proof, inputs: &Vec) -> String { + format!( + "{{ + \"proof\": {{ + \"a\": {}, + \"b\": {}, + \"c\": {} + }}, + \"inputs\": [{}] + }}", + p.a, + p.b, + p.c, + inputs + .iter() + .map(|v| format!("\"{}\"", v)) + .collect::>() + .join(", "), + ) + .replace("G2(x=Fq2(Fq(", "[[\"") + .replace("), y=Fq(", "\", \"") + .replace("G1(x=Fq(", "[\"") + .replace(") + Fq(", "\", \"") + .replace(") * u), y=Fq2(Fq(", "\"], [\"") + .replace(") * u]", "\"]]") + .replace(") * u))", "\"]]") + .replace("))", "\"]") + .replace("Fr(", "") + .replace(")", "") + } +} + const CONTRACT_TEMPLATE: &str = r#" contract Verifier { using Pairing for *; diff --git a/zokrates_core/src/proof_system/bn128/utils/bellman.rs b/zokrates_core/src/proof_system/bn128/utils/bellman.rs index 5d09a566..f127113e 100644 --- a/zokrates_core/src/proof_system/bn128/utils/bellman.rs +++ b/zokrates_core/src/proof_system/bn128/utils/bellman.rs @@ -3,7 +3,7 @@ extern crate rand; use bellman::groth16::Proof; use bellman::groth16::{ create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, - Parameters, VerifyingKey, + Parameters, }; use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable}; use ir::{LinComb, Prog, Statement, Witness}; @@ -189,66 +189,6 @@ impl Circuit for Computation { } } -pub fn serialize_vk(vk: VerifyingKey) -> String { - format!( - "vk.alpha = {} -vk.beta = {} -vk.gamma = {} -vk.delta = {} -vk.gammaABC.len() = {} -{}", - vk.alpha_g1, - vk.beta_g2, - vk.gamma_g2, - vk.delta_g2, - vk.ic.len(), - vk.ic - .iter() - .enumerate() - .map(|(i, x)| format!("vk.gammaABC[{}] = {}", i, x)) - .collect::>() - .join("\n") - ) - .replace("G2(x=Fq2(Fq(", "[") - .replace("), y=Fq(", ", ") - .replace("G1(x=Fq(", "") - .replace(") + Fq(", ", ") - .replace("))", "") - .replace(") * u), y=Fq2(Fq(", "], [") - .replace(") * u", "]") -} - -pub fn serialize_proof(p: &Proof, inputs: &Vec) -> String { - format!( - "{{ - \"proof\": {{ - \"a\": {}, - \"b\": {}, - \"c\": {} - }}, - \"inputs\": [{}] -}}", - p.a, - p.b, - p.c, - inputs - .iter() - .map(|v| format!("\"{}\"", v)) - .collect::>() - .join(", "), - ) - .replace("G2(x=Fq2(Fq(", "[[\"") - .replace("), y=Fq(", "\", \"") - .replace("G1(x=Fq(", "[\"") - .replace(") + Fq(", "\", \"") - .replace(") * u), y=Fq2(Fq(", "\"], [\"") - .replace(") * u]", "\"]]") - .replace(") * u))", "\"]]") - .replace("))", "\"]") - .replace("Fr(", "") - .replace(")", "") -} - #[cfg(test)] mod tests { use super::*; diff --git a/zokrates_core/tests/utils/mod.rs b/zokrates_core/tests/utils/mod.rs index 97087ebc..a090fa24 100644 --- a/zokrates_core/tests/utils/mod.rs +++ b/zokrates_core/tests/utils/mod.rs @@ -44,8 +44,8 @@ impl From for ComparableResult { fn from(r: TestResult) -> ComparableResult { ComparableResult(r.map(|v| { v.values - .into_iter() - .map(|v| FieldPrime::from_dec_string(v)) + .iter() + .map(|v| FieldPrime::try_from_dec_str(v).unwrap()) .collect() })) } @@ -102,7 +102,7 @@ macro_rules! zokrates_test { for test in t.tests.into_iter() { let input = &test.input.values; - let output = bin.execute(&input.iter().map(|v| FieldPrime::from_dec_string(v.clone())).collect()); + let output = bin.execute(&input.iter().map(|v| FieldPrime::try_from_dec_str(v).unwrap()).collect()); let context = format!(" {} diff --git a/zokrates_field/src/field.rs b/zokrates_field/src/field.rs index 92e3abda..6f030221 100644 --- a/zokrates_field/src/field.rs +++ b/zokrates_field/src/field.rs @@ -7,7 +7,7 @@ use lazy_static::lazy_static; use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; use num_integer::Integer; -use num_traits::{Num, One, Zero}; +use num_traits::{One, Zero}; use serde_derive::{Deserialize, Serialize}; use std::convert::From; use std::fmt; @@ -59,8 +59,6 @@ pub trait Field: fn from_byte_vector(_: Vec) -> Self; /// Returns this `Field`'s contents as decimal string fn to_dec_string(&self) -> String; - /// Returns an element of this `Field` from a decimal string - fn from_dec_string(val: String) -> Self; /// Returns the multiplicative inverse, i.e.: self * self.inverse_mul() = Self::one() fn inverse_mul(&self) -> Self; /// Returns the smallest value that can be represented by this field type. @@ -70,7 +68,7 @@ pub trait Field: /// Returns the number of required bits to represent this field type. fn get_required_bits() -> usize; /// Tries to parse a string into this representation - fn try_from_str<'a>(s: &'a str) -> Result; + fn try_from_dec_str<'a>(s: &'a str) -> Result; /// Returns a decimal string representing a the member of the equivalence class of this `Field` in Z/pZ /// which lies in [-(p-1)/2, (p-1)/2] fn to_compact_dec_string(&self) -> String; @@ -100,12 +98,6 @@ impl Field for FieldPrime { self.value.to_str_radix(10) } - fn from_dec_string(val: String) -> Self { - FieldPrime { - value: BigInt::from_str_radix(val.as_str(), 10).unwrap(), - } - } - fn inverse_mul(&self) -> FieldPrime { let (b, s, _) = extended_euclid(&self.value, &*P); assert_eq!(b, BigInt::one()); @@ -126,7 +118,7 @@ impl Field for FieldPrime { fn get_required_bits() -> usize { (*P).bits() } - fn try_from_str<'a>(s: &'a str) -> Result { + fn try_from_dec_str<'a>(s: &'a str) -> Result { let x = BigInt::parse_bytes(s.as_bytes(), 10).ok_or(())?; Ok(FieldPrime { value: &x - x.div_floor(&*P) * &*P, @@ -364,7 +356,7 @@ mod tests { impl<'a> From<&'a str> for FieldPrime { fn from(s: &'a str) -> FieldPrime { - FieldPrime::try_from_str(s).unwrap() + FieldPrime::try_from_dec_str(s).unwrap() } } @@ -624,7 +616,7 @@ mod tests { fn dec_string_ser_deser() { let fp = FieldPrime::from("101"); let bv = fp.to_dec_string(); - assert_eq!(fp, FieldPrime::from_dec_string(bv)); + assert_eq!(fp, FieldPrime::try_from_dec_str(&bv).unwrap()); } #[test] diff --git a/zokrates_stdlib/tests/test_template b/zokrates_stdlib/tests/test_template index 3a345f6a..af48b620 100644 --- a/zokrates_stdlib/tests/test_template +++ b/zokrates_stdlib/tests/test_template @@ -27,7 +27,7 @@ fn {test_name}() {{ for test in t.tests.into_iter() {{ let input = &test.input.values; - let output = bin.execute(&input.iter().map(|v| FieldPrime::from_dec_string(v.clone())).collect()); + let output = bin.execute(&input.iter().map(|v| FieldPrime::try_from_dec_str(&v.clone()).unwrap()).collect()); match utils::compare(output, test.output) {{ Err(e) => {{ diff --git a/zokrates_stdlib/tests/utils/mod.rs b/zokrates_stdlib/tests/utils/mod.rs index 64d98c4f..11ff8911 100644 --- a/zokrates_stdlib/tests/utils/mod.rs +++ b/zokrates_stdlib/tests/utils/mod.rs @@ -41,8 +41,8 @@ impl From for ComparableResult { fn from(r: TestResult) -> ComparableResult { ComparableResult(r.map(|v| { v.values - .into_iter() - .map(|v| FieldPrime::from_dec_string(v)) + .iter() + .map(|v| FieldPrime::try_from_dec_str(v).unwrap()) .collect() })) }