commit
68b9f6409c
10 changed files with 85 additions and 68 deletions
1
changelogs/unreleased/751-dark64
Normal file
1
changelogs/unreleased/751-dark64
Normal file
|
@ -0,0 +1 @@
|
|||
Add global `--verbose` flag to CLI for verbose logging, add `--ztf` flag to `compile` command, deprecate `--light` flag as its behaviour is now a default.
|
|
@ -11,7 +11,7 @@ mod constants;
|
|||
mod helpers;
|
||||
mod ops;
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
use clap::{App, AppSettings, Arg};
|
||||
use ops::*;
|
||||
|
||||
fn main() {
|
||||
|
@ -28,6 +28,12 @@ fn cli() -> Result<(), String> {
|
|||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.author("Jacob Eberhardt, Thibaut Schaeffer, Stefan Deml, Darko Macesic")
|
||||
.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!'")
|
||||
.arg(Arg::with_name("verbose")
|
||||
.long("verbose")
|
||||
.help("Verbose mode")
|
||||
.required(false)
|
||||
.global(true)
|
||||
)
|
||||
.subcommands(vec![
|
||||
compile::subcommand(),
|
||||
check::subcommand(),
|
||||
|
|
|
@ -58,7 +58,7 @@ fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
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))?;
|
||||
.map_err(|why| format!("Could not open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut source = String::new();
|
||||
|
|
|
@ -56,11 +56,17 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.long("allow-unconstrained-variables")
|
||||
.help("Allow unconstrained variables by inserting dummy constraints")
|
||||
.required(false)
|
||||
).arg(Arg::with_name("light")
|
||||
.long("light")
|
||||
.help("Skip logs and human readable output")
|
||||
).arg(Arg::with_name("ztf")
|
||||
.long("ztf")
|
||||
.help("Write human readable output (ztf)")
|
||||
.required(false)
|
||||
)
|
||||
.arg(Arg::with_name("light") // TODO: deprecated, should be removed
|
||||
.long("light")
|
||||
.required(false)
|
||||
.overrides_with_all(&["ztf", "verbose"])
|
||||
.hidden(true)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
|
@ -74,16 +80,23 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
}
|
||||
|
||||
fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
println!("Compiling {}\n", sub_matches.value_of("input").unwrap());
|
||||
// TODO: remove the warning once light flag is removed entirely
|
||||
if sub_matches.is_present("light") {
|
||||
println!(
|
||||
"Warning: the --light flag is deprecated and will be removed in a coming release.\n\
|
||||
Terminal output is now off by default and can be activated with the --verbose flag.\n\
|
||||
Human-readable output file (ztf) is now off by default and can be activated with the --ztf flag.\n"
|
||||
)
|
||||
}
|
||||
|
||||
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))?;
|
||||
.map_err(|why| format!("Could not open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut source = String::new();
|
||||
|
@ -132,7 +145,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
|
||||
// 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))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", bin_output_path.display(), why))?;
|
||||
|
||||
let mut writer = BufWriter::new(bin_output_file);
|
||||
|
||||
|
@ -140,18 +153,24 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
|
||||
// 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))?;
|
||||
.map_err(|why| format!("Could not 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 {
|
||||
if sub_matches.is_present("verbose") {
|
||||
// debugging output
|
||||
println!("Compiled program:\n{}", program_flattened);
|
||||
}
|
||||
|
||||
println!("Compiled code written to '{}'", bin_output_path.display());
|
||||
|
||||
if sub_matches.is_present("ztf") {
|
||||
// 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))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", hr_output_path.display(), why))?;
|
||||
|
||||
let mut hrofb = BufWriter::new(hr_output_file);
|
||||
writeln!(&mut hrofb, "{}", program_flattened)
|
||||
|
@ -159,16 +178,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), 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());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("abi_spec")
|
||||
).arg(Arg::with_name("abi-spec")
|
||||
.short("s")
|
||||
.long("abi_spec")
|
||||
.long("abi-spec")
|
||||
.help("Path of the ABI specification")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
|
@ -57,10 +57,6 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.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)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -68,7 +64,7 @@ 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))?;
|
||||
File::open(&path).map_err(|why| format!("Could not open {}: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
|
@ -83,8 +79,10 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
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") {
|
||||
let verbose = sub_matches.is_present("verbose");
|
||||
|
||||
// print deserialized flattened program if in verbose mode
|
||||
if verbose {
|
||||
println!("{}", ir_prog);
|
||||
}
|
||||
|
||||
|
@ -97,9 +95,9 @@ fn cli_compute<T: Field>(ir_prog: ir::Prog<T>, sub_matches: &ArgMatches) -> Resu
|
|||
|
||||
let signature = match is_abi {
|
||||
true => {
|
||||
let path = Path::new(sub_matches.value_of("abi_spec").unwrap());
|
||||
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))?;
|
||||
.map_err(|why| format!("Could not open {}: {}", path.display(), why))?;
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
let abi: Abi = from_reader(&mut reader).map_err(|why| why.to_string())?;
|
||||
|
@ -176,18 +174,21 @@ fn cli_compute<T: Field>(ir_prog: ir::Prog<T>, sub_matches: &ArgMatches) -> Resu
|
|||
zokrates_abi::CheckedValues::decode(witness.return_values(), signature.outputs)
|
||||
.into_serde_json();
|
||||
|
||||
println!("\nWitness: \n\n{}", results_json_value);
|
||||
if verbose {
|
||||
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))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", output_path.display(), why))?;
|
||||
|
||||
let writer = BufWriter::new(output_file);
|
||||
|
||||
witness
|
||||
.write(writer)
|
||||
.map_err(|why| format!("could not save witness: {:?}", why))?;
|
||||
.map_err(|why| format!("Could not save witness: {:?}", why))?;
|
||||
|
||||
println!("Witness file written to '{}'", output_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -93,11 +93,11 @@ fn cli_export_verifier<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T
|
|||
// 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))?;
|
||||
.map_err(|why| format!("Could not 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))?;
|
||||
.map_err(|why| format!("Could not deserialize verification key: {}", why))?;
|
||||
|
||||
let abi = SolidityAbi::from(sub_matches.value_of("solidity-abi").unwrap())?;
|
||||
|
||||
|
@ -106,7 +106,7 @@ fn cli_export_verifier<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T
|
|||
//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))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", output_path.display(), why))?;
|
||||
|
||||
let mut writer = BufWriter::new(output_file);
|
||||
|
||||
|
@ -114,6 +114,6 @@ fn cli_export_verifier<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T
|
|||
.write_all(&verifier.as_bytes())
|
||||
.map_err(|_| "Failed writing output to file".to_string())?;
|
||||
|
||||
println!("Finished exporting verifier");
|
||||
println!("Verifier exported to '{}'", output_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
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))?;
|
||||
.map_err(|why| format!("Could not open {}: {}", program_path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(program_file);
|
||||
let prog = ProgEnum::deserialize(&mut reader)?;
|
||||
|
@ -148,7 +148,7 @@ fn cli_generate_proof<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
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),
|
||||
Err(why) => panic!("Could not open {}: {}", witness_path.display(), why),
|
||||
};
|
||||
|
||||
let witness = ir::Witness::read(witness_file)
|
||||
|
@ -158,13 +158,13 @@ fn cli_generate_proof<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
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))?;
|
||||
.map_err(|why| format!("Could not 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))?;
|
||||
.map_err(|why| format!("Could not read {}: {}", pk_path.display(), why))?;
|
||||
|
||||
let proof = B::generate_proof(program, witness, pk);
|
||||
let mut proof_file = File::create(proof_path).unwrap();
|
||||
|
@ -172,9 +172,12 @@ fn cli_generate_proof<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
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))?;
|
||||
.map_err(|why| format!("Could not write to {}: {}", proof_path.display(), why))?;
|
||||
|
||||
println!("Proof:\n{}", proof);
|
||||
if sub_matches.is_present("verbose") {
|
||||
println!("Proof:\n{}", proof);
|
||||
}
|
||||
|
||||
println!("Proof written to '{}'", proof_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -70,12 +70,6 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.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> {
|
||||
|
@ -136,8 +130,8 @@ fn cli_setup<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
) -> Result<(), String> {
|
||||
println!("Performing setup...");
|
||||
|
||||
// print deserialized flattened program
|
||||
if !sub_matches.is_present("light") {
|
||||
// print deserialized flattened program if in verbose mode
|
||||
if sub_matches.is_present("verbose") {
|
||||
println!("{}", program);
|
||||
}
|
||||
|
||||
|
@ -150,23 +144,26 @@ fn cli_setup<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
|
||||
// write verification key
|
||||
let mut vk_file = File::create(vk_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", vk_path.display(), why))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", vk_path.display(), why))?;
|
||||
vk_file
|
||||
.write_all(
|
||||
serde_json::to_string_pretty(&keypair.vk)
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.map_err(|why| format!("couldn't write to {}: {}", vk_path.display(), why))?;
|
||||
.map_err(|why| format!("Could not write to {}: {}", vk_path.display(), why))?;
|
||||
|
||||
println!("Verification key written to '{}'", vk_path.display());
|
||||
|
||||
// write proving key
|
||||
let mut pk_file = File::create(pk_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", pk_path.display(), why))?;
|
||||
.map_err(|why| format!("Could not create {}: {}", pk_path.display(), why))?;
|
||||
pk_file
|
||||
.write_all(keypair.pk.as_ref())
|
||||
.map_err(|why| format!("couldn't write to {}: {}", pk_path.display(), why))?;
|
||||
.map_err(|why| format!("Could not write to {}: {}", pk_path.display(), why))?;
|
||||
|
||||
println!("Setup completed.");
|
||||
println!("Proving key written to '{}'", pk_path.display());
|
||||
println!("Setup completed");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -106,26 +106,26 @@ fn cli_verify<T: Field, S: Scheme<T>, B: Backend<T, S>>(
|
|||
) -> 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))?;
|
||||
.map_err(|why| format!("Could not 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))?;
|
||||
.map_err(|why| format!("Could not 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))?;
|
||||
.map_err(|why| format!("Could not 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))?;
|
||||
.map_err(|why| format!("Could not deserialize proof: {}", why))?;
|
||||
|
||||
println!("Performing verification...");
|
||||
println!(
|
||||
"The verification result is: {}",
|
||||
"{}",
|
||||
match B::verify(vk, proof) {
|
||||
true => "PASS",
|
||||
false => "FAIL",
|
||||
true => "PASSED",
|
||||
false => "FAILED",
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -105,7 +105,6 @@ mod integration {
|
|||
abi_spec_path.to_str().unwrap(),
|
||||
"-o",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"--light",
|
||||
];
|
||||
|
||||
// compile
|
||||
|
@ -138,7 +137,7 @@ mod integration {
|
|||
|
||||
// First we need to convert our test input into raw field elements. We need to ABI spec for that
|
||||
let file = File::open(&abi_spec_path)
|
||||
.map_err(|why| format!("couldn't open {}: {}", flattened_path.display(), why))
|
||||
.map_err(|why| format!("Could not open {}: {}", flattened_path.display(), why))
|
||||
.unwrap();
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
|
|
Loading…
Reference in a new issue