Setup phase separated. Keys serialized to files.
This commit is contained in:
parent
8fc4d5609f
commit
e1d5aeb9f5
4 changed files with 159 additions and 30 deletions
|
@ -1,33 +1,21 @@
|
|||
/**
|
||||
* @file wraplibsnark.cpp
|
||||
* @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
|
||||
* @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
|
||||
* @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
|
||||
* @date 2017
|
||||
*/
|
||||
|
||||
#include "wraplibsnark.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
// contains definition of alt_bn128 ec public parameters
|
||||
#include "libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
|
||||
// contains required interfaces and types (keypair, proof, generator, prover, verifier)
|
||||
#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp"
|
||||
|
||||
// contains usage example for these interfaces
|
||||
//#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp"
|
||||
|
||||
// How to "zkSNARK from R1CS:"
|
||||
// libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc
|
||||
|
||||
// How to generate R1CS Example
|
||||
// libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc
|
||||
|
||||
// Interfaces for R1CS
|
||||
// libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp
|
||||
|
||||
using namespace std;
|
||||
using namespace libsnark;
|
||||
|
||||
|
@ -85,7 +73,7 @@ std::string outputPointG2AffineAsHex(libsnark::alt_bn128_G2 _p)
|
|||
}
|
||||
|
||||
//takes input and puts it into constraint system
|
||||
r1cs_ppzksnark_constraint_system<alt_bn128_pp> createConstraintSystem(const uint8_t* A, const uint8_t* B, const uint8_t* C, const uint8_t* witness, int constraints, int variables, int inputs)
|
||||
r1cs_ppzksnark_constraint_system<alt_bn128_pp> createConstraintSystem(const uint8_t* A, const uint8_t* B, const uint8_t* C, int constraints, int variables, int inputs)
|
||||
{
|
||||
r1cs_constraint_system<Fr<alt_bn128_pp> > cs;
|
||||
cs.primary_input_size = inputs;
|
||||
|
@ -124,9 +112,6 @@ r1cs_ppzksnark_constraint_system<alt_bn128_pp> createConstraintSystem(const uint
|
|||
}
|
||||
cs.add_constraint(r1cs_constraint<Fr<alt_bn128_pp> >(lin_comb_A, lin_comb_B, lin_comb_C));
|
||||
}
|
||||
for (int idx=0; idx<variables; idx++) {
|
||||
cout << "witness entry " << idx << ": " << libsnarkBigintFromBytes(witness + idx*32) << endl;
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
@ -137,6 +122,14 @@ r1cs_ppzksnark_keypair<alt_bn128_pp> generateKeypair(const r1cs_ppzksnark_constr
|
|||
return r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
|
||||
}
|
||||
|
||||
void serializeProvingKeyToFile(r1cs_ppzksnark_keypair<alt_bn128_pp> keypair, const char* pk_path){
|
||||
writeToFile(pk_path, keypair.pk);
|
||||
}
|
||||
|
||||
void serializeVerificationKeyToFile(r1cs_ppzksnark_keypair<alt_bn128_pp> keypair, const char* vk_path){
|
||||
writeToFile(vk_path, keypair.vk);
|
||||
}
|
||||
|
||||
// compliant with solidty verification example
|
||||
void exportVerificationKey(r1cs_ppzksnark_keypair<alt_bn128_pp> keypair){
|
||||
unsigned icLength = keypair.vk.encoded_IC_query.rest.indices.size() + 1;
|
||||
|
@ -196,6 +189,33 @@ void exportProof(r1cs_ppzksnark_proof<alt_bn128_pp> proof){
|
|||
|
||||
}
|
||||
|
||||
bool _setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int constraints, int variables, int inputs, const char* pk_path, const char* vk_path)
|
||||
{
|
||||
libsnark::inhibit_profiling_info = true;
|
||||
libsnark::inhibit_profiling_counters = true;
|
||||
|
||||
//initialize curve parameters
|
||||
alt_bn128_pp::init_public_params();
|
||||
|
||||
r1cs_constraint_system<Fr<alt_bn128_pp>> cs;
|
||||
cs = createConstraintSystem(A, B ,C , constraints, variables, inputs);
|
||||
|
||||
assert(cs.num_variables() >= inputs);
|
||||
assert(cs.num_inputs() == inputs);
|
||||
assert(cs.num_constraints() == constraints);
|
||||
|
||||
// create keypair
|
||||
r1cs_ppzksnark_keypair<alt_bn128_pp> keypair = r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
|
||||
|
||||
// Export vk and pk to files
|
||||
serializeProvingKeyToFile(keypair, pk_path);
|
||||
serializeVerificationKeyToFile(keypair, vk_path);
|
||||
|
||||
// Print VerificationKey in Solidity compatible format
|
||||
exportVerificationKey(keypair);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _run_libsnark(const uint8_t* A, const uint8_t* B, const uint8_t* C, const uint8_t* witness, int constraints, int variables, int inputs)
|
||||
{
|
||||
|
@ -218,7 +238,7 @@ bool _run_libsnark(const uint8_t* A, const uint8_t* B, const uint8_t* C, const u
|
|||
// Setup:
|
||||
// create constraint system
|
||||
r1cs_constraint_system<Fr<alt_bn128_pp>> cs;
|
||||
cs = createConstraintSystem(A, B ,C , witness, constraints, variables, inputs);
|
||||
cs = createConstraintSystem(A, B ,C , constraints, variables, inputs);
|
||||
|
||||
// assign variables based on witness values, excludes ~one
|
||||
r1cs_variable_assignment<Fr<alt_bn128_pp> > full_variable_assignment;
|
||||
|
@ -266,3 +286,15 @@ bool _run_libsnark(const uint8_t* A, const uint8_t* B, const uint8_t* C, const u
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeToFile(std::string path, T& obj) {
|
||||
std::stringstream ss;
|
||||
ss << obj;
|
||||
std::ofstream fh;
|
||||
fh.open(path, std::ios::binary);
|
||||
ss.rdbuf()->pubseekpos(0, std::ios_base::out);
|
||||
fh << ss.rdbuf();
|
||||
fh.flush();
|
||||
fh.close();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* @file wraplibsnark.hpp
|
||||
* @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
|
||||
* @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
|
||||
* @date 2017
|
||||
*/
|
||||
|
@ -11,6 +12,16 @@ extern "C" {
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool _setup(const uint8_t* A,
|
||||
const uint8_t* B,
|
||||
const uint8_t* C,
|
||||
int constraints,
|
||||
int variables,
|
||||
int inputs,
|
||||
const char* pk_path,
|
||||
const char* vk_path
|
||||
);
|
||||
|
||||
// entrypoint, wraps the whole process, probably should be removed later
|
||||
bool _run_libsnark(const uint8_t* A,
|
||||
const uint8_t* B,
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
//
|
||||
// @file libsnark.rs
|
||||
// @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
|
||||
// @author Dennis Kuhnert <dennis.kuhnert@campus.tu-berlin.de>
|
||||
// @date 2017
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use self::libc::c_int;
|
||||
use self::libc::c_char;
|
||||
use self::libc::uint8_t;
|
||||
use std::ffi::CString;
|
||||
|
||||
use field::Field;
|
||||
|
||||
#[link(name = "snark")]
|
||||
|
@ -23,6 +27,65 @@ extern "C" {
|
|||
variables: c_int,
|
||||
inputs: c_int,
|
||||
) -> bool;
|
||||
|
||||
fn _setup(
|
||||
A: *const uint8_t,
|
||||
B: *const uint8_t,
|
||||
C: *const uint8_t,
|
||||
constraints: c_int,
|
||||
variables: c_int,
|
||||
inputs: c_int,
|
||||
pk_path: *const c_char,
|
||||
vk_path: *const c_char,
|
||||
) -> bool;
|
||||
}
|
||||
|
||||
pub fn setup<T: Field> (
|
||||
variables: Vec<String>,
|
||||
a: Vec<Vec<(usize, T)>>,
|
||||
b: Vec<Vec<(usize, T)>>,
|
||||
c: Vec<Vec<(usize, T)>>,
|
||||
num_inputs: usize,
|
||||
pk_path: &str,
|
||||
vk_path: &str,
|
||||
) -> bool {
|
||||
|
||||
let num_constraints = a.len();
|
||||
let num_variables = variables.len();
|
||||
|
||||
//initialize matrix entries with 0s.
|
||||
let mut a_arr: Vec<[u8; 32]> = vec![[0u8; 32]; num_constraints * num_variables];
|
||||
let mut b_arr: Vec<[u8; 32]> = vec![[0u8; 32]; num_constraints * num_variables];
|
||||
let mut c_arr: Vec<[u8; 32]> = vec![[0u8; 32]; num_constraints * num_variables];
|
||||
|
||||
for row in 0..num_constraints {
|
||||
for &(idx, ref val) in &a[row] {
|
||||
a_arr[row * num_variables + idx] = vec_as_u8_32_array(&val.into_byte_vector());
|
||||
}
|
||||
for &(idx, ref val) in &b[row] {
|
||||
b_arr[row * num_variables + idx] = vec_as_u8_32_array(&val.into_byte_vector());
|
||||
}
|
||||
for &(idx, ref val) in &c[row] {
|
||||
c_arr[row * num_variables + idx] = vec_as_u8_32_array(&val.into_byte_vector());
|
||||
}
|
||||
}
|
||||
|
||||
// convert String slices to 'CString's
|
||||
let pk_path_cstring = CString::new(pk_path).unwrap();
|
||||
let vk_path_cstring = CString::new(vk_path).unwrap();
|
||||
|
||||
unsafe {
|
||||
_setup(
|
||||
a_arr[0].as_ptr(),
|
||||
b_arr[0].as_ptr(),
|
||||
c_arr[0].as_ptr(),
|
||||
num_constraints as i32,
|
||||
num_variables as i32,
|
||||
num_inputs as i32,
|
||||
pk_path_cstring.as_ptr(),
|
||||
vk_path_cstring.as_ptr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// assumes that field elements can be represented with 32 bytes
|
||||
|
@ -34,6 +97,7 @@ pub fn run_libsnark<T: Field>(
|
|||
witness: Vec<T>,
|
||||
num_inputs: usize,
|
||||
) -> bool {
|
||||
|
||||
let num_constraints = a.len();
|
||||
let num_variables = variables.len();
|
||||
|
||||
|
|
44
src/main.rs
44
src/main.rs
|
@ -34,7 +34,7 @@ use flatten::Flattener;
|
|||
use r1cs::r1cs_program;
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
#[cfg(not(feature = "nolibsnark"))]
|
||||
use libsnark::run_libsnark;
|
||||
use libsnark::{run_libsnark, setup};
|
||||
use bincode::{serialize_into, deserialize_from , Infinite};
|
||||
|
||||
fn main() {
|
||||
|
@ -78,7 +78,26 @@ fn main() {
|
|||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH))
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH)
|
||||
)
|
||||
.arg(Arg::with_name("proving-key-path")
|
||||
.short("pk")
|
||||
.long("proving-key-path")
|
||||
.help("Path of the generated proving key file.")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(PROVING_KEY_DEFAULT_PATH)
|
||||
)
|
||||
.arg(Arg::with_name("verification-key-path")
|
||||
.short("vk")
|
||||
.long("verification-key-path")
|
||||
.help("Path of the generated verification key file.")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(VERIFICATION_KEY_DEFAULT_PATH)
|
||||
)
|
||||
)
|
||||
.subcommand(SubCommand::with_name("export-verifier")
|
||||
.about("Exports a verifier as Solidity smart contract.")
|
||||
|
@ -297,7 +316,7 @@ fn main() {
|
|||
|
||||
// write witness to file
|
||||
let output_path = Path::new(sub_matches.value_of("output").unwrap());
|
||||
let mut output_file = match File::create(&output_path) {
|
||||
let output_file = match File::create(&output_path) {
|
||||
Ok(file) => file,
|
||||
Err(why) => panic!("couldn't create {}: {}", output_path.display(), why),
|
||||
};
|
||||
|
@ -345,16 +364,19 @@ fn main() {
|
|||
// print deserialized flattened program
|
||||
println!("{}", main_flattened);
|
||||
|
||||
// transform to R1CS
|
||||
let (variables, a, b, c) = r1cs_program(&program_ast);
|
||||
|
||||
// TODO: Setup Operation
|
||||
// get paths for proving and verification keys
|
||||
let pk_path = sub_matches.value_of("proving-key-path").unwrap();
|
||||
let vk_path = sub_matches.value_of("verification-key-path").unwrap();
|
||||
|
||||
// run libsnark
|
||||
// #[cfg(not(feature="nolibsnark"))]{
|
||||
// // number of inputs in the zkSNARK sense, i.e., input variables + output variables
|
||||
// let num_inputs = main_flattened.arguments.len() + 1; //currently exactly one output variable
|
||||
// println!("run_libsnark = {:?}", run_libsnark(variables, a, b, c, witness, num_inputs));
|
||||
// }
|
||||
// run setup phase
|
||||
#[cfg(not(feature="nolibsnark"))]{
|
||||
// number of inputs in the zkSNARK sense, i.e., input variables + output variables
|
||||
let num_inputs = main_flattened.arguments.len() + 1; //currently exactly one output variable
|
||||
println!("setup successful: {:?}", setup(variables, a, b, c, num_inputs, pk_path, vk_path));
|
||||
}
|
||||
|
||||
}
|
||||
("shortcut", Some(sub_matches)) => {
|
||||
|
@ -434,7 +456,7 @@ fn main() {
|
|||
|
||||
// deserialize witness
|
||||
let witness_path = Path::new(sub_matches.value_of("witness").unwrap());
|
||||
let mut witness_file = match File::open(&witness_path) {
|
||||
let witness_file = match File::open(&witness_path) {
|
||||
Ok(file) => file,
|
||||
Err(why) => panic!("couldn't open {}: {}", witness_path.display(), why),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue