1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00
Conflicts:
	lib/wraplibsnark.cpp
This commit is contained in:
Jacob Eberhardt 2017-03-27 18:10:23 +02:00
commit 9a466c9cb7
9 changed files with 179 additions and 94 deletions

7
examples/for.code Normal file
View file

@ -0,0 +1,7 @@
def forex(a):
x = 7
for i in 0..10 do
// x = x + a
x = x + a
endfor
return x

View file

@ -34,12 +34,14 @@ using namespace libsnark;
// conversion byte[32] <-> libsnark bigint.
libsnark::bigint<libsnark::alt_bn128_r_limbs> libsnarkBigintFromBytes(const uint8_t* _x)
{
libsnark::bigint<libsnark::alt_bn128_r_limbs> x;
libsnark::bigint<libsnark::alt_bn128_r_limbs> x;
for (unsigned i = 0; i < 4; i++)
for (unsigned j = 0; j < 8; j++)
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7-j));
return x;
for (unsigned i = 0; i < 4; i++) {
for (unsigned j = 0; j < 8; j++) {
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7-j));
}
}
return x;
}
@ -85,57 +87,55 @@ std::string outputPointG2Affine(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)
{
r1cs_constraint_system<Fr<alt_bn128_pp> > cs;
cs.primary_input_size = variables - 1;
cs.auxiliary_input_size = 0;
r1cs_constraint_system<Fr<alt_bn128_pp> > cs;
cs.primary_input_size = variables - 1;
cs.auxiliary_input_size = 0;
cout << "num variables: " << variables <<endl;
cout << "num constraints: " << constraints <<endl;
cout << "num variables: " << variables <<endl;
cout << "num constraints: " << constraints <<endl;
for (int row = 0; row < constraints; row++) {
for (int row = 0; row < constraints; row++) {
linear_combination<Fr<alt_bn128_pp> > lin_comb_A, lin_comb_B, lin_comb_C;
linear_combination<Fr<alt_bn128_pp> > lin_comb_A, lin_comb_B, lin_comb_C;
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(A+row*variables*32 + idx*32);
// cout << "C entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "A(" << idx << ", " << value << ")" << endl;
lin_comb_A.add_term(idx, value);
}
}
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(B+row*variables*32 + idx*32);
// cout << "B entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "B(" << idx << ", " << value << ")" << endl;
lin_comb_B.add_term(idx, value);
}
}
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(C+row*variables*32 + idx*32);
// cout << "C entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "C(" << idx << ", " << value << ")" << endl;
lin_comb_C.add_term(idx, value);
}
}
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;
}
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(A+row*variables*32 + idx*32);
// cout << "C entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "A(" << idx << ", " << value << ")" << endl;
lin_comb_A.add_term(idx, value);
}
}
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(B+row*variables*32 + idx*32);
// cout << "B entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "B(" << idx << ", " << value << ")" << endl;
lin_comb_B.add_term(idx, value);
}
}
for (int idx=0; idx<variables; idx++) {
libsnark::bigint<libsnark::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(C+row*variables*32 + idx*32);
// cout << "C entry " << idx << " in row " << row << ": " << value << endl;
if (!value.is_zero()) {
cout << "C(" << idx << ", " << value << ")" << endl;
lin_comb_C.add_term(idx, value);
}
}
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;
return cs;
}
// keypair generateKeypair(constraints)
r1cs_ppzksnark_keypair<alt_bn128_pp> generateKeypair(const r1cs_ppzksnark_constraint_system<alt_bn128_pp> &cs){
// from r1cs_ppzksnark.hpp
return r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
// from r1cs_ppzksnark.hpp
return r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
}
// compliant with solidty, from c++ client libsnark integration
void exportVerificationKey(r1cs_ppzksnark_keypair<alt_bn128_pp> keypair){
unsigned icLength = keypair.vk.encoded_IC_query.rest.indices.size() + 1;
@ -162,43 +162,44 @@ void exportVerificationKey(r1cs_ppzksnark_keypair<alt_bn128_pp> keypair){
bool _run_libsnark(const uint8_t* A, const uint8_t* B, const uint8_t* C, const uint8_t* witness, int constraints, int variables)
{
// Setup:
// create constraint system
r1cs_constraint_system<Fr<alt_bn128_pp> > cs;
cs = createConstraintSystem(A,B,C,witness,constraints,variables);
// Setup:
// create constraint system
r1cs_constraint_system<Fr<alt_bn128_pp> > cs;
cs = createConstraintSystem(A,B,C,witness,constraints,variables);
// assign variables
r1cs_variable_assignment<Fr<alt_bn128_pp> > full_variable_assignment;
for (int i = 1; i < variables; i++) {
full_variable_assignment.push_back(witness[i]);
}
// assign variables
r1cs_variable_assignment<Fr<alt_bn128_pp> > full_variable_assignment;
for (int i = 1; i < variables; i++) {
full_variable_assignment.push_back(witness[i]);
}
//split up variables into primary and auxiliary inputs
// TODO: Check whether this is consistent with inputs from VerifiableStatementCompiler
r1cs_primary_input<Fr<alt_bn128_pp> > primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + variables - 1);
r1cs_primary_input<Fr<alt_bn128_pp> > auxiliary_input(full_variable_assignment.begin() + variables - 1, full_variable_assignment.end());
//split up variables into primary and auxiliary inputs
// TODO: Check whether this is consistent with inputs from VerifiableStatementCompiler
r1cs_primary_input<Fr<alt_bn128_pp> > primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + variables - 1);
r1cs_primary_input<Fr<alt_bn128_pp> > auxiliary_input(full_variable_assignment.begin() + variables - 1, full_variable_assignment.end());
// sanity checks
assert(cs.num_variables() == full_variable_assignment.size());
assert(cs.num_variables() >= variables - 1);
assert(cs.num_inputs() == variables - 1);
assert(cs.num_constraints() == constraints);
assert(cs.is_satisfied(primary_input, auxiliary_input));
// sanity checks
assert(cs.num_variables() == full_variable_assignment.size());
assert(cs.num_variables() >= variables - 1);
assert(cs.num_inputs() == variables - 1);
assert(cs.num_constraints() == constraints);
assert(cs.is_satisfied(primary_input, auxiliary_input));
//initialize curve parameters
alt_bn128_pp::init_public_params();
//initialize curve parameters
alt_bn128_pp::init_public_params();
// create keypair
r1cs_ppzksnark_keypair<alt_bn128_pp> keypair = r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
// create keypair
r1cs_ppzksnark_keypair<alt_bn128_pp> keypair = r1cs_ppzksnark_generator<alt_bn128_pp>(cs);
// Print VerificationKey in Solidity compatible format
exportVerificationKey(keypair);
// Print VerificationKey in Solidity compatible format
exportVerificationKey(keypair);
// Proof Generation
r1cs_ppzksnark_proof<alt_bn128_pp> proof = r1cs_ppzksnark_prover<alt_bn128_pp>(keypair.pk, primary_input, auxiliary_input);
// Verification
bool result = r1cs_ppzksnark_verifier_strong_IC<alt_bn128_pp>(keypair.vk, primary_input, proof);
// Proof Generation
r1cs_ppzksnark_proof<alt_bn128_pp> proof = r1cs_ppzksnark_prover<alt_bn128_pp>(keypair.pk, primary_input, auxiliary_input);
return result;
// Verification
bool result = r1cs_ppzksnark_verifier_strong_IC<alt_bn128_pp>(keypair.vk, primary_input, proof);
return result;
}

View file

@ -13,11 +13,11 @@ extern "C" {
// entrypoint, wraps the whole process, probably should be removed later
bool _run_libsnark(const uint8_t* A,
const uint8_t* B,
const uint8_t* C,
const uint8_t* witness,
int constraints,
int variables);
const uint8_t* B,
const uint8_t* C,
const uint8_t* witness,
int constraints,
int variables);
#ifdef __cplusplus
} // extern "C"

View file

@ -38,6 +38,7 @@ impl<T: Field> Prog<T> {
let s = expr.solve(&mut witness);
witness.insert(id.to_string(), s);
},
Statement::For(..) => unimplemented!(),
Statement::Condition(ref lhs, ref rhs) => assert_eq!(lhs.solve(&mut witness), rhs.solve(&mut witness)),
}
}
@ -61,6 +62,7 @@ pub enum Statement<T: Field> {
Return(Expression<T>),
Definition(String, Expression<T>),
Condition(Expression<T>, Expression<T>),
For(String, T, T, Vec<Statement<T>>),
Compiler(String, Expression<T>),
}
@ -70,6 +72,13 @@ impl<T: Field> fmt::Display for Statement<T> {
Statement::Return(ref expr) => write!(f, "return {}", expr),
Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {}", lhs, rhs),
Statement::Condition(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
Statement::For(ref var, ref start, ref stop, ref list) => {
try!(write!(f, "for {} in {}..{} do\n", var, start, stop));
for l in list {
try!(write!(f, "\t\t{}\n", l));
}
write!(f, "\tendfor")
},
Statement::Compiler(ref lhs, ref rhs) => write!(f, "# {} = {}", lhs, rhs),
}
}
@ -81,6 +90,13 @@ impl<T: Field> fmt::Debug for Statement<T> {
Statement::Return(ref expr) => write!(f, "Return({:?})", expr),
Statement::Definition(ref lhs, ref rhs) => write!(f, "Definition({:?}, {:?})", lhs, rhs),
Statement::Condition(ref lhs, ref rhs) => write!(f, "Condition({:?}, {:?})", lhs, rhs),
Statement::For(ref var, ref start, ref stop, ref list) => {
try!(write!(f, "for {:?} in {:?}..{:?} do\n", var, start, stop));
for l in list {
try!(write!(f, "\t\t{:?}\n", l));
}
write!(f, "\tendfor")
},
Statement::Compiler(ref lhs, ref rhs) => write!(f, "Compiler({:?}, {:?})", lhs, rhs),
}
}

View file

@ -27,8 +27,6 @@ pub trait Field : From<i32> + From<u32> + From<usize> + for<'a> From<&'a str>
+ Div<Self, Output=Self> + for<'a> Div<&'a Self, Output=Self>
+ Pow<usize, Output=Self> + Pow<Self, Output=Self> + for<'a> Pow<&'a Self, Output=Self>
{
/// Returns a byte slice of this `Field`'s contents in decimal `String` representation.
fn into_dec_bytes(&self) -> Vec<u8>;
/// Returns this `Field`'s contents as little-endian byte vector
fn into_byte_vector(&self) -> Vec<u8>;
/// Returns the multiplicative inverse, i.e.: self * self.inverse_mul() = Self::one()
@ -48,10 +46,6 @@ pub struct FieldPrime {
}
impl Field for FieldPrime {
fn into_dec_bytes(&self) -> Vec<u8> {
self.value.to_str_radix(10).to_string().into_bytes()
}
fn into_byte_vector(&self) -> Vec<u8> {
////for debugging
//println!("uint dec: {}\n",self.value.to_biguint().unwrap().to_str_radix(10));

View file

@ -355,6 +355,7 @@ impl Flattener {
};
statements_flattened.push(Statement::Condition(lhs, rhs));
},
Statement::For(..) => unimplemented!(),
s @ Statement::Compiler(..) => statements_flattened.push(s),
}
}

View file

@ -9,10 +9,6 @@ use self::libc::c_int;
use self::libc::uint8_t;
use field::Field;
#[cfg(test)]
use field::FieldPrime;
use num::bigint::{BigUint};
#[link(name = "snark")]
#[link(name = "supercop")]
#[link(name = "gmp")]
@ -74,6 +70,8 @@ fn vec_as_u8_32_array(vec: &Vec<u8>) -> [u8;32]{
#[cfg(test)]
mod tests {
use super::*;
use field::FieldPrime;
use num::bigint::{BigUint};
#[cfg(test)]
mod libsnark_integration {

View file

@ -55,7 +55,7 @@
//
use std::fmt;
use std::io::BufReader;
use std::io::{BufReader, Lines};
use std::io::prelude::*;
use std::fs::File;
use field::Field;
@ -106,6 +106,7 @@ enum Token<T: Field> {
Open, Close, Comma, Colon, Hash,
Eq, Return,
If, Then, Else, Fi,
For, In, Dotdot, Do, Endfor,
Lt, Le, Eqeq, Ge, Gt,
Add, Sub, Mult, Div, Pow,
Ide(String),
@ -128,6 +129,11 @@ impl<T: Field> fmt::Display for Token<T> {
Token::Then => write!(f, "then"),
Token::Else => write!(f, "else"),
Token::Fi => write!(f, "fi"),
Token::For => write!(f, "for"),
Token::In => write!(f, "in"),
Token::Dotdot => write!(f, ".."),
Token::Do => write!(f, "do"),
Token::Endfor => write!(f, "endfor"),
Token::Lt => write!(f, "<"),
Token::Le => write!(f, "<="),
Token::Eqeq => write!(f, "=="),
@ -228,6 +234,11 @@ fn next_token<T: Field>(input: &String, pos: &Position) -> (Token<T>, String, Po
Some(_) if input[offset..].starts_with("then ") => (Token::Then, input[offset + 5..].to_string(), Position { line: pos.line, col: pos.col + offset + 5 }),
Some(_) if input[offset..].starts_with("else ") => (Token::Else, input[offset + 5..].to_string(), Position { line: pos.line, col: pos.col + offset + 5 }),
Some(_) if input[offset..].starts_with("fi ") || input[offset..].to_string() == "fi" => (Token::Fi, input[offset + 2..].to_string(), Position { line: pos.line, col: pos.col + offset + 2 }),
Some(_) if input[offset..].starts_with("for ") => (Token::For, input[offset + 4..].to_string(), Position { line: pos.line, col: pos.col + offset + 4 }),
Some(_) if input[offset..].starts_with("in ") => (Token::In, input[offset + 3..].to_string(), Position { line: pos.line, col: pos.col + offset + 3 }),
Some(_) if input[offset..].starts_with("..") => (Token::Dotdot, input[offset + 2..].to_string(), Position { line: pos.line, col: pos.col + offset + 2 }),
Some(_) if input[offset..].starts_with("do ") || input[offset..].to_string() == "do" => (Token::Do, input[offset + 2..].to_string(), Position { line: pos.line, col: pos.col + offset + 2 }),
Some(_) if input[offset..].starts_with("endfor ") || input[offset..].to_string() == "endfor" => (Token::For, input[offset + 6..].to_string(), Position { line: pos.line, col: pos.col + offset + 6 }),
Some(x) => match x {
'0'...'9' => parse_num(&input[offset..].to_string(), &Position { line: pos.line, col: pos.col + offset }),
'a'...'z' | 'A'...'Z' => parse_ide(&input[offset..].to_string(), &Position { line: pos.line, col: pos.col + offset }),
@ -435,7 +446,7 @@ fn parse_statement1<T: Field>(ide: String, input: String, pos: Position) -> Resu
}
}
fn parse_statement<T: Field>(input: &String, pos: &Position) -> Result<(Statement<T>, String, Position), Error<T>> {
fn parse_statement<T: Field>(lines: &mut Lines<BufReader<File>>, input: &String, pos: &Position) -> Result<(Statement<T>, String, Position), Error<T>> {
match next_token::<T>(input, pos) {
(Token::Ide(x1), s1, p1) => parse_statement1(x1, s1, p1),
(Token::If, ..) |
@ -456,6 +467,62 @@ fn parse_statement<T: Field>(input: &String, pos: &Position) -> Result<(Statemen
},
Err(err) => Err(err),
},
(Token::For, s1, p1) => match parse_ide(&s1, &p1) {
(Token::Ide(x2), s2, p2) => match next_token(&s2, &p2) {
(Token::In, s3, p3) => match next_token(&s3, &p3) {
(Token::Num(x4), s4, p4) => match next_token(&s4, &p4) {
(Token::Dotdot, s5, p5) => match next_token(&s5, &p5) {
(Token::Num(x6), s6, p6) => match next_token(&s6, &p6) {
(Token::Do, s7, p7) => {
match next_token(&s7, &p7) {
(Token::Unknown(ref t8), ref s8, _) if t8 == "" => {
assert_eq!(s8, "");
},
(t8, _, p8) => return Err(Error { expected: vec![Token::Unknown("".to_string())], got: t8 , pos: p8 }),
}
let mut current_line = p7.line;
let mut statements = Vec::new();
loop {
current_line += 1;
match lines.next() {
Some(Ok(ref x)) if x.trim().starts_with("//") || x.trim() == "" => {}, // skip
Some(Ok(ref x)) if x.trim().starts_with("endfor") => {
let offset = skip_whitespaces(x);
let s8 = x[offset + 6..].to_string();
let p8 = Position{ line: current_line, col: offset + 7 };
match next_token(&s8, &p8) {
(Token::Unknown(ref t9), ref s9, _) if t9 == "" => {
assert_eq!(s9, "");
return Ok((Statement::For(x2, x4, x6, statements), s8, p8))
},
(t9, _, p9) => return Err(Error { expected: vec![Token::Unknown("1432567iuhgvfc".to_string())], got: t9 , pos: p9 }),
}
},
Some(Ok(ref x)) if !x.trim().starts_with("return") => match parse_statement(lines, x, &Position { line: current_line, col: 1 }) {
Ok((statement, ..)) => statements.push(statement),
Err(err) => return Err(err),
},
Some(Err(err)) => panic!("Error while reading Definitions: {}", err),
Some(Ok(ref x)) => {
let (t, ..) = next_token(x, &Position{ line: current_line, col: 1 });
return Err(Error { expected: vec![Token::ErrIde, Token::ErrNum, Token::If, Token::Open, Token::Hash, Token::For, Token::Endfor], got: t , pos: Position{ line: current_line, col: 1 } })
},
None => return Err(Error { expected: vec![Token::ErrIde, Token::ErrNum, Token::If, Token::Open, Token::Hash, Token::For], got: Token::Unknown("".to_string()) , pos: Position{ line: current_line, col: 1 } }),
}
};
},
(t7, _, p7) => Err(Error { expected: vec![Token::Do], got: t7 , pos: p7 }),
},
(t6, _, p6) => Err(Error { expected: vec![Token::ErrNum], got: t6 , pos: p6 }),
},
(t5, _, p5) => Err(Error { expected: vec![Token::Dotdot], got: t5 , pos: p5 }),
},
(t4, _, p4) => Err(Error { expected: vec![Token::ErrNum], got: t4 , pos: p4 }),
},
(t3, _, p3) => Err(Error { expected: vec![Token::In], got: t3 , pos: p3 }),
},
(t2, _, p2) => Err(Error { expected: vec![Token::ErrIde], got: t2 , pos: p2 }),
},
(Token::Hash, s1, p1) => match parse_ide(&s1, &p1) {
(Token::Ide(x2), s2, p2) => match next_token(&s2, &p2) {
(Token::Eq, s3, p3) => match parse_expr(&s3, &p3) {
@ -547,7 +614,7 @@ pub fn parse_program<T: Field>(file: File) -> Result<Prog<T>, Error<T>> {
loop {
match lines.next() {
Some(Ok(ref x)) if x.trim().starts_with("//") || x.trim() == "" => {}, // skip
Some(Ok(ref x)) => match parse_statement(x, &Position { line: current_line, col: 1 }) {
Some(Ok(ref x)) => match parse_statement(&mut lines, x, &Position { line: current_line, col: 1 }) {
Ok((statement @ Statement::Return(_), ..)) => {
if !got_return {
got_return = true;

View file

@ -258,6 +258,7 @@ pub fn r1cs_program<T: Field>(prog: &Prog<T>) -> (Vec<String>, Vec<Vec<(usize, T
Statement::Return(ref expr) => r1cs_expression(Identifier("~out".to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::Definition(ref id, ref expr) => r1cs_expression(Identifier(id.to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::Condition(ref expr1, ref expr2) => r1cs_expression(expr1.clone(), expr2.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::For(..) => unimplemented!(),
Statement::Compiler(..) => continue,
}
a.push(a_row);