diff --git a/Cargo.lock b/Cargo.lock index ca8e38e0..52aa9feb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,5 @@ [root] -name = "zkc" +name = "ZoKrates" version = "0.1.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 565e5d04..a04e714a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "zkc" +name = "ZoKrates" version = "0.1.0" authors = ["Jacob Eberhardt ", "Dennis Kuhnert "] repository = "https://github.com/Kyroy/VerifiableStatementCompiler.git" diff --git a/src/field.rs b/src/field.rs index f600da86..9ac0f08a 100644 --- a/src/field.rs +++ b/src/field.rs @@ -4,12 +4,13 @@ // @date 2017 use num::{Integer, One, Zero}; -use num::bigint::{BigInt, ToBigInt}; +use num::bigint::{BigInt, BigUint, ToBigInt, ToBigUint}; use std::convert::From; use std::ops::{Add, Div, Mul, Sub}; use std::fmt; use std::fmt::{Debug, Display}; -use serde::{Serialize, Deserialize, Serializer}; +use serde::{Serialize, Serializer}; +use serde::de::{Deserialize, Deserializer, Visitor}; lazy_static! { static ref P: BigInt = BigInt::parse_bytes(b"21888242871839275222246405745257275088548364400416034343698204186575808495617", 10).unwrap(); @@ -292,10 +293,43 @@ impl Serialize for FieldPrime { fn serialize(&self, serializer: S) -> Result where S: Serializer { + // serializer.serialize_bytes(&(*self.value.to_biguint().to_bytes_le().as_slice())) serializer.serialize_bytes(&(*self.into_byte_vector().as_slice())) } } +// custom serde deserialization + +struct FieldPrimeVisitor; + +impl FieldPrimeVisitor { + fn new() -> Self { + FieldPrimeVisitor{} + } +} + +impl<'de> Visitor<'de> for FieldPrimeVisitor { + type Value = FieldPrime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct FieldPrime") + } + + fn visit_bytes(self, v: &[u8]) -> Result { + let val = BigUint::from_bytes_le(v).to_bigint().unwrap(); + Ok(FieldPrime{value: val}) + } +} + +impl<'de> Deserialize<'de> for FieldPrime { + + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + deserializer.deserialize_bytes(FieldPrimeVisitor::new()) + } +} + /// Calculates the gcd using a iterative implementation of the extended euclidian algorithm. /// Returning `(d, s, t)` so that `d = s * a + t * b` /// @@ -328,6 +362,7 @@ mod tests { #[cfg(test)] mod field_prime { use super::*; + use bincode::{serialize, deserialize , Infinite}; #[test] fn positive_number() { @@ -556,6 +591,13 @@ mod tests { (FieldPrime::from("-54").pow(&FieldPrime::from("11"))).value ); } + + #[test] + fn ser_deser() { + let serialized = &serialize(&FieldPrime::from("11"), Infinite).unwrap(); + let deserialized = deserialize(serialized).unwrap(); + assert_eq!(FieldPrime::from("11"), deserialized); + } } #[test] diff --git a/src/main.rs b/src/main.rs index c544357f..3c60dc5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ // // @file main.rs -// @author Dennis Kuhnert // @author Jacob Eberhardt +// @author Dennis Kuhnert // @date 2017 #![feature(box_patterns, box_syntax)] @@ -34,7 +34,7 @@ use r1cs::r1cs_program; use clap::{App, AppSettings, Arg, SubCommand}; #[cfg(not(feature = "nolibsnark"))] use libsnark::run_libsnark; -use bincode::{serialize, deserialize, Infinite}; +use bincode::{serialize_into, deserialize_from , Infinite}; fn main() { const FLATTENED_CODE_DEFAULT_PATH: &str = "out"; @@ -44,7 +44,7 @@ fn main() { .setting(AppSettings::SubcommandRequiredElseHelp) .version("0.1") .author("Jacob Eberhardt, Dennis Kuhnert") - .about("Supports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.") + .about("I know that I show nothing!\nSupports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.") .subcommand(SubCommand::with_name("compile") .about("Compiles into flattened conditions. Produces two files: human-readable '.code' file and binary file") .arg(Arg::with_name("input") @@ -123,7 +123,7 @@ fn main() { Err(why) => panic!("couldn't create {}: {}", bin_output_path.display(), why), }; - let encoded: Vec = serialize(&program_flattened, Infinite).unwrap(); + serialize_into(&mut bin_output_file, &program_flattened, Infinite).expect("Unable to write data to file."); // write human-readable output file let hr_output_path = bin_output_path.to_path_buf().with_extension("code"); @@ -149,12 +149,12 @@ fn main() { // read compiled program let path = Path::new(sub_matches.value_of("input").unwrap()); - let file = match File::open(&path) { + let mut file = match File::open(&path) { Ok(file) => file, Err(why) => panic!("couldn't open {}: {}", path.display(), why), }; - let program_ast: Prog = match parse_program(file) { + let program_ast: Prog = match deserialize_from(&mut file, Infinite) { Ok(x) => x, Err(why) => { println!("{:?}", why); @@ -162,31 +162,43 @@ fn main() { } }; + // debugging output + println!("AST:\n {}", program_ast); + // make sure the input program is actually flattened. // TODO: is_flattened should be provided as method of Prog in absy. - let program_flattened = program_ast + let main_flattened = program_ast .functions .iter() .find(|x| x.id == "main") .unwrap(); - for stat in program_flattened.statements.clone() { + for stat in main_flattened.statements.clone() { assert!( stat.is_flattened(), format!("Input conditions not flattened: {}", &stat) ); } - // validate arguments - println!("{:?}", sub_matches.value_of("arguments")); + // validate #arguments + let mut args: Vec = Vec::new(); + match sub_matches.values_of("output"){ + Some(p) => { + let arg_strings: Vec<&str> = p.collect(); + args = arg_strings.into_iter().map(|x| FieldPrime::from(x)).collect(); + }, + None => { + } + } + println!("{:?}\n{:?}", main_flattened.arguments, args); + assert!(main_flattened.arguments.len() == args.len()); - // calculate witness - // let witness_map = program_flattened.get_witness(args); - // println!("witness_map {:?}", witness_map); - // match witness_map.get("~out") { - // Some(out) => println!("~out: {}", out), - // None => println!("~out not found") - // } + let witness_map = main_flattened.get_witness(args); + println!("witness_map {:?}", witness_map); + match witness_map.get("~out") { + Some(out) => println!("~out: {}", out), + None => println!("~out not found") + } // let witness: Vec<_> = variables.iter().map(|x| witness_map[x].clone()).collect(); // println!("witness {:?}", witness); }