Add basic field arithmetic.
This commit is contained in:
parent
8e0af61ba4
commit
0b8b52cb41
|
@ -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"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
This is a tiny wrapper around libsnark's r1cs_ppzksnark on ALT_BN128.
|
|
@ -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 { }
|
|
@ -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();
|
||||
}
|
||||
|
||||
pub fn 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_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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue