mirror of https://github.com/zcash/mpc.git
Foundations of libsnark interaction and BN curve operation wrappers.
This commit is contained in:
parent
34aa24a040
commit
d01e48b800
|
@ -0,0 +1,3 @@
|
|||
[submodule "libsnark"]
|
||||
path = libsnark
|
||||
url = https://github.com/zcash/libsnark.git
|
|
@ -1,4 +1,24 @@
|
|||
[root]
|
||||
name = "mpc"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
|
|
|
@ -9,4 +9,11 @@ authors = [
|
|||
license = "MIT OR Apache-2.0"
|
||||
readme = "README.md"
|
||||
|
||||
build = "src/build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
gcc = "0.3.*"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.*"
|
||||
lazy_static = "0.1.*"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a7031481fd8d2360337321401fe8e24f0359317a
|
|
@ -0,0 +1,62 @@
|
|||
#include <sodium.h>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
#include <assert.h>
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
#include "algebra/curves/public_params.hpp"
|
||||
#include "relations/arithmetic_programs/qap/qap.hpp"
|
||||
#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace libsnark;
|
||||
|
||||
typedef Fr<alt_bn128_pp> FieldT;
|
||||
|
||||
extern "C" void bnwrap_init() {
|
||||
assert(sodium_init() != -1);
|
||||
init_alt_bn128_params();
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_zero() {
|
||||
return alt_bn128_G1::zero();
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_one() {
|
||||
return alt_bn128_G1::one();
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_random() {
|
||||
return alt_bn128_G1::random_element();
|
||||
}
|
||||
|
||||
extern "C" bool bnwrap_G1_is_zero(alt_bn128_G1 *p) {
|
||||
return p->is_zero();
|
||||
}
|
||||
|
||||
extern "C" bool bnwrap_G1_is_equal(alt_bn128_G1 *p, alt_bn128_G1 *q) {
|
||||
return *p == *q;
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_add(alt_bn128_G1 *p, alt_bn128_G1 *q) {
|
||||
return *p + *q;
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_sub(alt_bn128_G1 *p, alt_bn128_G1 *q) {
|
||||
return *p - *q;
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_neg(alt_bn128_G1 *p) {
|
||||
return -(*p);
|
||||
}
|
||||
|
||||
extern "C" alt_bn128_G1 bnwrap_G1_scalarmul(alt_bn128_G1 *p, FieldT *q) {
|
||||
return (*q) * (*p);
|
||||
}
|
||||
|
||||
extern "C" FieldT bnwrap_fr_from(const char *a) {
|
||||
return FieldT(a);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
extern crate gcc;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-link-lib=gmp");
|
||||
println!("cargo:rustc-link-lib=gmpxx");
|
||||
println!("cargo:rustc-link-lib=sodium");
|
||||
|
||||
let mut cfg = gcc::Config::new();
|
||||
|
||||
cfg.cpp(true)
|
||||
.define("NO_PROCPS", None)
|
||||
.define("STATIC", None)
|
||||
.define("CURVE_ALT_BN128", None)
|
||||
.define("MONTGOMERY_OUTPUT", None)
|
||||
.define("USE_ASM", None)
|
||||
.define("NO_PT_COMPRESSION", None)
|
||||
.define("BINARY_OUTPUT", None)
|
||||
.flag("-std=c++11")
|
||||
.include("libsnark/src")
|
||||
.file("libsnark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp")
|
||||
.file("libsnark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp")
|
||||
.file("libsnark/src/algebra/curves/alt_bn128/alt_bn128_init.cpp")
|
||||
.file("libsnark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp")
|
||||
.file("libsnark/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp")
|
||||
.file("libsnark/src/common/utils.cpp")
|
||||
.file("libsnark/src/common/profiling.cpp")
|
||||
.file("src/bnwrap.cpp")
|
||||
;
|
||||
|
||||
cfg.compile("libbnwrap.a");
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
use super::{Fr,GroupElement};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct G1 {
|
||||
x: [u64; 4],
|
||||
y: [u64; 4],
|
||||
z: [u64; 4]
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn bnwrap_G1_zero() -> G1;
|
||||
fn bnwrap_G1_one() -> G1;
|
||||
fn bnwrap_G1_random() -> G1;
|
||||
|
||||
fn bnwrap_G1_is_zero(p: *const G1) -> bool;
|
||||
fn bnwrap_G1_is_equal(p: *const G1, q: *const G1) -> bool;
|
||||
|
||||
fn bnwrap_G1_add(p: *const G1, q: *const G1) -> G1;
|
||||
fn bnwrap_G1_sub(p: *const G1, q: *const G1) -> G1;
|
||||
fn bnwrap_G1_neg(p: *const G1) -> G1;
|
||||
fn bnwrap_G1_scalarmul(p: *const G1, s: *const Fr) -> G1;
|
||||
}
|
||||
|
||||
impl GroupElement for G1 {
|
||||
fn zero() -> G1 {
|
||||
unsafe { bnwrap_G1_zero() }
|
||||
}
|
||||
|
||||
fn one() -> G1 {
|
||||
unsafe { bnwrap_G1_one() }
|
||||
}
|
||||
|
||||
fn is_equal(&self, other: &Self) -> bool {
|
||||
unsafe { bnwrap_G1_is_equal(self, other) }
|
||||
}
|
||||
|
||||
fn random() -> G1 {
|
||||
unsafe { bnwrap_G1_random() }
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
unsafe { bnwrap_G1_is_zero(self) }
|
||||
}
|
||||
|
||||
fn arith_neg(&self) -> Self {
|
||||
unsafe { bnwrap_G1_neg(self) }
|
||||
}
|
||||
|
||||
fn arith_add(&self, other: &Self) -> Self {
|
||||
unsafe { bnwrap_G1_add(self, other) }
|
||||
}
|
||||
|
||||
fn arith_sub(&self, other: &Self) -> Self {
|
||||
unsafe { bnwrap_G1_sub(self, other) }
|
||||
}
|
||||
|
||||
fn arith_mul(&self, other: &Fr) -> Self {
|
||||
unsafe { bnwrap_G1_scalarmul(self, other) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
use std::ops::{Add,Sub,Mul,Neg};
|
||||
use std::sync::Mutex;
|
||||
use libc::c_char;
|
||||
use std::ffi::CString;
|
||||
|
||||
mod g1;
|
||||
|
||||
pub type G1 = G<g1::G1>;
|
||||
|
||||
extern "C" {
|
||||
fn bnwrap_init();
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref INIT_LOCK: Mutex<bool> = Mutex::new(false);
|
||||
}
|
||||
|
||||
/// This must be called before anything in this module is used.
|
||||
pub fn initialize() {
|
||||
let mut l = INIT_LOCK.lock().unwrap();
|
||||
|
||||
if !*l {
|
||||
unsafe { bnwrap_init(); }
|
||||
*l = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// The scalar field for the curve construction we use.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Fr([u64; 4]);
|
||||
|
||||
extern "C" {
|
||||
fn bnwrap_fr_from(s: *const c_char) -> Fr;
|
||||
}
|
||||
|
||||
impl Fr {
|
||||
pub fn from_str(s: &'static str) -> Self {
|
||||
for c in s.chars() {
|
||||
if c != '0' &&
|
||||
c != '1' &&
|
||||
c != '2' &&
|
||||
c != '3' &&
|
||||
c != '4' &&
|
||||
c != '5' &&
|
||||
c != '6' &&
|
||||
c != '7' &&
|
||||
c != '8' &&
|
||||
c != '9' {
|
||||
panic!("character out of range")
|
||||
}
|
||||
}
|
||||
|
||||
let s = CString::new(s).unwrap();
|
||||
|
||||
unsafe { bnwrap_fr_from(s.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GroupElement: Sized + Copy + Clone {
|
||||
fn zero() -> Self;
|
||||
fn one() -> Self;
|
||||
fn random() -> Self;
|
||||
|
||||
fn is_equal(&self, other: &Self) -> bool;
|
||||
fn is_zero(&self) -> bool;
|
||||
|
||||
fn arith_neg(&self) -> Self;
|
||||
fn arith_add(&self, other: &Self) -> Self;
|
||||
fn arith_sub(&self, other: &Self) -> Self;
|
||||
fn arith_mul(&self, other: &Fr) -> Self;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct G<T: GroupElement>(T);
|
||||
|
||||
impl<T: GroupElement> G<T> {
|
||||
pub fn zero() -> Self {
|
||||
G(T::zero())
|
||||
}
|
||||
|
||||
pub fn one() -> Self {
|
||||
G(T::one())
|
||||
}
|
||||
|
||||
pub fn random() -> Self {
|
||||
G(T::random())
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.0.is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GroupElement> PartialEq for G<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.is_equal(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GroupElement> Neg for &'a G<T> {
|
||||
type Output = G<T>;
|
||||
|
||||
fn neg(self) -> G<T> {
|
||||
G(self.0.arith_neg())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: GroupElement> Add<&'a G<T>> for &'b G<T> {
|
||||
type Output = G<T>;
|
||||
|
||||
fn add(self, other: &G<T>) -> G<T> {
|
||||
G(self.0.arith_add(&other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: GroupElement> Sub<&'a G<T>> for &'b G<T> {
|
||||
type Output = G<T>;
|
||||
|
||||
fn sub(self, other: &G<T>) -> G<T> {
|
||||
G(self.0.arith_sub(&other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: GroupElement> Mul<&'a Fr> for &'b G<T> {
|
||||
type Output = G<T>;
|
||||
|
||||
fn mul(self, other: &Fr) -> G<T> {
|
||||
G(self.0.arith_mul(other))
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
use super::{G, Fr, g1, initialize, GroupElement};
|
||||
|
||||
fn test_associative<Group: GroupElement>() {
|
||||
for _ in 0..50 {
|
||||
let a = G::<Group>::random();
|
||||
let b = G::<Group>::random();
|
||||
let c = G::<Group>::random();
|
||||
|
||||
let x = &(&a + &b) + &c;
|
||||
let y = &(&a + &c) + &b;
|
||||
|
||||
assert!(x == y);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_scalar_mul<Group: GroupElement>() {
|
||||
let r = G::<Group>::random();
|
||||
let res = &r * &Fr::from_str("16");
|
||||
|
||||
let mut acc = G::<Group>::zero();
|
||||
|
||||
for _ in 0..16 {
|
||||
acc = &acc + &r;
|
||||
}
|
||||
|
||||
assert!(acc == res);
|
||||
}
|
||||
|
||||
fn test_addition<Group: GroupElement>() {
|
||||
{
|
||||
let a = G::<Group>::random();
|
||||
let b = -(&a);
|
||||
let c = &a + &b;
|
||||
|
||||
assert!(c.is_zero());
|
||||
}
|
||||
{
|
||||
let a = G::<Group>::random();
|
||||
let b = -(&a);
|
||||
let c = &a - &b;
|
||||
let d = &a * &Fr::from_str("2");
|
||||
|
||||
assert!(c == d);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_primitives<Group: GroupElement>() {
|
||||
let a = G::<Group>::zero();
|
||||
let b = G::<Group>::one();
|
||||
|
||||
assert_eq!(a.is_zero(), true);
|
||||
assert_eq!(b.is_zero(), false);
|
||||
}
|
||||
|
||||
fn test_group_ops<Group: GroupElement>() {
|
||||
test_associative::<Group>();
|
||||
test_primitives::<Group>();
|
||||
test_scalar_mul::<Group>();
|
||||
test_addition::<Group>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1() {
|
||||
initialize();
|
||||
|
||||
test_group_ops::<g1::G1>();
|
||||
}
|
||||
}
|
10
src/main.rs
10
src/main.rs
|
@ -1,3 +1,11 @@
|
|||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
mod curve;
|
||||
|
||||
use curve::*;
|
||||
|
||||
fn main() {
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue