cli commands in separate files
This commit is contained in:
parent
d94c44a4b8
commit
b06acb55e4
16 changed files with 1193 additions and 1164 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2050,6 +2050,8 @@ dependencies = [
|
|||
"dirs",
|
||||
"fs_extra",
|
||||
"glob 0.2.11",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"tempdir",
|
||||
|
|
|
@ -22,6 +22,8 @@ zokrates_core = { version = "0.5", path = "../zokrates_core", default-features =
|
|||
zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"}
|
||||
serde_json = "1.0"
|
||||
dirs = "3.0.1"
|
||||
log = "0.4.11"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
glob = "0.2.11"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,24 @@
|
|||
pub const FLATTENED_CODE_DEFAULT_PATH: &str = "out";
|
||||
pub const ABI_SPEC_DEFAULT_PATH: &str = "abi.json";
|
||||
pub const VERIFICATION_KEY_DEFAULT_PATH: &str = "verification.key";
|
||||
pub const PROVING_KEY_DEFAULT_PATH: &str = "proving.key";
|
||||
pub const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol";
|
||||
pub const WITNESS_DEFAULT_PATH: &str = "witness";
|
||||
pub const JSON_PROOF_PATH: &str = "proof.json";
|
||||
|
||||
pub const BELLMAN: &str = "bellman";
|
||||
pub const LIBSNARK: &str = "libsnark";
|
||||
pub const ARK: &str = "ark";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref DEFAULT_STDLIB_PATH: String = dirs::home_dir()
|
||||
.map(|p| p.join(".zokrates/stdlib"))
|
||||
.unwrap()
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub const BACKENDS: &[&str] = if cfg!(feature = "libsnark") {
|
||||
if cfg!(feature = "ark") {
|
||||
if cfg!(feature = "bellman") {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use core::convert::TryFrom;
|
||||
|
||||
use crate::constants::*;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CurveParameter {
|
||||
|
|
94
zokrates_cli/src/ops/check.rs
Normal file
94
zokrates_cli/src/ops/check.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::CurveParameter;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read};
|
||||
use std::path::PathBuf;
|
||||
use zokrates_core::compile::{check, CompileError};
|
||||
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field};
|
||||
use zokrates_fs_resolver::FileSystemResolver;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("check")
|
||||
.about("Checks a program for errors")
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the source code")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("stdlib-path")
|
||||
.long("stdlib-path")
|
||||
.help("Path to the standard library")
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.env("ZOKRATES_STDLIB")
|
||||
.default_value(constants::DEFAULT_STDLIB_PATH.as_str()),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("curve")
|
||||
.short("c")
|
||||
.long("curve")
|
||||
.help("Curve to be used in the compilation")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::CURVES)
|
||||
.default_value(constants::BN128),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let curve = CurveParameter::try_from(sub_matches.value_of("curve").unwrap())?;
|
||||
match curve {
|
||||
CurveParameter::Bn128 => cli_check::<Bn128Field>(sub_matches),
|
||||
CurveParameter::Bls12_377 => cli_check::<Bls12_377Field>(sub_matches),
|
||||
CurveParameter::Bls12_381 => cli_check::<Bls12_381Field>(sub_matches),
|
||||
CurveParameter::Bw6_761 => cli_check::<Bw6_761Field>(sub_matches),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
println!("Checking {}\n", sub_matches.value_of("input").unwrap());
|
||||
let path = PathBuf::from(sub_matches.value_of("input").unwrap());
|
||||
|
||||
let file = File::open(path.clone())
|
||||
.map_err(|why| format!("Couldn't open input file {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut source = String::new();
|
||||
reader.read_to_string(&mut source).unwrap();
|
||||
|
||||
let fmt_error = |e: &CompileError| {
|
||||
let file = e.file().canonicalize().unwrap();
|
||||
format!(
|
||||
"{}:{}",
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
};
|
||||
|
||||
let stdlib_path = sub_matches.value_of("stdlib-path").unwrap();
|
||||
let resolver = FileSystemResolver::with_stdlib_root(stdlib_path);
|
||||
|
||||
let _ = check::<T, _>(source, path, Some(&resolver)).map_err(|e| {
|
||||
format!(
|
||||
"Check failed:\n\n{}",
|
||||
e.0.iter()
|
||||
.map(|e| fmt_error(e))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\n")
|
||||
)
|
||||
})?;
|
||||
|
||||
println!("Program checked, no errors found.");
|
||||
|
||||
Ok(())
|
||||
}
|
162
zokrates_cli/src/ops/compile.rs
Normal file
162
zokrates_cli/src/ops/compile.rs
Normal file
|
@ -0,0 +1,162 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::CurveParameter;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use serde_json::to_writer_pretty;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use zokrates_core::compile::{compile, CompilationArtifacts, CompileError};
|
||||
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field};
|
||||
use zokrates_fs_resolver::FileSystemResolver;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("compile")
|
||||
.about("Compiles into flattened conditions. Produces two files: human-readable '.ztf' file for debugging and binary file")
|
||||
.arg(Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the source code")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
).arg(Arg::with_name("stdlib-path")
|
||||
.long("stdlib-path")
|
||||
.help("Path to the standard library")
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.env("ZOKRATES_STDLIB")
|
||||
.default_value(constants::DEFAULT_STDLIB_PATH.as_str())
|
||||
).arg(Arg::with_name("abi_spec")
|
||||
.short("s")
|
||||
.long("abi_spec")
|
||||
.help("Path of the ABI specification")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::ABI_SPEC_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("output")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.help("Path of the output binary")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::FLATTENED_CODE_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("curve")
|
||||
.short("c")
|
||||
.long("curve")
|
||||
.help("Curve to be used in the compilation")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::CURVES)
|
||||
.default_value(constants::BN128)
|
||||
).arg(Arg::with_name("light")
|
||||
.long("light")
|
||||
.help("Skip logs and human readable output")
|
||||
.required(false)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let curve = CurveParameter::try_from(sub_matches.value_of("curve").unwrap())?;
|
||||
match curve {
|
||||
CurveParameter::Bn128 => cli_compile::<Bn128Field>(sub_matches),
|
||||
CurveParameter::Bls12_377 => cli_compile::<Bls12_377Field>(sub_matches),
|
||||
CurveParameter::Bls12_381 => cli_compile::<Bls12_381Field>(sub_matches),
|
||||
CurveParameter::Bw6_761 => cli_compile::<Bw6_761Field>(sub_matches),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
println!("Compiling {}\n", sub_matches.value_of("input").unwrap());
|
||||
|
||||
let path = PathBuf::from(sub_matches.value_of("input").unwrap());
|
||||
let light = sub_matches.occurrences_of("light") > 0;
|
||||
let bin_output_path = Path::new(sub_matches.value_of("output").unwrap());
|
||||
let abi_spec_path = Path::new(sub_matches.value_of("abi_spec").unwrap());
|
||||
let hr_output_path = bin_output_path.to_path_buf().with_extension("ztf");
|
||||
|
||||
let file = File::open(path.clone())
|
||||
.map_err(|why| format!("Couldn't open input file {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut source = String::new();
|
||||
reader.read_to_string(&mut source).unwrap();
|
||||
|
||||
let fmt_error = |e: &CompileError| {
|
||||
let file = e.file().canonicalize().unwrap();
|
||||
format!(
|
||||
"{}:{}",
|
||||
file.strip_prefix(std::env::current_dir().unwrap())
|
||||
.unwrap_or(file.as_path())
|
||||
.display(),
|
||||
e.value()
|
||||
)
|
||||
};
|
||||
|
||||
let stdlib_path = sub_matches.value_of("stdlib-path").unwrap();
|
||||
let resolver = FileSystemResolver::with_stdlib_root(stdlib_path);
|
||||
|
||||
let artifacts: CompilationArtifacts<T> =
|
||||
compile(source, path, Some(&resolver)).map_err(|e| {
|
||||
format!(
|
||||
"Compilation failed:\n\n{}",
|
||||
e.0.iter()
|
||||
.map(|e| fmt_error(e))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\n")
|
||||
)
|
||||
})?;
|
||||
|
||||
let program_flattened = artifacts.prog();
|
||||
|
||||
// number of constraints the flattened program will translate to.
|
||||
let num_constraints = program_flattened.constraint_count();
|
||||
|
||||
// serialize flattened program and write to binary file
|
||||
let bin_output_file = File::create(&bin_output_path)
|
||||
.map_err(|why| format!("Couldn't create {}: {}", bin_output_path.display(), why))?;
|
||||
|
||||
let mut writer = BufWriter::new(bin_output_file);
|
||||
|
||||
program_flattened.serialize(&mut writer);
|
||||
|
||||
// serialize ABI spec and write to JSON file
|
||||
let abi_spec_file = File::create(&abi_spec_path)
|
||||
.map_err(|why| format!("Couldn't create {}: {}", abi_spec_path.display(), why))?;
|
||||
|
||||
let abi = artifacts.abi();
|
||||
|
||||
let mut writer = BufWriter::new(abi_spec_file);
|
||||
|
||||
to_writer_pretty(&mut writer, &abi).map_err(|_| "Unable to write data to file.".to_string())?;
|
||||
|
||||
if !light {
|
||||
// write human-readable output file
|
||||
let hr_output_file = File::create(&hr_output_path)
|
||||
.map_err(|why| format!("Couldn't create {}: {}", hr_output_path.display(), why))?;
|
||||
|
||||
let mut hrofb = BufWriter::new(hr_output_file);
|
||||
write!(&mut hrofb, "{}\n", program_flattened)
|
||||
.map_err(|_| "Unable to write data to file".to_string())?;
|
||||
hrofb
|
||||
.flush()
|
||||
.map_err(|_| "Unable to flush buffer".to_string())?;
|
||||
}
|
||||
|
||||
if !light {
|
||||
// debugging output
|
||||
println!("Compiled program:\n{}", program_flattened);
|
||||
}
|
||||
|
||||
println!("Compiled code written to '{}'", bin_output_path.display());
|
||||
|
||||
if !light {
|
||||
println!("Human readable code to '{}'", hr_output_path.display());
|
||||
}
|
||||
|
||||
println!("Number of constraints: {}", num_constraints);
|
||||
Ok(())
|
||||
}
|
189
zokrates_cli/src/ops/compute_witness.rs
Normal file
189
zokrates_cli/src/ops/compute_witness.rs
Normal file
|
@ -0,0 +1,189 @@
|
|||
use crate::constants::{ABI_SPEC_DEFAULT_PATH, FLATTENED_CODE_DEFAULT_PATH, WITNESS_DEFAULT_PATH};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use serde_json::from_reader;
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, BufReader, BufWriter, Read};
|
||||
use std::path::Path;
|
||||
use zokrates_abi::Encode;
|
||||
use zokrates_core::ir;
|
||||
use zokrates_core::ir::ProgEnum;
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
use zokrates_core::typed_absy::{Signature, Type};
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("compute-witness")
|
||||
.about("Calculates a witness for a given constraint system")
|
||||
.arg(Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the binary")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("abi_spec")
|
||||
.short("s")
|
||||
.long("abi_spec")
|
||||
.help("Path of the ABI specification")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(ABI_SPEC_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("output")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.help("Path of the output file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(WITNESS_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("arguments")
|
||||
.short("a")
|
||||
.long("arguments")
|
||||
.help("Arguments for the program's main function, when not using ABI encoding. Expects a space-separated list of field elements like `-a 1 2 3`")
|
||||
.takes_value(true)
|
||||
.multiple(true) // allows multiple values
|
||||
.required(false)
|
||||
.conflicts_with("abi")
|
||||
.conflicts_with("stdin")
|
||||
).arg(Arg::with_name("abi")
|
||||
.long("abi")
|
||||
.help("Use ABI encoding. Arguments are expected as a JSON object as specified at zokrates.github.io/toolbox/abi.html#abi-input-format")
|
||||
.conflicts_with("arguments")
|
||||
.required(false)
|
||||
).arg(Arg::with_name("stdin")
|
||||
.long("stdin")
|
||||
.help("Read arguments from stdin")
|
||||
.conflicts_with("arguments")
|
||||
.required(false)
|
||||
).arg(Arg::with_name("light")
|
||||
.long("light")
|
||||
.help("Skip logging the human-readable program")
|
||||
.required(false)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
// read compiled program
|
||||
let path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let file =
|
||||
File::open(&path).map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
match ProgEnum::deserialize(&mut reader)? {
|
||||
ProgEnum::Bn128Program(p) => cli_compute(p, sub_matches),
|
||||
ProgEnum::Bls12_377Program(p) => cli_compute(p, sub_matches),
|
||||
ProgEnum::Bls12_381Program(p) => cli_compute(p, sub_matches),
|
||||
ProgEnum::Bw6_761Program(p) => cli_compute(p, sub_matches),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_compute<T: Field>(ir_prog: ir::Prog<T>, sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
println!("Computing witness...");
|
||||
|
||||
// print deserialized flattened program
|
||||
if !sub_matches.is_present("light") {
|
||||
println!("{}", ir_prog);
|
||||
}
|
||||
|
||||
let is_stdin = sub_matches.is_present("stdin");
|
||||
let is_abi = sub_matches.is_present("abi");
|
||||
|
||||
if !is_stdin && is_abi {
|
||||
return Err("ABI input as inline argument is not supported. Please use `--stdin`.".into());
|
||||
}
|
||||
|
||||
let signature = match is_abi {
|
||||
true => {
|
||||
let path = Path::new(sub_matches.value_of("abi_spec").unwrap());
|
||||
let file = File::open(&path)
|
||||
.map_err(|why| format!("couldn't open {}: {}", path.display(), why))?;
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
let abi: Abi = from_reader(&mut reader).map_err(|why| why.to_string())?;
|
||||
|
||||
abi.signature()
|
||||
}
|
||||
false => Signature::new()
|
||||
.inputs(vec![Type::FieldElement; ir_prog.main.arguments.len()])
|
||||
.outputs(vec![Type::FieldElement; ir_prog.main.returns.len()]),
|
||||
};
|
||||
|
||||
use zokrates_abi::Inputs;
|
||||
|
||||
// get arguments
|
||||
let arguments = match is_stdin {
|
||||
// take inline arguments
|
||||
false => {
|
||||
let arguments = sub_matches.values_of("arguments");
|
||||
arguments
|
||||
.map(|a| {
|
||||
a.map(|x| T::try_from_dec_str(x).map_err(|_| x.to_string()))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.unwrap_or(Ok(vec![]))
|
||||
.map(|v| Inputs::Raw(v))
|
||||
}
|
||||
// take stdin arguments
|
||||
true => {
|
||||
let mut stdin = stdin();
|
||||
let mut input = String::new();
|
||||
|
||||
match is_abi {
|
||||
true => match stdin.read_to_string(&mut input) {
|
||||
Ok(_) => {
|
||||
use zokrates_abi::parse_strict;
|
||||
|
||||
parse_strict(&input, signature.inputs)
|
||||
.map(|parsed| Inputs::Abi(parsed))
|
||||
.map_err(|why| why.to_string())
|
||||
}
|
||||
Err(_) => Err(String::from("???")),
|
||||
},
|
||||
false => match ir_prog.arguments_count() {
|
||||
0 => Ok(Inputs::Raw(vec![])),
|
||||
_ => match stdin.read_to_string(&mut input) {
|
||||
Ok(_) => {
|
||||
input.retain(|x| x != '\n');
|
||||
input
|
||||
.split(" ")
|
||||
.map(|x| T::try_from_dec_str(x).map_err(|_| x.to_string()))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map(|v| Inputs::Raw(v))
|
||||
}
|
||||
Err(_) => Err(String::from("???")),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
.map_err(|e| format!("Could not parse argument: {}", e))?;
|
||||
|
||||
let interpreter = ir::Interpreter::default();
|
||||
|
||||
let witness = interpreter
|
||||
.execute(&ir_prog, &arguments.encode())
|
||||
.map_err(|e| format!("Execution failed: {}", e))?;
|
||||
|
||||
use zokrates_abi::Decode;
|
||||
|
||||
let results_json_value: serde_json::Value =
|
||||
zokrates_abi::CheckedValues::decode(witness.return_values(), signature.outputs).into();
|
||||
|
||||
println!("\nWitness: \n\n{}", results_json_value);
|
||||
|
||||
// write witness to file
|
||||
let output_path = Path::new(sub_matches.value_of("output").unwrap());
|
||||
let output_file = File::create(&output_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?;
|
||||
|
||||
let writer = BufWriter::new(output_file);
|
||||
|
||||
witness
|
||||
.write(writer)
|
||||
.map_err(|why| format!("could not save witness: {:?}", why))?;
|
||||
|
||||
Ok(())
|
||||
}
|
119
zokrates_cli/src/ops/export_verifier.rs
Normal file
119
zokrates_cli/src/ops/export_verifier.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::{CurveParameter, SchemeParameter};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter, Write};
|
||||
use std::path::Path;
|
||||
use zokrates_core::proof_system::*;
|
||||
use zokrates_field::Bn128Field;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("export-verifier")
|
||||
.about("Exports a verifier as Solidity smart contract")
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the verifier")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::VERIFICATION_KEY_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("output")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.help("Path of the output file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::VERIFICATION_CONTRACT_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("curve")
|
||||
.short("c")
|
||||
.long("curve")
|
||||
.help("Curve to be used to export the verifier")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::CURVES)
|
||||
.default_value(constants::BN128),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use to export the verifier")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::SCHEMES)
|
||||
.default_value(constants::G16),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("solidity-abi")
|
||||
.short("a")
|
||||
.long("solidity-abi")
|
||||
.help("Flag for setting the version of the ABI Encoder used in the contract")
|
||||
.takes_value(true)
|
||||
.possible_values(&["v1", "v2"])
|
||||
.default_value("v1")
|
||||
.required(false),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let curve = sub_matches.value_of("curve").unwrap();
|
||||
let scheme = sub_matches.value_of("proving-scheme").unwrap();
|
||||
|
||||
let curve_parameter = CurveParameter::try_from(curve)?;
|
||||
let scheme_parameter = SchemeParameter::try_from(scheme)?;
|
||||
|
||||
match (curve_parameter, scheme_parameter) {
|
||||
(CurveParameter::Bn128, SchemeParameter::G16) => {
|
||||
cli_export_verifier::<Bn128Field, G16>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
cli_export_verifier::<Bn128Field, GM17>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
cli_export_verifier::<Bn128Field, PGHR13>(sub_matches)
|
||||
}
|
||||
_ => Err(format!("Could not export verifier with given parameters (curve: {}, scheme: {}): not supported", curve, scheme))
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_export_verifier<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T>>(
|
||||
sub_matches: &ArgMatches,
|
||||
) -> Result<(), String> {
|
||||
println!("Exporting verifier...");
|
||||
|
||||
// read vk file
|
||||
let input_path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let input_file = File::open(&input_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", input_path.display(), why))?;
|
||||
let reader = BufReader::new(input_file);
|
||||
|
||||
let vk = serde_json::from_reader(reader)
|
||||
.map_err(|why| format!("Couldn't deserialize verifying key: {}", why))?;
|
||||
|
||||
let abi = SolidityAbi::from(sub_matches.value_of("solidity-abi").unwrap())?;
|
||||
|
||||
let verifier = S::export_solidity_verifier(vk, abi);
|
||||
|
||||
//write output file
|
||||
let output_path = Path::new(sub_matches.value_of("output").unwrap());
|
||||
let output_file = File::create(&output_path)
|
||||
.map_err(|why| format!("Couldn't create {}: {}", output_path.display(), why))?;
|
||||
|
||||
let mut writer = BufWriter::new(output_file);
|
||||
|
||||
writer
|
||||
.write_all(&verifier.as_bytes())
|
||||
.map_err(|_| "Failed writing output to file".to_string())?;
|
||||
|
||||
println!("Finished exporting verifier");
|
||||
Ok(())
|
||||
}
|
180
zokrates_cli/src/ops/generate_proof.rs
Normal file
180
zokrates_cli/src/ops/generate_proof.rs
Normal file
|
@ -0,0 +1,180 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::*;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
use std::path::Path;
|
||||
use zokrates_core::ir;
|
||||
use zokrates_core::ir::ProgEnum;
|
||||
#[cfg(feature = "ark")]
|
||||
use zokrates_core::proof_system::ark::Ark;
|
||||
#[cfg(feature = "bellman")]
|
||||
use zokrates_core::proof_system::bellman::Bellman;
|
||||
#[cfg(feature = "libsnark")]
|
||||
use zokrates_core::proof_system::libsnark::Libsnark;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
use zokrates_core::proof_system::*;
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("generate-proof")
|
||||
.about("Calculates a proof for a given constraint system and witness")
|
||||
.arg(
|
||||
Arg::with_name("witness")
|
||||
.short("w")
|
||||
.long("witness")
|
||||
.help("Path of the witness file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::WITNESS_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-key-path")
|
||||
.short("p")
|
||||
.long("proving-key-path")
|
||||
.help("Path of the proving key file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::PROVING_KEY_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proof-path")
|
||||
.short("j")
|
||||
.long("proof-path")
|
||||
.help("Path of the JSON proof file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::JSON_PROOF_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the binary")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::FLATTENED_CODE_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::BACKENDS)
|
||||
.default_value(constants::BELLMAN),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use to generate the proof")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::SCHEMES)
|
||||
.default_value(constants::G16),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let program_path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let program_file = File::open(&program_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", program_path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(program_file);
|
||||
let prog = ProgEnum::deserialize(&mut reader)?;
|
||||
|
||||
let parameters = Parameters::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(_) => constants::BN128,
|
||||
ProgEnum::Bls12_381Program(_) => constants::BLS12_381,
|
||||
ProgEnum::Bls12_377Program(_) => constants::BLS12_377,
|
||||
ProgEnum::Bw6_761Program(_) => constants::BW6_761,
|
||||
},
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match parameters {
|
||||
#[cfg(feature = "bellman")]
|
||||
Parameters(BackendParameter::Bellman, _, SchemeParameter::G16) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, G16, Bellman>(p, sub_matches),
|
||||
ProgEnum::Bls12_381Program(p) => cli_generate_proof::<_, G16, Bellman>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "ark")]
|
||||
Parameters(BackendParameter::Ark, _, SchemeParameter::GM17) => match prog {
|
||||
ProgEnum::Bls12_377Program(p) => cli_generate_proof::<_, GM17, Ark>(p, sub_matches),
|
||||
ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, GM17, Ark>(p, sub_matches),
|
||||
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17, Ark>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(p) => {
|
||||
cli_generate_proof::<_, GM17, Libsnark>(p, sub_matches)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(p) => {
|
||||
cli_generate_proof::<_, PGHR13, Libsnark>(p, sub_matches)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_generate_proof<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
||||
program: ir::Prog<T>,
|
||||
sub_matches: &ArgMatches,
|
||||
) -> Result<(), String> {
|
||||
println!("Generating proof...");
|
||||
|
||||
// deserialize witness
|
||||
let witness_path = Path::new(sub_matches.value_of("witness").unwrap());
|
||||
let witness_file = match File::open(&witness_path) {
|
||||
Ok(file) => file,
|
||||
Err(why) => panic!("Couldn't open {}: {}", witness_path.display(), why),
|
||||
};
|
||||
|
||||
let witness = ir::Witness::read(witness_file)
|
||||
.map_err(|why| format!("Could not load witness: {:?}", why))?;
|
||||
|
||||
let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap());
|
||||
let proof_path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
|
||||
let pk_file = File::open(&pk_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", pk_path.display(), why))?;
|
||||
|
||||
let mut pk: Vec<u8> = Vec::new();
|
||||
let mut pk_reader = BufReader::new(pk_file);
|
||||
pk_reader
|
||||
.read_to_end(&mut pk)
|
||||
.map_err(|why| format!("Couldn't read {}: {}", pk_path.display(), why))?;
|
||||
|
||||
let proof = B::generate_proof(program, witness, pk);
|
||||
let mut proof_file = File::create(proof_path).unwrap();
|
||||
|
||||
let proof = serde_json::to_string_pretty(&proof).unwrap();
|
||||
proof_file
|
||||
.write(proof.as_bytes())
|
||||
.map_err(|why| format!("Couldn't write to {}: {}", proof_path.display(), why))?;
|
||||
|
||||
println!("Proof:\n{}", format!("{}", proof));
|
||||
|
||||
Ok(())
|
||||
}
|
12
zokrates_cli/src/ops/mod.rs
Normal file
12
zokrates_cli/src/ops/mod.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
pub mod check;
|
||||
pub mod compile;
|
||||
pub mod compute_witness;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
pub mod export_verifier;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
pub mod generate_proof;
|
||||
pub mod print_proof;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
pub mod setup;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
pub mod verify;
|
68
zokrates_cli/src/ops/print_proof.rs
Normal file
68
zokrates_cli/src/ops/print_proof.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use crate::constants::JSON_PROOF_PATH;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use serde_json::Value;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("print-proof")
|
||||
.about("Prints proof in the chosen format")
|
||||
.arg(
|
||||
Arg::with_name("proof-path")
|
||||
.short("j")
|
||||
.long("proof-path")
|
||||
.help("Path of the JSON proof file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(JSON_PROOF_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("format")
|
||||
.short("f")
|
||||
.long("format")
|
||||
.value_name("FORMAT")
|
||||
.help("Format in which the proof should be printed")
|
||||
.takes_value(true)
|
||||
.possible_values(&["remix", "json"])
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let format = sub_matches.value_of("format").unwrap();
|
||||
let path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
|
||||
let file =
|
||||
File::open(&path).map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
|
||||
|
||||
let proof_object: Value = serde_json::from_reader(file).map_err(|why| format!("{:?}", why))?;
|
||||
|
||||
match format {
|
||||
"json" => {
|
||||
println!("~~~~~~~~ Copy the output below for valid ABIv2 format ~~~~~~~~");
|
||||
println!();
|
||||
print!("{}", proof_object["proof"]);
|
||||
print!(",");
|
||||
println!("{}", proof_object["inputs"]);
|
||||
println!();
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
}
|
||||
"remix" => {
|
||||
println!("~~~~~~~~ Copy the output below for valid ABIv1 format ~~~~~~~~");
|
||||
println!();
|
||||
|
||||
for (_, value) in proof_object["proof"].as_object().unwrap().iter() {
|
||||
print!("{}", value);
|
||||
print!(",");
|
||||
}
|
||||
|
||||
println!("{}", proof_object["inputs"]);
|
||||
println!();
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
172
zokrates_cli/src/ops/setup.rs
Normal file
172
zokrates_cli/src/ops/setup.rs
Normal file
|
@ -0,0 +1,172 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::*;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Write};
|
||||
use std::path::Path;
|
||||
use zokrates_core::ir;
|
||||
use zokrates_core::ir::ProgEnum;
|
||||
#[cfg(feature = "ark")]
|
||||
use zokrates_core::proof_system::ark::Ark;
|
||||
#[cfg(feature = "bellman")]
|
||||
use zokrates_core::proof_system::bellman::Bellman;
|
||||
#[cfg(feature = "libsnark")]
|
||||
use zokrates_core::proof_system::libsnark::Libsnark;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
use zokrates_core::proof_system::*;
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("setup")
|
||||
.about("Performs a trusted setup for a given constraint system")
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Path of the binary")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::FLATTENED_CODE_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-key-path")
|
||||
.short("p")
|
||||
.long("proving-key-path")
|
||||
.help("Path of the generated proving key file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::PROVING_KEY_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("verification-key-path")
|
||||
.short("v")
|
||||
.long("verification-key-path")
|
||||
.help("Path of the generated verification key file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::VERIFICATION_KEY_DEFAULT_PATH),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::BACKENDS)
|
||||
.default_value(constants::BELLMAN),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use in the setup")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::SCHEMES)
|
||||
.default_value(constants::G16),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("light")
|
||||
.long("light")
|
||||
.help("Skip logging the human-readable program and writing it to a file")
|
||||
.required(false),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
// read compiled program
|
||||
let path = Path::new(sub_matches.value_of("input").unwrap());
|
||||
let file =
|
||||
File::open(&path).map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let prog = ProgEnum::deserialize(&mut reader)?;
|
||||
|
||||
let parameters = Parameters::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(_) => constants::BN128,
|
||||
ProgEnum::Bls12_377Program(_) => constants::BLS12_377,
|
||||
ProgEnum::Bls12_381Program(_) => constants::BLS12_381,
|
||||
ProgEnum::Bw6_761Program(_) => constants::BW6_761,
|
||||
},
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match parameters {
|
||||
#[cfg(feature = "bellman")]
|
||||
Parameters(BackendParameter::Bellman, _, SchemeParameter::G16) => match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, G16, Bellman>(p, sub_matches),
|
||||
ProgEnum::Bls12_381Program(p) => cli_setup::<_, G16, Bellman>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "ark")]
|
||||
Parameters(BackendParameter::Ark, _, SchemeParameter::GM17) => match prog {
|
||||
ProgEnum::Bls12_377Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
|
||||
ProgEnum::Bw6_761Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17, Libsnark>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
match prog {
|
||||
ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13, Libsnark>(p, sub_matches),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_setup<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
||||
program: ir::Prog<T>,
|
||||
sub_matches: &ArgMatches,
|
||||
) -> Result<(), String> {
|
||||
println!("Performing setup...");
|
||||
|
||||
// print deserialized flattened program
|
||||
if !sub_matches.is_present("light") {
|
||||
println!("{}", program);
|
||||
}
|
||||
|
||||
// get paths for proving and verification keys
|
||||
let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap());
|
||||
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
|
||||
|
||||
// run setup phase
|
||||
let keypair = B::setup(program);
|
||||
|
||||
// write verification key
|
||||
let mut vk_file = File::create(vk_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", vk_path.display(), why))?;
|
||||
vk_file
|
||||
.write(
|
||||
serde_json::to_string_pretty(&keypair.vk)
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.map_err(|why| format!("couldn't write to {}: {}", vk_path.display(), why))?;
|
||||
|
||||
// write proving key
|
||||
let mut pk_file = File::create(pk_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", pk_path.display(), why))?;
|
||||
pk_file
|
||||
.write(keypair.pk.as_ref())
|
||||
.map_err(|why| format!("couldn't write to {}: {}", pk_path.display(), why))?;
|
||||
|
||||
println!("Setup completed.");
|
||||
|
||||
Ok(())
|
||||
}
|
133
zokrates_cli/src/ops/verify.rs
Normal file
133
zokrates_cli/src/ops/verify.rs
Normal file
|
@ -0,0 +1,133 @@
|
|||
use crate::constants;
|
||||
use crate::helpers::*;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "ark")]
|
||||
use zokrates_core::proof_system::ark::Ark;
|
||||
#[cfg(feature = "bellman")]
|
||||
use zokrates_core::proof_system::bellman::Bellman;
|
||||
#[cfg(feature = "libsnark")]
|
||||
use zokrates_core::proof_system::libsnark::Libsnark;
|
||||
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
|
||||
use zokrates_core::proof_system::*;
|
||||
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field};
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("verify")
|
||||
.about("Verifies a given proof with the given verification key")
|
||||
.arg(Arg::with_name("proof-path")
|
||||
.short("j")
|
||||
.long("proof-path")
|
||||
.help("Path of the JSON proof file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::JSON_PROOF_PATH)
|
||||
).arg(Arg::with_name("verification-key-path")
|
||||
.short("v")
|
||||
.long("verification-key-path")
|
||||
.help("Path of the generated verification key file")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(constants::VERIFICATION_KEY_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("backend")
|
||||
.short("b")
|
||||
.long("backend")
|
||||
.help("Backend to use")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::BACKENDS)
|
||||
.default_value(constants::BELLMAN)
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.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)
|
||||
.default_value(constants::G16)
|
||||
).arg(Arg::with_name("curve")
|
||||
.short("c")
|
||||
.long("curve")
|
||||
.help("Curve to be used in the verification")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::CURVES)
|
||||
.default_value(constants::BN128)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let parameters = Parameters::try_from((
|
||||
sub_matches.value_of("backend").unwrap(),
|
||||
sub_matches.value_of("curve").unwrap(),
|
||||
sub_matches.value_of("proving-scheme").unwrap(),
|
||||
))?;
|
||||
|
||||
match parameters {
|
||||
#[cfg(feature = "bellman")]
|
||||
Parameters(BackendParameter::Bellman, CurveParameter::Bn128, SchemeParameter::G16) => {
|
||||
cli_verify::<Bn128Field, G16, Bellman>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "bellman")]
|
||||
Parameters(BackendParameter::Bellman, CurveParameter::Bls12_381, SchemeParameter::G16) => {
|
||||
cli_verify::<Bls12_381Field, G16, Bellman>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "ark")]
|
||||
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::GM17) => {
|
||||
cli_verify::<Bls12_377Field, GM17, Ark>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "ark")]
|
||||
Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::GM17) => {
|
||||
cli_verify::<Bw6_761Field, GM17, Ark>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "ark")]
|
||||
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
cli_verify::<Bn128Field, GM17, Ark>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
cli_verify::<Bn128Field, GM17, Libsnark>(sub_matches)
|
||||
}
|
||||
#[cfg(feature = "libsnark")]
|
||||
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
cli_verify::<Bn128Field, PGHR13, Libsnark>(sub_matches)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_verify<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
||||
sub_matches: &ArgMatches,
|
||||
) -> Result<(), String> {
|
||||
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
|
||||
let vk_file = File::open(&vk_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", vk_path.display(), why))?;
|
||||
|
||||
let vk_reader = BufReader::new(vk_file);
|
||||
let vk = serde_json::from_reader(vk_reader)
|
||||
.map_err(|why| format!("Couldn't deserialize verification key: {}", why))?;
|
||||
|
||||
let proof_path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
let proof_file = File::open(&proof_path)
|
||||
.map_err(|why| format!("Couldn't open {}: {}", proof_path.display(), why))?;
|
||||
|
||||
let proof_reader = BufReader::new(proof_file);
|
||||
let proof = serde_json::from_reader(proof_reader)
|
||||
.map_err(|why| format!("Couldn't deserialize proof: {}", why))?;
|
||||
|
||||
println!("Performing verification...");
|
||||
println!(
|
||||
"The verification result is: {}",
|
||||
match B::verify(vk, proof) {
|
||||
true => "PASS",
|
||||
false => "FAIL",
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -6,6 +6,10 @@ pub mod gm17;
|
|||
pub mod groth16;
|
||||
pub mod pghr13;
|
||||
|
||||
pub use self::gm17::GM17;
|
||||
pub use self::groth16::G16;
|
||||
pub use self::pghr13::PGHR13;
|
||||
|
||||
pub trait Scheme<T: Field> {
|
||||
type VerificationKey: Serialize + DeserializeOwned;
|
||||
type ProofPoints: Serialize + DeserializeOwned;
|
||||
|
|
123
zokrates_js/Cargo.lock
generated
123
zokrates_js/Cargo.lock
generated
|
@ -24,86 +24,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bls12-377"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bn254"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bw6-761"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/curves#23e87bf224c23be5c5bccc6084aae31fff8bb83f"
|
||||
dependencies = [
|
||||
"ark-bls12-377",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-ec"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/algebra#9bc541722707e1ac495e82fbf86446bbfde38a82"
|
||||
dependencies = [
|
||||
"ark-ff",
|
||||
"ark-serialize",
|
||||
"ark-std",
|
||||
"derivative",
|
||||
"num-traits 0.2.12",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-ff"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/algebra#9bc541722707e1ac495e82fbf86446bbfde38a82"
|
||||
dependencies = [
|
||||
"ark-ff-asm",
|
||||
"ark-serialize",
|
||||
"ark-std",
|
||||
"derivative",
|
||||
"num-traits 0.2.12",
|
||||
"rand 0.7.3",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-ff-asm"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/algebra#9bc541722707e1ac495e82fbf86446bbfde38a82"
|
||||
dependencies = [
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-serialize"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/algebra#9bc541722707e1ac495e82fbf86446bbfde38a82"
|
||||
dependencies = [
|
||||
"ark-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-std"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/arkworks-rs/utils#f6974ac72f59339b7ab798a728a84c5a7b8bac45"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
|
@ -256,17 +176,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.34",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
|
@ -896,39 +805,12 @@ version = "0.1.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65c94201b44764d6d1f7e37c15a8289ed55e546c1762c7f1d57f616966e0c181"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ef146c2ad5e5f4b037cd6ce2ebb775401729b19a82040c1beac9d36c7d1428"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.114"
|
||||
|
@ -1229,11 +1111,6 @@ dependencies = [
|
|||
name = "zokrates_field"
|
||||
version = "0.3.7"
|
||||
dependencies = [
|
||||
"ark-bls12-377",
|
||||
"ark-bn254",
|
||||
"ark-bw6-761",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"bellman_ce",
|
||||
"bincode 0.8.0",
|
||||
"lazy_static",
|
||||
|
|
Loading…
Reference in a new issue