diff --git a/src/main.rs b/src/main.rs index 18afa07a..87257908 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ extern crate clap; extern crate lazy_static; extern crate num; // cli extern crate serde; // serialization deserialization +extern crate serde_json; #[macro_use] extern crate serde_derive; extern crate bincode; @@ -36,7 +37,7 @@ use absy::Prog; use parser::parse_program; use semantics::Checker; use flatten::Flattener; -use r1cs::r1cs_program; +use r1cs::{r1cs_program, R1CS}; use clap::{App, AppSettings, Arg, SubCommand}; #[cfg(not(feature = "nolibsnark"))] use libsnark::{setup, generate_proof}; @@ -50,6 +51,7 @@ fn main() { const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol"; const WITNESS_DEFAULT_PATH: &str = "witness"; const VARIABLES_INFORMATION_KEY_DEFAULT_PATH: &str = "variables.inf"; + const IMPORT_OUTPUT_DEFAULT_PATH: &str = "import.code"; // cli specification using clap library let matches = App::new("ZoKrates") @@ -195,6 +197,26 @@ fn main() { .default_value(VARIABLES_INFORMATION_KEY_DEFAULT_PATH) ) ) + .subcommand(SubCommand::with_name("import") + .about("Imports a standard R1CS file as .code.") + .arg(Arg::with_name("input") + .short("i") + .long("input") + .help("path of verifier.") + .value_name("FILE") + .takes_value(true) + .required(true) + ) + .arg(Arg::with_name("output") + .short("o") + .long("output") + .help("output file path.") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(IMPORT_OUTPUT_DEFAULT_PATH) + ) + ) .get_matches(); match matches.subcommand() { @@ -569,6 +591,19 @@ fn main() { } } + ("import", Some(sub_matches)) => { + let path = Path::new(sub_matches.value_of("input").unwrap()); + println!("Importing R1CS from {}", sub_matches.value_of("input").unwrap()); + + let file = match File::open(&path) { + Ok(file) => file, + Err(why) => panic!("couldn't open {}: {}", path.display(), why), + }; + + let r1cs: r1cs::R1CS = serde_json::from_reader(file).unwrap(); + println!("R1CS: {:?}", r1cs); + let prog: Prog = r1cs::flattened_program(r1cs); + } _ => unimplemented!(), // Either no subcommand or one not tested for... } diff --git a/src/r1cs.rs b/src/r1cs.rs index 63640c5b..bd384428 100644 --- a/src/r1cs.rs +++ b/src/r1cs.rs @@ -6,10 +6,23 @@ //! @date 2017 use std::collections::HashMap; +use std::collections::BTreeMap; use absy::*; use absy::Expression::*; use field::Field; +// for r1cs import, can be moved. +// r1cs data strucutre reflecting JSON standard format: +//{variables:["a","b", ... ], +//constraints:[ +// [{offset_1:value_a1,offset2:value_a2,...},{offset1:value_b1,offset2:value_b2,...},{offset1:value_c1,offset2:value_c2,...}] +//]} +#[derive(Serialize, Deserialize, Debug)] +pub struct R1CS { + variables: Vec, + constraints: Vec>>, +} + /// Returns a vector of summands of the given `Expression`. /// /// # Arguments @@ -338,25 +351,45 @@ pub fn r1cs_program( /// * Since the matrices in R1CS are usually sparse, the following encoding is used: /// * For each constraint (i.e., row in the R1CS), only non-zero values are supplied and encoded as a tuple (index, value). /// -/// Example for a row of Matrix A: 0 0 1 2 0 -> (2,1),(3,2) -/// /// # Arguments /// -/// * `inputs` - Input variables as (Index, Name) name tuples, where index is the column index. -/// * `outputs` - Output variables as (Index, Name) name tuples, where index is the column index. -/// * `a` - Matrix A in the R1CS. -/// * `b` - Matrix B in the R1CS. -/// * `c` - Matrix C in the R1CS. +/// * r1cs - R1CS in standard JSON data format pub fn flattened_program( - inputs: Vec<(usize, String)>, - outputs: Vec<(usize, String)>, - a: Vec>, - b: Vec>, - c: Vec>, + r1cs: R1CS ) -> Prog { - // initialize variable map with index->name + // statements that constrains are translated to + let mut statements: Vec> = Vec::new(); + + for cons in r1cs.constraints { + assert!(cons.len() == 3); // entries for a,b,c + + // right hand side of definition + let mut rhs: Expression; + + // Expression: c0+c1+c2... + for (c_var_offset, c_val) in cons[2] { + let counter = 0; + let var = r1cs.variables[c_var_offset.parse::().unwrap()]; // get variable name + if counter ==0{ + rhs = Expression::Identifier(var); + } else { + rhs = Expression::Add(box rhs, box Expression::Identifier(var)); + } + println!("rhs: {:?}", rhs); + } + + + let a_entries = cons[0].clone(); + let b_entries = cons[1].clone(); + let c_entries = cons[2].clone(); + println!("a entries: {:?}", a_entries); + } + + let mut functs = Vec::new(); + functs.push(Function{ id: "import".to_owned(), arguments: Vec::new() , statements: statements}); + Prog{functions: functs} } #[cfg(test)]