Added r1cs ppzksnark proving scheme and some tests.
This commit is contained in:
+40
-6
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user