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

integrate with backend api, activate with --backend g16

This commit is contained in:
schaeff 2019-02-15 11:41:35 +01:00
commit b0e8b9d042
21 changed files with 337 additions and 390 deletions

28
Cargo.lock generated
View file

@ -3,7 +3,7 @@ name = "aho-corasick"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -83,7 +83,7 @@ dependencies = [
"ff 0.5.0 (git+https://github.com/matterinc/ff)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pairing 0.15.2 (git+https://github.com/matterinc/pairing)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -330,7 +330,7 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -440,12 +440,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.1.3"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memoffset"
@ -523,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
@ -735,7 +731,7 @@ dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -770,7 +766,7 @@ version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1089,7 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "zokrates_cli"
version = "0.4.1"
version = "0.4.2"
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)",
@ -1097,14 +1093,14 @@ dependencies = [
"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.38 (registry+https://github.com/rust-lang/crates.io-index)",
"zokrates_core 0.3.5",
"zokrates_core 0.3.6",
"zokrates_field 0.3.2",
"zokrates_fs_resolver 0.4.0",
]
[[package]]
name = "zokrates_core"
version = "0.3.5"
version = "0.3.6"
dependencies = [
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman 0.1.3 (git+https://github.com/matterinc/bellman)",
@ -1210,7 +1206,7 @@ dependencies = [
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
@ -1221,7 +1217,7 @@ dependencies = [
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238"
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6"
"checksum pairing 0.15.2 (git+https://github.com/matterinc/pairing)" = "<none>"

1
proof.json Normal file
View file

@ -0,0 +1 @@
˜2°J«ִגי*דמE ָt<EFBFBD>S9ֻ"ֹrפWחw״{1 ת ל ה%ע>כ®ְpsמqtA)§בD<EFBFBD>Zװ>ƒדM?<EFBFBD>h..´Vה<EFBFBD>C}÷[ ¨p°5<EFBFBD>U¬NGHרI½{>ְװ¦<EFBFBD>י<EFBFBD>05<EFBFBD>0OLד`\ןj

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_cli"
version = "0.4.1"
version = "0.4.2"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>", "Thibaut Schaeffer <thibaut@schaeff.fr>"]
repository = "https://github.com/JacobEberhardt/ZoKrates.git"
edition = "2018"
@ -16,11 +16,11 @@ regex = "0.2"
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"
[dev-dependencies]
glob = "0.2.11"
assert_cli = "0.5"
serde_json = "1.0"
[[bin]]
name = "zokrates"

View file

@ -6,8 +6,6 @@
use bincode::{deserialize_from, serialize_into, Infinite};
use clap::{App, AppSettings, Arg, SubCommand};
#[cfg(feature = "libsnark")]
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, BufWriter, Write};
@ -15,10 +13,7 @@ use std::path::{Path, PathBuf};
use std::string::String;
use zokrates_core::compile::compile;
use zokrates_core::ir;
#[cfg(feature = "libsnark")]
use zokrates_core::ir::r1cs_program;
#[cfg(feature = "libsnark")]
use zokrates_core::proof_system::{ProofSystem, GM17, PGHR13};
use zokrates_core::proof_system::*;
use zokrates_field::field::{Field, FieldPrime};
use zokrates_fs_resolver::resolve as fs_resolve;
@ -42,7 +37,7 @@ fn cli() -> Result<(), String> {
// cli specification using clap library
let matches = App::new("ZoKrates")
.setting(AppSettings::SubcommandRequiredElseHelp)
.version("0.4.1")
.version("0.4.2")
.author("Jacob Eberhardt, Thibaut Schaeffer, Dennis Kuhnert")
.about("Supports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.\n'I know that I show nothing!'")
.subcommand(SubCommand::with_name("compile")
@ -202,8 +197,16 @@ fn cli() -> Result<(), String> {
.takes_value(true)
.required(false)
.default_value(JSON_PROOF_PATH)
).arg(Arg::with_name("meta-information")
).arg(Arg::with_name("input")
.short("i")
.long("input")
.help("Path of compiled code")
.value_name("FILE")
.takes_value(true)
.required(false)
.default_value(FLATTENED_CODE_DEFAULT_PATH)
).arg(Arg::with_name("meta-information")
.short("m")
.long("meta-information")
.help("Path of file containing meta information for variable transformation")
.value_name("FILE")
@ -373,13 +376,18 @@ fn cli() -> Result<(), String> {
let output_file = File::create(&output_path)
.map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?;
//println!("{:?}", witness);
let mut bw = BufWriter::new(output_file);
write!(&mut bw, "{}", witness)
.map_err(|_| "Unable to write data to file.".to_string())?;
write!(
&mut bw,
"{}",
&serde_json::to_string_pretty(&ir::WitnessVec::from(witness)).unwrap()
)
.map_err(|_| "Unable to write data to file.".to_string())?;
bw.flush()
.map_err(|_| "Unable to flush buffer.".to_string())?;
}
#[cfg(feature = "libsnark")]
("setup", Some(sub_matches)) => {
let backend = get_backend(sub_matches.value_of("backend").unwrap())?;
@ -395,8 +403,13 @@ fn cli() -> Result<(), String> {
// print deserialized flattened program
println!("{}", program);
// transform to R1CS
let (variables, public_variables_count, a, b, c) = r1cs_program(program);
// get paths for proving and verification keys
let pk_path = sub_matches.value_of("proving-key-path").unwrap();
let vk_path = sub_matches.value_of("verification-key-path").unwrap();
// run setup phase
// number of inputs in the zkSNARK sense, i.e., input variables + output variables
let metadata = backend.setup(program, pk_path, vk_path);
// write variables meta information to file
let var_inf_path = Path::new(sub_matches.value_of("meta-information").unwrap());
@ -406,41 +419,13 @@ fn cli() -> Result<(), String> {
write!(
&mut bw,
"Private inputs offset:\n{}\n",
public_variables_count
"{}",
&serde_json::to_string_pretty(&metadata).unwrap()
)
.map_err(|_| "Unable to write data to file.".to_string())?;
write!(&mut bw, "R1CS variable order:\n")
.map_err(|_| "Unable to write data to file.".to_string())?;
for var in &variables {
write!(&mut bw, "{} ", var)
.map_err(|_| "Unable to write data to file.".to_string())?;
}
write!(&mut bw, "\n").map_err(|_| "Unable to write data to file.".to_string())?;
bw.flush()
.map_err(|_| "Unable to flush buffer.".to_string())?;
// get paths for proving and verification keys
let pk_path = sub_matches.value_of("proving-key-path").unwrap();
let vk_path = sub_matches.value_of("verification-key-path").unwrap();
// run setup phase
// number of inputs in the zkSNARK sense, i.e., input variables + output variables
println!(
"setup successful: {:?}",
backend.setup(
variables,
a,
b,
c,
public_variables_count - 1,
pk_path,
vk_path
)
);
}
#[cfg(feature = "libsnark")]
("export-verifier", Some(sub_matches)) => {
{
let backend = get_backend(sub_matches.value_of("backend").unwrap())?;
@ -466,7 +451,6 @@ fn cli() -> Result<(), String> {
println!("Finished exporting verifier.");
}
}
#[cfg(feature = "libsnark")]
("generate-proof", Some(sub_matches)) => {
println!("Generating proof...");
@ -474,74 +458,43 @@ fn cli() -> Result<(), String> {
// deserialize witness
let witness_path = Path::new(sub_matches.value_of("witness").unwrap());
let witness_file = File::open(&witness_path)
.map_err(|why| format!("couldn't open {}: {}", witness_path.display(), why))?;
let witness_file = match File::open(&witness_path) {
Ok(file) => file,
Err(why) => panic!("couldn't open {}: {}", witness_path.display(), why),
};
let reader = BufReader::new(witness_file);
let mut lines = reader.lines();
let mut witness_map = HashMap::new();
let witness: ir::WitnessVec<FieldPrime> =
serde_json::from_reader(BufReader::new(witness_file)).unwrap();
loop {
match lines.next() {
Some(Ok(ref x)) => {
let pairs: Vec<&str> = x.split_whitespace().collect();
witness_map.insert(
pairs[0].to_string(),
FieldPrime::from_dec_string(pairs[1].to_string()),
);
}
None => break,
Some(Err(err)) => return Err(format!("Error reading witness: {}", err)),
}
}
let witness = ir::Witness::from(witness);
// determine variable order
let var_inf_path = Path::new(sub_matches.value_of("meta-information").unwrap());
let var_inf_file = File::open(&var_inf_path)
.map_err(|why| format!("couldn't open {}: {}", var_inf_path.display(), why))?;
let var_reader = BufReader::new(var_inf_file);
let mut var_lines = var_reader.lines();
println!("Using Witness: {}", witness);
// get private inputs offset
let private_inputs_offset;
if let Some(Ok(ref o)) = var_lines.nth(1) {
// consumes first 2 lines
private_inputs_offset = o
.parse()
.map_err(|_| "Failed parsing private inputs offset")?;
} else {
return Err(format!("Error reading private inputs offset"));
}
// deserialize metadata
let metadata_path = Path::new(sub_matches.value_of("meta-information").unwrap());
// get variables vector
let mut variables: Vec<String> = Vec::new();
if let Some(Ok(ref v)) = var_lines.nth(1) {
let iter = v.split_whitespace();
for i in iter {
variables.push(i.to_string());
}
} else {
return Err(format!("Error reading variables"));
}
let metadata_file = match File::open(&metadata_path) {
Ok(file) => file,
Err(why) => panic!("couldn't open {}: {}", metadata_path.display(), why),
};
println!("Using Witness: {:?}", witness_map);
let witness: Vec<_> = variables.iter().map(|x| witness_map[x].clone()).collect();
// split witness into public and private inputs at offset
let mut public_inputs: Vec<_> = witness.clone();
let private_inputs: Vec<_> = public_inputs.split_off(private_inputs_offset);
println!("Public inputs: {:?}", public_inputs);
println!("Private inputs: {:?}", private_inputs);
let metadata: Metadata =
serde_json::from_reader(BufReader::new(metadata_file)).unwrap();
let pk_path = sub_matches.value_of("provingkey").unwrap();
let proof_path = sub_matches.value_of("proofpath").unwrap();
let program_path = Path::new(sub_matches.value_of("input").unwrap());
let mut program_file = File::open(&program_path)
.map_err(|why| format!("couldn't open {}: {}", program_path.display(), why))?;
let program: ir::Prog<FieldPrime> = deserialize_from(&mut program_file, Infinite)
.map_err(|why| format!("{:?}", why))?;
// run libsnark
println!(
"generate-proof successful: {:?}",
backend.generate_proof(pk_path, proof_path, public_inputs, private_inputs)
backend.generate_proof(program, witness, metadata, pk_path, proof_path)
);
}
_ => unreachable!(),
@ -549,11 +502,13 @@ fn cli() -> Result<(), String> {
Ok(())
}
#[cfg(feature = "libsnark")]
fn get_backend(backend_str: &str) -> Result<&'static ProofSystem, String> {
match backend_str.to_lowercase().as_ref() {
#[cfg(feature = "libsnark")]
"pghr13" => Ok(&PGHR13 {}),
#[cfg(feature = "libsnark")]
"gm17" => Ok(&GM17 {}),
"g16" => Ok(&G16 {}),
s => Err(format!("Backend \"{}\" not supported", s)),
}
}

View file

@ -199,11 +199,13 @@ mod integration {
assert_cli::Assert::command(&[
"../target/release/zokrates",
"generate-proof",
"-i",
flattened_path.to_str().unwrap(),
"-w",
witness_path.to_str().unwrap(),
"-p",
proving_key_path.to_str().unwrap(),
"-i",
"-m",
variable_information_path.to_str().unwrap(),
"--backend",
backend,

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_core"
version = "0.3.5"
version = "0.3.6"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
repository = "https://github.com/JacobEberhardt/ZoKrates"
readme = "README.md"

View file

@ -49,7 +49,6 @@ impl Flattener {
fn load_corelib<T: Field>(&mut self, functions_flattened: &mut Vec<FlatFunction<T>>) -> () {
// Load type casting functions
functions_flattened.push(cast(&Type::Boolean, &Type::FieldElement));
functions_flattened.push(cast(&Type::FieldElement, &Type::Boolean));
// Load IfElse helper
let ie = TypedFunction {

View file

@ -72,7 +72,7 @@ fn alloc<CS: ConstraintSystem<Bn256>>(
witness: &Witness<FieldPrime>,
) -> Result<Variable, SynthesisError> {
match var.is_output() {
true => cs.alloc(
true => cs.alloc_input(
|| format!("{}", var),
|| {
// let w = witness.ok_or(SynthesisError::AssignmentMissing)?;
@ -83,7 +83,7 @@ fn alloc<CS: ConstraintSystem<Bn256>>(
Ok(Fr::from(val.clone()))
},
),
false => cs.alloc_input(
false => cs.alloc(
|| format!("{}", var),
|| {
// let witness = witness.ok_or(SynthesisError::AssignmentMissing)?;
@ -107,7 +107,7 @@ impl Prog<FieldPrime> {
let mut arguments = vec![];
let witness = witness.unwrap();
let witness = witness.unwrap_or(Witness::empty());
for (index, (var, private)) in self
.main
@ -178,6 +178,39 @@ impl Prog<FieldPrime> {
}
impl Computation<FieldPrime> {
pub fn prove(self, params: Parameters<Bn256>) -> Proof<Bn256> {
let rng = &mut thread_rng();
let proof = create_random_proof(self.clone(), &params, rng).unwrap();
let pvk = prepare_verifying_key(&params.vk);
// extract public inputs
let public_inputs: Vec<Fr> = self
.program
.main
.arguments
.clone()
.iter()
.zip(self.program.private.clone())
.filter(|(_, p)| !p)
.map(|(a, _)| a)
.chain(
self.witness
.clone()
.unwrap()
.0
.keys()
.filter(|k| k.is_output()),
)
.map(|v| self.witness.clone().unwrap().0.get(v).unwrap().clone())
.map(|v| Fr::from(v.clone()))
.collect();
assert!(verify_proof(&pvk, &proof, &public_inputs).unwrap());
proof
}
pub fn setup_prove_verify(self) -> Proof<Bn256> {
// run setup phase
let params = self.clone().setup();
@ -285,7 +318,7 @@ mod tests {
use super::*;
#[test]
fn empty_program() {
fn empty() {
let program: Prog<FieldPrime> = Prog {
main: Function {
id: String::from("main"),
@ -301,6 +334,54 @@ mod tests {
let _proof = computation.setup_prove_verify();
}
#[test]
fn identity() {
let program: Prog<FieldPrime> = Prog {
main: Function {
id: String::from("main"),
arguments: vec![FlatVariable::new(0)],
returns: vec![FlatVariable::public(0)],
statements: vec![Statement::Constraint(
FlatVariable::new(0).into(),
FlatVariable::public(0).into(),
)],
},
private: vec![true],
};
let witness = program
.clone()
.execute::<FieldPrime>(&vec![FieldPrime::from(0)])
.unwrap();
let computation = Computation::with_witness(program, witness);
let _proof = computation.setup_prove_verify();
}
#[test]
fn public_identity() {
let program: Prog<FieldPrime> = Prog {
main: Function {
id: String::from("main"),
arguments: vec![FlatVariable::new(0)],
returns: vec![FlatVariable::public(0)],
statements: vec![Statement::Constraint(
FlatVariable::new(0).into(),
FlatVariable::public(0).into(),
)],
},
private: vec![false],
};
let witness = program
.clone()
.execute::<FieldPrime>(&vec![FieldPrime::from(0)])
.unwrap();
let computation = Computation::with_witness(program, witness);
let _proof = computation.setup_prove_verify();
}
}
mod serialize {

View file

@ -18,7 +18,11 @@ impl<T: Field> From<FlatFunction<T>> for Function<T> {
Function {
id: flat_function.id,
arguments: flat_function.arguments.into_iter().map(|p| p.id).collect(),
returns: return_expressions.into_iter().map(|e| e.into()).collect(),
returns: return_expressions
.iter()
.enumerate()
.map(|(index, _)| FlatVariable::public(index))
.collect(),
statements: flat_function
.statements
.into_iter()
@ -26,6 +30,17 @@ impl<T: Field> From<FlatFunction<T>> for Function<T> {
FlatStatement::Return(..) => None,
s => Some(s.into()),
})
.chain(
return_expressions
.into_iter()
.enumerate()
.map(|(index, expression)| {
Statement::Constraint(
expression.into(),
FlatVariable::public(index).into(),
)
}),
)
.collect(),
}
}
@ -43,25 +58,8 @@ impl<T: Field> From<FlatProg<T>> for Prog<T> {
// get the interface of the program, ie which inputs are private and public
let private = main.arguments.iter().map(|p| p.private).collect();
// convert the main function to this IR for functions
let main: Function<T> = main.into();
let main = main.into();
// contrary to other functions, we need to make sure that return values are identifiers, so we define new (public) variables
let definitions =
main.returns.iter().enumerate().map(|(index, e)| {
Statement::Constraint(e.clone(), FlatVariable::public(index).into())
});
// update the main function with the extra definition statements and replace the return values
let main = Function {
returns: (0..main.returns.len())
.map(|i| FlatVariable::public(i).into())
.collect(),
statements: main.statements.into_iter().chain(definitions).collect(),
..main
};
let main = Function::from(main);
Prog { private, main }
}
}

View file

@ -5,6 +5,21 @@ use zokrates_field::field::Field;
pub type ExecutionResult<T> = Result<Witness<T>, Error>;
#[derive(Serialize, Deserialize)]
pub struct WitnessVec<T: Field>(Vec<(FlatVariable, T)>);
impl<T: Field> From<Witness<T>> for WitnessVec<T> {
fn from(w: Witness<T>) -> WitnessVec<T> {
WitnessVec(w.0.into_iter().collect())
}
}
impl<T: Field> From<WitnessVec<T>> for Witness<T> {
fn from(w: WitnessVec<T>) -> Witness<T> {
Witness(w.0.into_iter().collect())
}
}
#[derive(Clone)]
pub struct Witness<T: Field>(pub BTreeMap<FlatVariable, T>);

View file

@ -6,7 +6,7 @@ use std::fmt;
use std::mem;
use zokrates_field::field::Field;
mod backend;
pub mod backend;
mod expression;
mod from_flat;
mod interpreter;
@ -14,8 +14,7 @@ mod interpreter;
use self::expression::LinComb;
use self::expression::QuadComb;
pub use self::interpreter::Error;
pub use self::interpreter::ExecutionResult;
pub use self::interpreter::{Error, ExecutionResult, Witness, WitnessVec};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum Statement<T: Field> {
@ -64,7 +63,7 @@ pub struct Function<T: Field> {
pub id: String,
pub statements: Vec<Statement<T>>,
pub arguments: Vec<FlatVariable>,
pub returns: Vec<QuadComb<T>>,
pub returns: Vec<FlatVariable>,
}
impl<T: Field> fmt::Display for Function<T> {

View file

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

View file

@ -0,0 +1,47 @@
use bellman::groth16::Parameters;
use ir;
use ir::backend::Computation;
use proof_system::Metadata;
use proof_system::ProofSystem;
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
use zokrates_field::field::FieldPrime;
pub struct G16 {}
impl ProofSystem for G16 {
fn setup(&self, program: ir::Prog<FieldPrime>, pk_path: &str, _vk_path: &str) -> Metadata {
let parameters = Computation::without_witness(program).setup();
let parameters_file = File::create(PathBuf::from(pk_path)).unwrap();
parameters.write(parameters_file).unwrap();
// TODO write pk, vk to files
Metadata {
offset: 42,
variables: vec![],
}
}
fn generate_proof(
&self,
program: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
_metadata: Metadata,
pk_path: &str,
proof_path: &str,
) -> bool {
let computation = Computation::with_witness(program, witness);
let parameters_file = File::open(PathBuf::from(pk_path)).unwrap();
let params = Parameters::read(parameters_file, true).unwrap();
let proof = computation.prove(params);
let proof_file = File::create(PathBuf::from(proof_path)).unwrap();
proof.write(proof_file).unwrap();
true
}
fn export_solidity_verifier(&self, reader: BufReader<File>) -> String {
unimplemented!()
}
}

View file

@ -1,11 +1,11 @@
extern crate libc;
use self::libc::{c_char, c_int, uint8_t};
use flat_absy::flat_variable::FlatVariable;
use ir;
use proof_system::utils::{
prepare_generate_proof, prepare_setup, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB,
};
use proof_system::ProofSystem;
use proof_system::{Metadata, ProofSystem};
use regex::Regex;
use std::fs::File;
use std::io::{BufRead, BufReader};
@ -46,16 +46,7 @@ extern "C" {
}
impl ProofSystem for GM17 {
fn setup(
&self,
variables: Vec<FlatVariable>,
a: Vec<Vec<(usize, FieldPrime)>>,
b: Vec<Vec<(usize, FieldPrime)>>,
c: Vec<Vec<(usize, FieldPrime)>>,
num_inputs: usize,
pk_path: &str,
vk_path: &str,
) -> bool {
fn setup(&self, program: ir::Prog<FieldPrime>, pk_path: &str, vk_path: &str) -> Metadata {
let (
a_arr,
b_arr,
@ -68,7 +59,8 @@ impl ProofSystem for GM17 {
num_inputs,
pk_path_cstring,
vk_path_cstring,
) = prepare_setup(variables, a, b, c, num_inputs, pk_path, vk_path);
metadata,
) = prepare_setup(program, pk_path, vk_path);
unsafe {
_gm17_setup(
@ -83,32 +75,35 @@ impl ProofSystem for GM17 {
num_inputs as i32,
pk_path_cstring.as_ptr(),
vk_path_cstring.as_ptr(),
)
);
}
metadata
}
fn generate_proof(
&self,
_: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
metadata: Metadata,
pk_path: &str,
proof_path: &str,
publquery_inputs: Vec<FieldPrime>,
private_inputs: Vec<FieldPrime>,
) -> bool {
let (
pk_path_cstring,
proof_path_cstring,
publquery_inputs_arr,
publquery_inputs_length,
public_inputs_arr,
public_inputs_length,
private_inputs_arr,
private_inputs_length,
) = prepare_generate_proof(pk_path, proof_path, publquery_inputs, private_inputs);
) = prepare_generate_proof(pk_path, proof_path, witness, metadata);
unsafe {
_gm17_generate_proof(
pk_path_cstring.as_ptr(),
proof_path_cstring.as_ptr(),
publquery_inputs_arr[0].as_ptr(),
publquery_inputs_length as i32,
public_inputs_arr[0].as_ptr(),
public_inputs_length as i32,
private_inputs_arr[0].as_ptr(),
private_inputs_length as i32,
)

View file

@ -1,5 +1,11 @@
mod g16;
#[cfg(feature = "libsnark")]
mod gm17;
#[cfg(feature = "libsnark")]
mod pghr13;
pub use self::g16::G16;
#[cfg(feature = "libsnark")]
pub use self::gm17::GM17;
#[cfg(feature = "libsnark")]
pub use self::pghr13::PGHR13;

View file

@ -1,11 +1,11 @@
extern crate libc;
use self::libc::{c_char, c_int, uint8_t};
use flat_absy::flat_variable::FlatVariable;
use ir;
use proof_system::utils::{
prepare_generate_proof, prepare_setup, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB,
};
use proof_system::ProofSystem;
use proof_system::{Metadata, ProofSystem};
use regex::Regex;
use std::fs::File;
@ -47,16 +47,7 @@ extern "C" {
}
impl ProofSystem for PGHR13 {
fn setup(
&self,
variables: Vec<FlatVariable>,
a: Vec<Vec<(usize, FieldPrime)>>,
b: Vec<Vec<(usize, FieldPrime)>>,
c: Vec<Vec<(usize, FieldPrime)>>,
num_inputs: usize,
pk_path: &str,
vk_path: &str,
) -> bool {
fn setup(&self, program: ir::Prog<FieldPrime>, pk_path: &str, vk_path: &str) -> Metadata {
let (
a_arr,
b_arr,
@ -69,7 +60,8 @@ impl ProofSystem for PGHR13 {
num_inputs,
pk_path_cstring,
vk_path_cstring,
) = prepare_setup(variables, a, b, c, num_inputs, pk_path, vk_path);
metadata,
) = prepare_setup(program, pk_path, vk_path);
unsafe {
_pghr13_setup(
@ -84,16 +76,19 @@ impl ProofSystem for PGHR13 {
num_inputs as i32,
pk_path_cstring.as_ptr(),
vk_path_cstring.as_ptr(),
)
);
}
metadata
}
fn generate_proof(
&self,
_: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
metadata: Metadata,
pk_path: &str,
proof_path: &str,
public_inputs: Vec<FieldPrime>,
private_inputs: Vec<FieldPrime>,
) -> bool {
let (
pk_path_cstring,
@ -102,7 +97,7 @@ impl ProofSystem for PGHR13 {
public_inputs_length,
private_inputs_arr,
private_inputs_length,
) = prepare_generate_proof(pk_path, proof_path, public_inputs, private_inputs);
) = prepare_generate_proof(pk_path, proof_path, witness, metadata);
unsafe {
_pghr13_generate_proof(

View file

@ -1,33 +1,37 @@
mod bn128;
#[cfg(feature = "libsnark")]
mod utils;
use flat_absy::flat_variable::FlatVariable;
use std::fs::File;
use zokrates_field::field::FieldPrime;
pub use self::bn128::G16;
#[cfg(feature = "libsnark")]
pub use self::bn128::GM17;
#[cfg(feature = "libsnark")]
pub use self::bn128::PGHR13;
use flat_absy::flat_variable::FlatVariable;
use ir;
use std::io::BufReader;
pub trait ProofSystem {
fn setup(
&self,
variables: Vec<FlatVariable>,
a: Vec<Vec<(usize, FieldPrime)>>,
b: Vec<Vec<(usize, FieldPrime)>>,
c: Vec<Vec<(usize, FieldPrime)>>,
num_inputs: usize,
pk_path: &str,
vk_path: &str,
) -> bool;
fn setup(&self, program: ir::Prog<FieldPrime>, pk_path: &str, vk_path: &str) -> Metadata;
fn generate_proof(
&self,
program: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
metadata: Metadata,
pk_path: &str,
proof_path: &str,
public_inputs: Vec<FieldPrime>,
private_inputs: Vec<FieldPrime>,
) -> bool;
fn export_solidity_verifier(&self, reader: BufReader<File>) -> String;
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Metadata {
offset: usize,
variables: Vec<FlatVariable>,
}

View file

@ -1,4 +1,6 @@
use flat_absy::flat_variable::FlatVariable;
use ir;
use proof_system::Metadata;
use std::cmp::max;
use std::ffi::CString;
use zokrates_field::field::Field;
@ -15,11 +17,7 @@ fn vec_as_u8_32_array(vec: &Vec<u8>) -> [u8; 32] {
// proof-system-independent preparation for the setup phase
pub fn prepare_setup<T: Field>(
variables: Vec<FlatVariable>,
a: Vec<Vec<(usize, T)>>,
b: Vec<Vec<(usize, T)>>,
c: Vec<Vec<(usize, T)>>,
num_inputs: usize,
program: ir::Prog<T>,
pk_path: &str,
vk_path: &str,
) -> (
@ -34,10 +32,21 @@ pub fn prepare_setup<T: Field>(
usize,
CString,
CString,
Metadata,
) {
// transform to R1CS
let (variables, public_variables_count, a, b, c) = ir::r1cs_program(program);
let num_inputs = public_variables_count - 1;
let num_constraints = a.len();
let num_variables = variables.len();
let metadata = Metadata {
offset: public_variables_count,
variables,
};
// Create single A,B,C vectors of tuples (constraint_number, variable_id, variable_value)
let mut a_vec = vec![];
let mut b_vec = vec![];
@ -142,6 +151,7 @@ pub fn prepare_setup<T: Field>(
num_inputs,
pk_path_cstring,
vk_path_cstring,
metadata,
)
}
@ -149,9 +159,19 @@ pub fn prepare_setup<T: Field>(
pub fn prepare_generate_proof<T: Field>(
pk_path: &str,
proof_path: &str,
public_inputs: Vec<T>,
private_inputs: Vec<T>,
witness: ir::Witness<T>,
metadata: Metadata,
) -> (CString, CString, Vec<[u8; 32]>, usize, Vec<[u8; 32]>, usize) {
let witness: Vec<_> = metadata
.variables
.iter()
.map(|x| witness.0[x].clone())
.collect();
// split witness into public and private inputs at offset
let mut public_inputs: Vec<_> = witness.clone();
let private_inputs: Vec<_> = public_inputs.split_off(metadata.offset);
let pk_path_cstring = CString::new(pk_path).unwrap();
let proof_path_cstring = CString::new(proof_path).unwrap();

View file

@ -1,30 +0,0 @@
use zokrates_field::field::Field;
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Debug)]
pub struct Constraints<T: Field> {
pub constraints: Vec<Constraint<T>>,
}
impl<T: Field> Constraints<T> {
pub fn none() -> Constraints<T> {
Constraints {
constraints: vec![],
}
}
pub fn boolean() -> Constraints<T> {
Constraints {
constraints: vec![Constraint {
a: box [T::from(1)],
b: box [T::from(1)],
c: box [T::from(1)],
}],
}
}
}
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Debug)]
pub struct Constraint<T: Field> {
pub a: Box<[T]>,
pub b: Box<[T]>,
pub c: Box<[T]>,
}

View file

@ -3,8 +3,6 @@ use flat_absy::flat_parameter::FlatParameter;
use flat_absy::flat_variable::FlatVariable;
use flat_absy::*;
use helpers::{DirectiveStatement, Helper};
use reduce::Reduce;
use types::constraints::Constraint;
use types::signature::Signature;
use types::Type;
use zokrates_field::field::Field;
@ -167,94 +165,24 @@ pub fn cast<T: Field>(from: &Type, to: &Type) -> FlatFunction<T> {
})
.collect();
let directive_inputs = (0..from.get_primitive_count())
let binding_inputs: Vec<_> = (0..from.get_primitive_count())
.map(|index| use_variable(&mut bijection, format!("i{}", index), &mut counter))
.collect();
let directive_outputs: Vec<FlatVariable> = (0..to.get_primitive_count())
let binding_outputs: Vec<FlatVariable> = (0..to.get_primitive_count())
.map(|index| use_variable(&mut bijection, format!("o{}", index), &mut counter))
.collect();
let constraints = to.get_constraints::<T>().constraints;
let intermediate_variables = match constraints.len() {
0 => vec![],
_ => constraints[0]
.a
.iter()
.enumerate()
.map(|(_, index)| use_variable(&mut bijection, format!("inter{}", index), &mut counter))
.collect(),
};
let conditions: Vec<FlatStatement<T>> = to
.get_constraints()
.constraints
let outputs = binding_outputs
.iter()
.map(|constraint: &Constraint<T>| {
let rhs_a = match constraint
.a
.iter()
.enumerate()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val.clone()),
box FlatExpression::Identifier(intermediate_variables[key]),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
let rhs_b = match constraint
.b
.iter()
.enumerate()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val.clone()),
box FlatExpression::Identifier(intermediate_variables[key]),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
let lhs = match constraint
.c
.iter()
.enumerate()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val.clone()),
box FlatExpression::Identifier(intermediate_variables[key]),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
})
.map(|o| FlatExpression::Identifier(o.clone()))
.collect();
let helper = match (from, to) {
(Type::Boolean, Type::FieldElement) => Helper::identity(),
(Type::FieldElement, Type::Boolean) => Helper::identity(),
let bindings: Vec<_> = match (from, to) {
(Type::Boolean, Type::FieldElement) => binding_outputs
.into_iter()
.zip(binding_inputs.into_iter())
.map(|(o, i)| FlatStatement::Definition(o, i.into()))
.collect(),
_ => panic!(format!("can't cast {} to {}", from, to)),
};
@ -263,26 +191,13 @@ pub fn cast<T: Field>(from: &Type, to: &Type) -> FlatFunction<T> {
outputs: vec![to.clone()],
};
let outputs = directive_outputs
.iter()
.map(|o| FlatExpression::Identifier(o.clone()))
let statements = bindings
.into_iter()
.chain(std::iter::once(FlatStatement::Return(FlatExpressionList {
expressions: outputs,
})))
.collect();
let mut statements = conditions;
statements.insert(
0,
FlatStatement::Directive(DirectiveStatement::new(
directive_outputs,
helper,
directive_inputs,
)),
);
statements.push(FlatStatement::Return(FlatExpressionList {
expressions: outputs,
}));
FlatFunction {
id: format!("_{}_to_{}", from, to),
arguments,
@ -300,32 +215,6 @@ mod tests {
mod cast {
use super::*;
#[test]
fn field_to_bool() {
let f2b: FlatFunction<FieldPrime> = cast(&Type::FieldElement, &Type::Boolean);
assert_eq!(f2b.id, String::from("_field_to_bool"));
assert_eq!(
f2b.arguments,
vec![FlatParameter::private(FlatVariable::new(0))]
);
assert_eq!(f2b.statements.len(), 3); // 1 directive, 1 constraint, 1 return
assert_eq!(
f2b.statements[0],
FlatStatement::Directive(DirectiveStatement::new(
vec![FlatVariable::new(1)],
Helper::identity(),
vec![FlatVariable::new(0)]
))
);
assert_eq!(
f2b.statements[2],
FlatStatement::Return(FlatExpressionList {
expressions: vec![FlatExpression::Identifier(FlatVariable::new(1))]
})
);
assert_eq!(f2b.signature.outputs.len(), 1);
}
#[test]
fn bool_to_field() {
let b2f: FlatFunction<FieldPrime> = cast(&Type::Boolean, &Type::FieldElement);
@ -334,14 +223,10 @@ mod tests {
b2f.arguments,
vec![FlatParameter::private(FlatVariable::new(0))]
);
assert_eq!(b2f.statements.len(), 2); // 1 directive, 1 return
assert_eq!(b2f.statements.len(), 2); // 1 definition, 1 return
assert_eq!(
b2f.statements[0],
FlatStatement::Directive(DirectiveStatement::new(
vec![FlatVariable::new(1)],
Helper::identity(),
vec![FlatVariable::new(0)]
))
FlatStatement::Definition(FlatVariable::new(1), FlatVariable::new(0).into())
);
assert_eq!(
b2f.statements[1],

View file

@ -1,9 +1,6 @@
use std::fmt;
use types::constraints::Constraints;
pub use types::signature::Signature;
use zokrates_field::field::Field;
mod constraints;
pub mod conversions;
mod signature;
@ -35,14 +32,6 @@ impl fmt::Debug for Type {
}
impl Type {
fn get_constraints<T: Field>(&self) -> Constraints<T> {
match self {
Type::FieldElement => Constraints::none(),
Type::Boolean => Constraints::boolean(),
Type::FieldElementArray(_) => Type::FieldElement.get_constraints(),
}
}
// the number of field elements the type maps to
pub fn get_primitive_count(&self) -> usize {
match self {
@ -64,21 +53,11 @@ impl Type {
#[cfg(test)]
mod tests {
use super::*;
use zokrates_field::field::FieldPrime;
#[test]
fn array() {
let t = Type::FieldElementArray(42);
assert_eq!(t.get_primitive_count(), 42);
assert_eq!(t.get_constraints::<FieldPrime>(), Constraints::none());
assert_eq!(t.to_slug(), "f[42]");
}
// #[test]
// fn array_of_arrays() {
// let t = Type::FieldElementArray(42, box Type::FieldElementArray(33, box Type::Boolean));
// assert_eq!(t.get_primitive_count(), 1);
// assert_eq!(t.get_constraints::<FieldPrime>(), Constraints::boolean());
// assert_eq!(t.to_slug(), "[]");
// }
}