Added r1cs ppzksnark proving scheme and some tests.

This commit is contained in:
Sean Bowe
2015-12-25 05:52:14 -07:00
parent a66c21fe11
commit fc1bdf2148
5 changed files with 317 additions and 31 deletions
+40 -6
View File
@@ -1,10 +1,13 @@
#![feature(box_syntax)]
#![allow(improper_ctypes)]
//#![cfg_attr(test, feature(test))]
extern crate libc;
mod arith;
mod r1cs;
pub use self::arith::*;
pub use self::r1cs::*;
use std::sync::{Once, ONCE_INIT};
@@ -13,7 +16,6 @@ static mut INITIALIZED: bool = false;
extern "C" {
fn tinysnark_init_public_params();
fn tinysnark_test();
}
pub fn init() {
@@ -27,16 +29,48 @@ pub fn is_initialized() -> bool {
unsafe { INITIALIZED }
}
pub fn test() {
unsafe { tinysnark_test(); }
}
#[cfg(test)]
mod tests {
//extern crate test;
use super::{init, FieldT};
use super::{init, FieldT, Proof, Keypair, LinearTerm, ConstraintSystem};
//use self::test::Bencher;
#[test]
fn test_zk() {
init();
{
let mut cs = ConstraintSystem::new(1, 2);
// zkpok { (a, b) c = a * b }
cs.add_constraint(
&[LinearTerm{coeff: FieldT::one(), index: 2}],
&[LinearTerm{coeff: FieldT::one(), index: 3}],
&[LinearTerm{coeff: FieldT::one(), index: 1}]
);
assert!(cs.test(&[10.into()], &[5.into(), 2.into()]));
assert!(!cs.test(&[10.into()], &[6.into(), 2.into()]));
let kp = Keypair::new(&cs);
let proof = Proof::new(&kp, &cs, &[10.into()], &[5.into(), 2.into()]);
assert!(proof.verify(&kp, &cs, &[10.into()]));
}
{
let mut cs = ConstraintSystem::new(0, 1);
// simple boolean constraint
cs.add_constraint(
&[LinearTerm{coeff: FieldT::one(), index: 0}, LinearTerm{coeff: -FieldT::one(), index: 1}],
&[LinearTerm{coeff: FieldT::one(), index: 1}],
&[LinearTerm{coeff: FieldT::zero(), index: 0}]
);
assert!(cs.test(&[], &[1.into()]));
assert!(cs.test(&[], &[0.into()]));
assert!(!cs.test(&[], &[2.into()]));
let kp = Keypair::new(&cs);
let proof = Proof::new(&kp, &cs, &[], &[1.into()]);
assert!(proof.verify(&kp, &cs, &[]));
}
}
#[test]
fn test_one() {
init();
+144
View File
@@ -0,0 +1,144 @@
use libc::{size_t};
use super::arith::FieldT;
#[repr(C)]
struct R1ConstraintSystem;
#[repr(C)]
pub struct LinearTerm {
pub coeff: FieldT,
pub index: size_t
}
extern "C" {
fn tinysnark_new_r1cs(primary: size_t, aux: size_t) -> *mut R1ConstraintSystem;
fn tinysnark_drop_r1cs(cs: *mut R1ConstraintSystem);
fn tinysnark_satisfy_test(cs: *mut R1ConstraintSystem, primary: *const FieldT, aux: *const FieldT) -> bool;
fn tinysnark_add_constraint(cs: *mut R1ConstraintSystem,
a: *const LinearTerm,
a_len: size_t,
b: *const LinearTerm,
b_len: size_t,
c: *const LinearTerm,
c_len: size_t
);
}
pub struct ConstraintSystem {
cs: *mut R1ConstraintSystem,
primary_size: usize,
aux_size: usize
}
impl Drop for ConstraintSystem {
fn drop(&mut self) {
unsafe { tinysnark_drop_r1cs(self.cs) }
}
}
impl ConstraintSystem {
pub fn new(primary_size: usize, aux_size: usize) -> ConstraintSystem {
ConstraintSystem {
cs: unsafe { tinysnark_new_r1cs(primary_size, aux_size) },
primary_size: primary_size,
aux_size: aux_size
}
}
pub fn add_constraint(&mut self, a: &[LinearTerm], b: &[LinearTerm], c: &[LinearTerm])
{
unsafe {
tinysnark_add_constraint(
self.cs,
a.get_unchecked(0),
a.len(),
b.get_unchecked(0),
b.len(),
c.get_unchecked(0),
c.len()
);
}
}
pub fn test(&mut self, primary: &[FieldT], aux: &[FieldT]) -> bool
{
assert_eq!(primary.len(), self.primary_size);
assert_eq!(aux.len(), self.aux_size);
unsafe {
tinysnark_satisfy_test(self.cs, primary.get_unchecked(0), aux.get_unchecked(0))
}
}
}
#[repr(C)]
struct R1CSKeypair;
pub struct Keypair {
kp: *mut R1CSKeypair
}
impl Keypair {
pub fn new(constraint_system: &ConstraintSystem) -> Keypair {
Keypair {
kp: unsafe { tinysnark_gen_keypair(constraint_system.cs) }
}
}
}
impl Drop for Keypair {
fn drop(&mut self) {
unsafe { tinysnark_drop_keypair(self.kp) }
}
}
extern "C" {
fn tinysnark_gen_keypair(cs: *mut R1ConstraintSystem) -> *mut R1CSKeypair;
fn tinysnark_drop_keypair(cs: *mut R1CSKeypair);
}
#[repr(C)]
struct R1CSProof;
pub struct Proof {
proof: *mut R1CSProof
}
impl Proof {
pub fn new(keypair: &Keypair, constraint_system: &ConstraintSystem, primary: &[FieldT], aux: &[FieldT])
-> Proof
{
assert_eq!(primary.len(), constraint_system.primary_size);
assert_eq!(aux.len(), constraint_system.aux_size);
unsafe {
Proof {
proof: tinysnark_gen_proof(keypair.kp, constraint_system.cs, primary.get_unchecked(0), aux.get_unchecked(0))
}
}
}
pub fn verify(&self, keypair: &Keypair, constraint_system: &ConstraintSystem, primary: &[FieldT]) -> bool {
unsafe {
tinysnark_verify_proof(self.proof, keypair.kp, constraint_system.cs, primary.get_unchecked(0))
}
}
}
impl Drop for Proof {
fn drop(&mut self) {
unsafe { tinysnark_drop_proof(self.proof) }
}
}
extern "C" {
fn tinysnark_gen_proof(keypair: *mut R1CSKeypair,
cs: *mut R1ConstraintSystem,
primary: *const FieldT,
aux: *const FieldT) -> *mut R1CSProof;
fn tinysnark_verify_proof(proof: *mut R1CSProof,
keypair: *mut R1CSKeypair,
cs: *mut R1ConstraintSystem,
primary: *const FieldT) -> bool;
fn tinysnark_drop_proof(proof: *mut R1CSProof);
}