diff --git a/src/bnwrap.cpp b/src/bnwrap.cpp index a571e1e..ccbdc7e 100644 --- a/src/bnwrap.cpp +++ b/src/bnwrap.cpp @@ -21,6 +21,12 @@ extern "C" void bnwrap_init() { init_alt_bn128_params(); } +extern "C" FieldT bnwrap_fr_from(const char *a) { + return FieldT(a); +} + +// G1 + extern "C" alt_bn128_G1 bnwrap_G1_zero() { return alt_bn128_G1::zero(); } @@ -57,6 +63,40 @@ 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); +// G2 + +extern "C" alt_bn128_G2 bnwrap_G2_zero() { + return alt_bn128_G2::zero(); +} + +extern "C" alt_bn128_G2 bnwrap_G2_one() { + return alt_bn128_G2::one(); +} + +extern "C" alt_bn128_G2 bnwrap_G2_random() { + return alt_bn128_G2::random_element(); +} + +extern "C" bool bnwrap_G2_is_zero(alt_bn128_G2 *p) { + return p->is_zero(); +} + +extern "C" bool bnwrap_G2_is_equal(alt_bn128_G2 *p, alt_bn128_G2 *q) { + return *p == *q; +} + +extern "C" alt_bn128_G2 bnwrap_G2_add(alt_bn128_G2 *p, alt_bn128_G2 *q) { + return *p + *q; +} + +extern "C" alt_bn128_G2 bnwrap_G2_sub(alt_bn128_G2 *p, alt_bn128_G2 *q) { + return *p - *q; +} + +extern "C" alt_bn128_G2 bnwrap_G2_neg(alt_bn128_G2 *p) { + return -(*p); +} + +extern "C" alt_bn128_G2 bnwrap_G2_scalarmul(alt_bn128_G2 *p, FieldT *q) { + return (*q) * (*p); } diff --git a/src/curve/g2.rs b/src/curve/g2.rs new file mode 100644 index 0000000..4045000 --- /dev/null +++ b/src/curve/g2.rs @@ -0,0 +1,61 @@ +use super::{Fr,GroupElement}; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct G2 { + x: [u64; 8], + y: [u64; 8], + z: [u64; 8] +} + +extern "C" { + fn bnwrap_G2_zero() -> G2; + fn bnwrap_G2_one() -> G2; + fn bnwrap_G2_random() -> G2; + + fn bnwrap_G2_is_zero(p: *const G2) -> bool; + fn bnwrap_G2_is_equal(p: *const G2, q: *const G2) -> bool; + + fn bnwrap_G2_add(p: *const G2, q: *const G2) -> G2; + fn bnwrap_G2_sub(p: *const G2, q: *const G2) -> G2; + fn bnwrap_G2_neg(p: *const G2) -> G2; + fn bnwrap_G2_scalarmul(p: *const G2, s: *const Fr) -> G2; +} + +impl GroupElement for G2 { + fn zero() -> G2 { + unsafe { bnwrap_G2_zero() } + } + + fn one() -> G2 { + unsafe { bnwrap_G2_one() } + } + + fn is_equal(&self, other: &Self) -> bool { + unsafe { bnwrap_G2_is_equal(self, other) } + } + + fn random() -> G2 { + unsafe { bnwrap_G2_random() } + } + + fn is_zero(&self) -> bool { + unsafe { bnwrap_G2_is_zero(self) } + } + + fn arith_neg(&self) -> Self { + unsafe { bnwrap_G2_neg(self) } + } + + fn arith_add(&self, other: &Self) -> Self { + unsafe { bnwrap_G2_add(self, other) } + } + + fn arith_sub(&self, other: &Self) -> Self { + unsafe { bnwrap_G2_sub(self, other) } + } + + fn arith_mul(&self, other: &Fr) -> Self { + unsafe { bnwrap_G2_scalarmul(self, other) } + } +} diff --git a/src/curve/mod.rs b/src/curve/mod.rs index 1959312..ee6c01d 100644 --- a/src/curve/mod.rs +++ b/src/curve/mod.rs @@ -4,8 +4,10 @@ use libc::c_char; use std::ffi::CString; mod g1; +mod g2; pub type G1 = G; +pub type G2 = G; extern "C" { fn bnwrap_init(); @@ -35,7 +37,7 @@ extern "C" { } impl Fr { - pub fn from_str(s: &'static str) -> Self { + pub fn from_str(s: &str) -> Self { for c in s.chars() { if c != '0' && c != '1' && @@ -131,7 +133,17 @@ impl<'a, 'b, T: GroupElement> Mul<&'a Fr> for &'b G { } mod test { - use super::{G, Fr, g1, initialize, GroupElement}; + use super::{G, Fr, g1, g2, initialize, GroupElement}; + + fn test_allocations_and_moves() { + let a: Vec> = (0..100) + .map(|i| (&G::one() * &Fr::from_str(&format!("{}", i)))) + .collect(); + + let b = a.into_iter().fold(G::zero(), |a, b| &a + &b); + + assert!(b == &G::one() * &Fr::from_str("4950")); + } fn test_associative() { for _ in 0..50 { @@ -190,6 +202,7 @@ mod test { test_primitives::(); test_scalar_mul::(); test_addition::(); + test_allocations_and_moves::(); } #[test] @@ -198,4 +211,11 @@ mod test { test_group_ops::(); } + + #[test] + fn test_g2() { + initialize(); + + test_group_ops::(); + } }