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

Setup phase separated. Keys serialized to files.

This commit is contained in:
Jacob Eberhardt 2017-10-25 02:02:13 +02:00
parent 8fc4d5609f
commit e1d5aeb9f5
4 changed files with 159 additions and 30 deletions

View file

@ -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();
}

View file

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

View file

@ -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();

View file

@ -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),
};