1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

fix following review: extract witness with write read, rename scheme to proving scheme, typos

This commit is contained in:
schaeff 2019-04-08 14:56:07 +02:00
parent 869b516d44
commit 0be493fdd1
19 changed files with 313 additions and 242 deletions

2
Cargo.lock generated
View file

@ -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)",

View file

@ -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

View file

@ -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"

View file

@ -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();

View file

@ -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()

View file

@ -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"

View file

@ -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<Self, &str> {
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!()
}
}

View file

@ -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<T> = Result<Witness<T>, Error>;
#[derive(Clone, Debug, PartialEq)]
pub struct Witness<T: Field>(pub BTreeMap<FlatVariable, T>);
impl<T: Field> Witness<T> {
pub fn return_values(&self) -> Vec<T> {
let out = self
.0
.iter()
.filter(|(k, _)| k.is_output())
.collect::<HashMap<_, _>>();
(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::<Vec<String>>()
.join("\n")
}
pub fn empty() -> Self {
Witness(BTreeMap::new())
}
pub fn into_human_readable(self) -> impl Iterator<Item = (String, String)> {
self.0
.into_iter()
.map(|(var, val)| (var.to_string(), val.to_dec_string()))
}
pub fn from_human_readable<I: Iterator<Item = (String, String)>>(i: I) -> Witness<T> {
Witness(
i.map(|(var, val)| {
(
FlatVariable::from_human_readable(&var),
T::from_dec_string(val),
)
})
.collect(),
)
}
}
impl<T: Field> fmt::Display for Witness<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
self.0
.iter()
.map(|(k, v)| format!("{} {}", k, v.to_dec_string()))
.collect::<Vec<_>>()
.join("\n")
)
}
}
impl<T: Field> Prog<T> {
pub fn execute<U: Into<T> + Clone>(&self, inputs: &Vec<U>) -> ExecutionResult<T> {
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())
);
}
}

View file

@ -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<T: Field> {

View file

@ -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<T: Field>(pub BTreeMap<FlatVariable, T>);
impl<T: Field> Witness<T> {
pub fn return_values(&self) -> Vec<T> {
let out = self
.0
.iter()
.filter(|(k, _)| k.is_output())
.collect::<HashMap<_, _>>();
(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::<Vec<String>>()
.join("\n")
}
pub fn empty() -> Self {
Witness(BTreeMap::new())
}
pub fn write<W: 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<R: Read>(mut reader: R) -> io::Result<Self> {
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::<io::Result<BTreeMap<FlatVariable, T>>>()?;
Ok(Witness(map))
}
}
impl<T: Field> fmt::Display for Witness<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
self.0
.iter()
.map(|(k, v)| format!("{} {}", k, v.to_dec_string()))
.collect::<Vec<_>>()
.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::<FieldPrime>::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::<FieldPrime>::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::<FieldPrime>::read(buff).is_err());
}
}
}

View file

@ -41,5 +41,4 @@ pub mod flat_absy;
pub mod ir;
#[cfg(feature = "libsnark")]
pub mod libsnark;
// #[cfg(feature = "libsnark")]
pub mod proof_system;

View file

@ -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()
);
}

View file

@ -16,7 +16,7 @@ pub fn parse_num<T: Field>(input: &String, pos: &Position) -> (Token<T>, 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,

View file

@ -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<Bn256>) -> 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::<Vec<_>>()
.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<Bn256>, inputs: &Vec<Fr>) -> String {
format!(
"{{
\"proof\": {{
\"a\": {},
\"b\": {},
\"c\": {}
}},
\"inputs\": [{}]
}}",
p.a,
p.b,
p.c,
inputs
.iter()
.map(|v| format!("\"{}\"", v))
.collect::<Vec<_>>()
.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 *;

View file

@ -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<Bn256> for Computation<FieldPrime> {
}
}
pub fn serialize_vk(vk: VerifyingKey<Bn256>) -> 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::<Vec<_>>()
.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<Bn256>, inputs: &Vec<Fr>) -> String {
format!(
"{{
\"proof\": {{
\"a\": {},
\"b\": {},
\"c\": {}
}},
\"inputs\": [{}]
}}",
p.a,
p.b,
p.c,
inputs
.iter()
.map(|v| format!("\"{}\"", v))
.collect::<Vec<_>>()
.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::*;

View file

@ -44,8 +44,8 @@ impl From<TestResult> 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!("
{}

View file

@ -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<u8>) -> 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<Self, ()>;
fn try_from_dec_str<'a>(s: &'a str) -> Result<Self, ()>;
/// 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<Self, ()> {
fn try_from_dec_str<'a>(s: &'a str) -> Result<Self, ()> {
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]

View file

@ -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) => {{

View file

@ -41,8 +41,8 @@ impl From<TestResult> 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()
}))
}