Add basic field arithmetic.

This commit is contained in:
Sean Bowe 2015-12-25 00:30:10 -07:00
parent 8e0af61ba4
commit 0b8b52cb41
5 changed files with 219 additions and 13 deletions

View File

@ -1,13 +1,16 @@
[package]
name = "tinysnark"
homepage = "https://github.com/ebfull/bellman"
repository = "https://github.com/ebfull/bellman"
documentation = "https://github.com/ebfull/bellman"
license = "MIT"
description = "Tiny libsnark bindings"
version = "0.0.1"
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
build = "build.rs"
description = "Tiny libsnark bindings"
documentation = "https://github.com/ebfull/bellman"
homepage = "https://github.com/ebfull/bellman"
license = "MIT"
name = "tinysnark"
repository = "https://github.com/ebfull/bellman"
version = "0.0.1"
[build-dependencies]
gcc = "0.3"
[dependencies]
libc = "0.2.4"

1
tinysnark/README.md Normal file
View File

@ -0,0 +1 @@
This is a tiny wrapper around libsnark's r1cs_ppzksnark on ALT_BN128.

94
tinysnark/src/arith.rs Normal file
View File

@ -0,0 +1,94 @@
use libc::{c_ulong, c_long};
use std::ops::{Neg, Add, Mul};
extern "C" {
fn tinysnark_fieldt_zero() -> FieldT;
fn tinysnark_fieldt_one() -> FieldT;
fn tinysnark_fieldt_neg(val: FieldT) -> FieldT;
fn tinysnark_fieldt_inverse(val: FieldT) -> FieldT;
fn tinysnark_fieldt_from_long(val: c_long) -> FieldT;
fn tinysnark_long_from_fieldt(val: FieldT) -> c_ulong;
fn tinysnark_fieldt_mul(a: FieldT, b: FieldT) -> FieldT;
fn tinysnark_fieldt_add(a: FieldT, b: FieldT) -> FieldT;
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct FieldT([u8; 32]);
impl FieldT {
#[inline(always)]
pub fn one() -> FieldT {
unsafe { tinysnark_fieldt_one() }
}
#[inline(always)]
pub fn zero() -> FieldT {
unsafe { tinysnark_fieldt_zero() }
}
#[inline(always)]
pub fn inverse(self) -> FieldT {
unsafe { tinysnark_fieldt_inverse(self) }
}
#[cfg(test)]
pub fn debug_equal(&self, is: [u8; 32]) -> bool {
&FieldT(is) == self
}
}
impl From<i64> for FieldT {
#[inline(always)]
fn from(num: i64) -> FieldT {
unsafe { tinysnark_fieldt_from_long(num) }
}
}
impl From<FieldT> for u64 {
#[inline(always)]
fn from(num: FieldT) -> u64 {
unsafe { tinysnark_long_from_fieldt(num) }
}
}
impl Neg for FieldT {
type Output = FieldT;
#[inline(always)]
fn neg(self) -> FieldT {
unsafe { tinysnark_fieldt_neg(self) }
}
}
impl Add for FieldT {
type Output = FieldT;
#[inline(always)]
fn add(self, other: FieldT) -> FieldT {
unsafe { tinysnark_fieldt_add(self, other) }
}
}
impl Mul for FieldT {
type Output = FieldT;
#[inline(always)]
fn mul(self, other: FieldT) -> FieldT {
unsafe { tinysnark_fieldt_mul(self, other) }
}
}
impl PartialEq for FieldT {
fn eq(&self, other: &FieldT) -> bool {
for i in 0..32 {
if (self.0)[i] != (other.0)[i] {
return false;
}
}
true
}
}
impl Eq for FieldT { }

View File

@ -1,9 +1,81 @@
#![feature(box_syntax, test)]
extern crate libc;
mod arith;
pub use self::arith::*;
use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;
static mut INITIALIZED: bool = false;
extern "C" {
fn tinysnark_init_public_params();
fn tinysnark_test();
fn tinysnark_init_public_params();
fn tinysnark_test();
}
pub fn init() {
START.call_once(|| {
unsafe { tinysnark_init_public_params(); }
unsafe { INITIALIZED = true; }
});
}
pub fn is_initialized() -> bool {
unsafe { INITIALIZED }
}
pub fn test() {
unsafe { tinysnark_init_public_params(); }
unsafe { tinysnark_test(); }
unsafe { tinysnark_test(); }
}
#[cfg(test)]
mod tests {
extern crate test;
use super::{init, FieldT};
use self::test::Bencher;
#[test]
fn test_one() {
init();
let one = FieldT::one();
let negone = -one;
let newone = -negone;
assert!(one == newone);
assert!(one != negone);
assert!(newone != negone);
assert_eq!(one, 1.into());
assert_eq!(negone, (-1).into());
assert!(one.debug_equal([251, 255, 255, 79, 28, 52, 150, 172, 41, 205, 96, 159, 149, 118, 252, 54, 46, 70, 121, 120, 111, 163, 110, 102, 47, 223, 7, 154, 193, 119, 10, 14]));
assert!(negone.debug_equal([6, 0, 0, 160, 119, 193, 75, 151, 103, 163, 88, 218, 178, 113, 55, 241, 46, 18, 8, 9, 71, 162, 225, 81, 250, 192, 41, 71, 177, 214, 89, 34]));
}
#[test]
fn test_math() {
init();
assert_eq!(FieldT::one() + 10.into(), 11.into());
assert_eq!(FieldT::from(2) + 2.into(), FieldT::from(2) * 2.into());
assert_eq!(FieldT::from(2), FieldT::from(-1) + FieldT::one() * 3.into());
assert_eq!(FieldT::one(), FieldT::from(100) * FieldT::from(100).inverse());
}
#[test]
fn test_conversions() {
init();
for i in 0..10000 {
let num: FieldT = i.into();
let back: u64 = num.into();
assert_eq!(i, back as i64);
}
assert_eq!(u64::from(FieldT::from(-1)), 4891460686036598784);
}
}

View File

@ -11,13 +11,49 @@ zk-SNARK support using the ALT_BN128 curve.
using namespace libsnark;
using namespace std;
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
extern "C" FieldT tinysnark_fieldt_mul(FieldT a, FieldT b) {
return a * b;
}
extern "C" FieldT tinysnark_fieldt_add(FieldT a, FieldT b) {
return a + b;
}
extern "C" unsigned long tinysnark_long_from_fieldt(FieldT num) {
return num.as_bigint().as_ulong();
}
extern "C" FieldT tinysnark_fieldt_from_long(long num) {
return FieldT(num);
}
extern "C" FieldT tinysnark_fieldt_one() {
return FieldT::one();
}
extern "C" FieldT tinysnark_fieldt_zero() {
return FieldT::zero();
}
extern "C" FieldT tinysnark_fieldt_neg(FieldT val) {
return -val;
}
extern "C" FieldT tinysnark_fieldt_inverse(FieldT val) {
return val.inverse();
}
extern "C" void tinysnark_init_public_params() {
default_r1cs_ppzksnark_pp::init_public_params();
{
auto p = FieldT::one();
assert(sizeof(p) == 32);
}
}
extern "C" void tinysnark_test() {
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
protoboard<FieldT> pb;
linear_combination<FieldT> sum;