1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

cli commands in separate files

This commit is contained in:
dark64 2020-12-17 21:03:45 +01:00
parent d94c44a4b8
commit b06acb55e4
16 changed files with 1193 additions and 1164 deletions

2
Cargo.lock generated
View file

@ -2050,6 +2050,8 @@ dependencies = [
"dirs",
"fs_extra",
"glob 0.2.11",
"lazy_static",
"log",
"regex",
"serde_json",
"tempdir",

View file

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

View file

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

View file

@ -1,6 +1,5 @@
use core::convert::TryFrom;
use crate::constants::*;
use core::convert::TryFrom;
#[derive(Debug)]
pub enum CurveParameter {

View 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(())
}

View 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(())
}

View 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(())
}

View 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(())
}

View 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(())
}

View 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;

View 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(())
}

View 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(())
}

View 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(())
}

View file

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

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