diff --git a/snark/src/lib.rs b/snark/src/lib.rs index da79222..cf7d559 100644 --- a/snark/src/lib.rs +++ b/snark/src/lib.rs @@ -26,18 +26,18 @@ extern "C" { lc2: *const G2, d: libc::uint64_t, vars: libc::uint64_t, - At: *mut G1, - Bt1: *mut G1, - Bt2: *mut G2, - Ct: *mut G1); + at: *mut G1, + bt1: *mut G1, + bt2: *mut G2, + ct: *mut G1); fn libsnarkwrap_test_eval( cs: *const libc::c_void, tau: *const Fr, vars: libc::uint64_t, - At: *const G1, - Bt1: *const G1, - Bt2: *const G2, - Ct: *const G1) -> bool; + at: *const G1, + bt1: *const G1, + bt2: *const G2, + ct: *const G1) -> bool; fn libsnarkwrap_test_compare_tau( i1: *const G1, i2: *const G2, @@ -68,44 +68,49 @@ pub struct CS { } impl CS { - pub fn test_eval(&self, tau: &Fr, At: &[G1], Bt1: &[G1], Bt2: &[G2], Ct: &[G1]) -> bool { - assert_eq!(At.len(), Bt1.len()); - assert_eq!(Bt1.len(), Bt2.len()); - assert_eq!(Bt2.len(), Ct.len()); + pub fn test_compare_tau(&self, v1: &[G1], v2: &[G2], tau: &Fr) -> bool { + assert_eq!(v1.len(), v2.len()); + unsafe { libsnarkwrap_test_compare_tau(&v1[0], &v2[0], tau, v1.len() as u64, self.ptr) } + } + + pub fn test_eval(&self, tau: &Fr, at: &[G1], bt1: &[G1], bt2: &[G2], ct: &[G1]) -> bool { + assert_eq!(at.len(), bt1.len()); + assert_eq!(bt1.len(), bt2.len()); + assert_eq!(bt2.len(), ct.len()); unsafe { libsnarkwrap_test_eval(self.ptr, tau, - At.len() as u64, - &At[0], - &Bt1[0], - &Bt2[0], - &Ct[0]) + at.len() as u64, + &at[0], + &bt1[0], + &bt2[0], + &ct[0]) } } pub fn eval(&self, - Lt1: &[G1], - Lt2: &[G2], - At: &mut [G1], - Bt1: &mut [G1], - Bt2: &mut [G2], - Ct: &mut [G1]) { - assert_eq!(Lt1.len(), Lt2.len()); - assert_eq!(At.len(), Bt1.len()); - assert_eq!(Bt1.len(), Bt2.len()); - assert_eq!(Bt2.len(), Ct.len()); + lt1: &[G1], + lt2: &[G2], + at: &mut [G1], + bt1: &mut [G1], + bt2: &mut [G2], + ct: &mut [G1]) { + assert_eq!(lt1.len(), lt2.len()); + assert_eq!(at.len(), bt1.len()); + assert_eq!(bt1.len(), bt2.len()); + assert_eq!(bt2.len(), ct.len()); unsafe { libsnarkwrap_eval(self.ptr, - &Lt1[0], - &Lt2[0], - Lt1.len() as u64, - At.len() as u64, - &mut At[0], - &mut Bt1[0], - &mut Bt2[0], - &mut Ct[0]); + <1[0], + <2[0], + lt1.len() as u64, + at.len() as u64, + &mut at[0], + &mut bt1[0], + &mut bt2[0], + &mut ct[0]); } } } @@ -132,13 +137,6 @@ pub fn getcs() -> CS { } } -/// Check that the lagrange coefficients computed by tau over -/// G1 equal the expected vector. -pub fn compare_tau(v1: &[G1], v2: &[G2], tau: &Fr, cs: &CS) -> bool { - assert_eq!(v1.len(), v2.len()); - unsafe { libsnarkwrap_test_compare_tau(&v1[0], &v2[0], tau, v1.len() as u64, cs.ptr) } -} - pub trait Pairing { fn g1<'a>(&'a self, other: &'a Other) -> &'a G1; fn g2<'a>(&'a self, other: &'a Other) -> &'a G2; diff --git a/snark/src/libsnarkwrap.cpp b/snark/src/libsnarkwrap.cpp index 4cb925c..fbff875 100644 --- a/snark/src/libsnarkwrap.cpp +++ b/snark/src/libsnarkwrap.cpp @@ -207,28 +207,6 @@ extern "C" void libsnarkwrap_dropcs(r1cs_constraint_system *cs) delete cs; } -extern "C" bool libsnarkwrap_test_compare_tau( - const curve_G1 *inputs1, - const curve_G2 *inputs2, - const curve_Fr *tau, - uint64_t d, - const r1cs_constraint_system *cs -) -{ - auto qap = r1cs_to_qap_instance_map(*cs); - auto coeffs = qap.domain->lagrange_coeffs(*tau); - assert(coeffs.size() == d); - assert(qap.degree() == d); - - bool res = true; - for (size_t i = 0; i < d; i++) { - res &= (coeffs[i] * curve_G1::one()) == inputs1[i]; - res &= (coeffs[i] * curve_G2::one()) == inputs2[i]; - } - - return res; -} - extern "C" void libsnarkwrap_eval( const r1cs_constraint_system *cs, const curve_G1 *lc1, @@ -266,6 +244,30 @@ extern "C" void libsnarkwrap_eval( } } +// Comparison tests + +extern "C" bool libsnarkwrap_test_compare_tau( + const curve_G1 *inputs1, + const curve_G2 *inputs2, + const curve_Fr *tau, + uint64_t d, + const r1cs_constraint_system *cs +) +{ + auto qap = r1cs_to_qap_instance_map(*cs); + auto coeffs = qap.domain->lagrange_coeffs(*tau); + assert(coeffs.size() == d); + assert(qap.degree() == d); + + bool res = true; + for (size_t i = 0; i < d; i++) { + res &= (coeffs[i] * curve_G1::one()) == inputs1[i]; + res &= (coeffs[i] * curve_G2::one()) == inputs2[i]; + } + + return res; +} + extern "C" bool libsnarkwrap_test_eval( const r1cs_constraint_system *cs, const curve_Fr *tau, diff --git a/src/lagrange.rs b/src/lagrange.rs index 58b6bac..455d64e 100644 --- a/src/lagrange.rs +++ b/src/lagrange.rs @@ -79,7 +79,7 @@ fn fft(v: &[G], omega: Fr, threads: usize) -> Vec mod test { use super::lagrange_coeffs; use snark::*; - use util::*; + use taupowers::*; #[test] fn compare_to_libsnark() { @@ -103,35 +103,35 @@ mod test { { // Perform G1 FFT with wrong omega let lc1 = lagrange_coeffs(&powers_of_tau_g1, Fr::random()); - assert!(!compare_tau(&lc1, &lc2, &tau, &cs)); + assert!(!cs.test_compare_tau(&lc1, &lc2, &tau)); } { // Perform G2 FFT with wrong omega let lc2 = lagrange_coeffs(&powers_of_tau_g2, Fr::random()); - assert!(!compare_tau(&lc1, &lc2, &tau, &cs)); + assert!(!cs.test_compare_tau(&lc1, &lc2, &tau)); } // Compare against libsnark - assert!(compare_tau(&lc1, &lc2, &tau, &cs)); + assert!(cs.test_compare_tau(&lc1, &lc2, &tau)); // Wrong tau - assert!(!compare_tau(&lc1, &lc2, &Fr::random(), &cs)); + assert!(!cs.test_compare_tau(&lc1, &lc2, &Fr::random())); // Evaluate At, Ct in G1 and Bt in G1/G2 - let mut At = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); - let mut Bt1 = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); - let mut Bt2 = (0..cs.num_vars).map(|_| G2::zero()).collect::>(); - let mut Ct = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); + let mut at = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); + let mut bt1 = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); + let mut bt2 = (0..cs.num_vars).map(|_| G2::zero()).collect::>(); + let mut ct = (0..cs.num_vars).map(|_| G1::zero()).collect::>(); - cs.eval(&lc1, &lc2, &mut At, &mut Bt1, &mut Bt2, &mut Ct); + cs.eval(&lc1, &lc2, &mut at, &mut bt1, &mut bt2, &mut ct); // Compare evaluation with libsnark - assert!(cs.test_eval(&tau, &At, &Bt1, &Bt2, &Ct)); + assert!(cs.test_eval(&tau, &at, &bt1, &bt2, &ct)); // Wrong tau - assert!(!cs.test_eval(&Fr::random(), &At, &Bt1, &Bt2, &Ct)); + assert!(!cs.test_eval(&Fr::random(), &at, &bt1, &bt2, &ct)); // Wrong polynomials - assert!(!cs.test_eval(&Fr::random(), &Bt1, &Bt1, &Bt2, &Ct)); + assert!(!cs.test_eval(&Fr::random(), &bt1, &bt1, &bt2, &ct)); } } diff --git a/src/main.rs b/src/main.rs index 2289103..c2b7b24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,48 +1,14 @@ extern crate snark; extern crate crossbeam; -mod util; +mod taupowers; +mod sequences; mod lagrange; mod protocol; mod spair; -use snark::*; -use protocol::*; -use lagrange::*; - fn main() { - initialize(); - - // Get the constraint system - let cs = getcs(); - - // Initialize the players - const NUM_PLAYERS: usize = 3; - let players = (0..NUM_PLAYERS).map(|_| Player::new(&cs)).collect::>(); - - // Phase 1 & 2 produces s-pairs for each player - let spairs = players.iter().map(|p| p.spairs()).collect::>(); - - // Phase 3 produces random powers of tau in G1/G2 - let (taupowers_g1, taupowers_g2) = { - let mut transcript = vec![]; - - for (i, p) in players.iter().enumerate() { - if i == 0 { - transcript.push(p.randompowers_start().unwrap()); - } else { - let v = p.randompowers(&transcript[i-1].0, &transcript[i-1].1).unwrap(); - transcript.push(v); - } - - // Verification - assert!(verify_randompowers(&transcript[i], - if i == 0 { None } else { Some(&transcript[i-1]) }, - &spairs[i])); - } - - transcript[NUM_PLAYERS-1].clone() - }; - + snark::initialize(); + } diff --git a/src/protocol.rs b/src/protocol.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs deleted file mode 100644 index 27bd754..0000000 --- a/src/protocol/mod.rs +++ /dev/null @@ -1,149 +0,0 @@ -use snark::*; -use util::*; -use lagrange::*; -use spair::*; - -#[derive(Debug)] -pub enum ProtocolError { - InvalidTauPowersSize -} - -pub struct Samples { - tau: T, - rho_a: T, - rho_b: T, - alpha_a: T, - alpha_b: T, - alpha_c: T, - beta: T, - gamma: T -} - -pub struct Player<'a> { - secrets: Samples, - cs: &'a CS -} - -impl<'a> Player<'a> { - pub fn new(cs: &'a CS) -> Player { - Player { - secrets: Samples { - tau: Fr::random_nonzero(), - rho_a: Fr::random_nonzero(), - rho_b: Fr::random_nonzero(), - alpha_a: Fr::random_nonzero(), - alpha_b: Fr::random_nonzero(), - alpha_c: Fr::random_nonzero(), - beta: Fr::random_nonzero(), - gamma: Fr::random_nonzero() - }, - cs: cs - } - } - - pub fn spairs(&self) -> Samples> { - Samples { - tau: Spair::random(&self.secrets.tau), - rho_a: Spair::random(&self.secrets.rho_a), - rho_b: Spair::random(&self.secrets.rho_b), - alpha_a: Spair::random(&self.secrets.alpha_a), - alpha_b: Spair::random(&self.secrets.alpha_b), - alpha_c: Spair::random(&self.secrets.alpha_c), - beta: Spair::random(&self.secrets.beta), - gamma: Spair::random(&self.secrets.gamma) - } - } - - pub fn randompowers_start(&self) -> Result<(Vec, Vec), ProtocolError> { - use std::iter::repeat; - - let v1 = repeat(G1::one()).take(self.cs.d + 1).collect::>(); - let v2 = repeat(G2::one()).take(self.cs.d + 1).collect::>(); - - self.randompowers(&v1, &v2) - } - - pub fn randompowers(&self, v1: &[G1], v2: &[G2]) -> Result<(Vec, Vec), ProtocolError> { - if (v1.len() != v2.len()) || (v1.len() != self.cs.d + 1) { - return Err(ProtocolError::InvalidTauPowersSize) - } - - let mut t1 = Vec::with_capacity(self.cs.d + 1); - let mut t2 = Vec::with_capacity(self.cs.d + 1); - - for (i, tp) in TauPowers::new(self.secrets.tau).take(self.cs.d+1).enumerate() { - t1.push(v1[i] * tp); - t2.push(v2[i] * tp); - } - - Ok((t1, t2)) - } -} - -pub fn verify_randompowers( - current: &(Vec, Vec), - last: Option<&(Vec, Vec)>, - spair: &Samples> -) -> bool { - current.0[0] == G1::one() && - current.1[0] == G2::one() && - match last { - Some(last) => { - checkseq(current.0.iter(), &Spair::new(¤t.1[0], ¤t.1[1])) && - checkseq(current.1.iter(), &Spair::new(¤t.0[0], ¤t.0[1])) && - same_power(&Spair::new(&last.0[1], ¤t.0[1]), &spair.tau) - }, - None => { - checkseq(current.0.iter(), &spair.tau) && - checkseq(current.1.iter(), &Spair::new(¤t.0[0], ¤t.0[1])) - } - } -} - -#[test] -fn randompowers_test() { - initialize(); - - const NUM_PARTIES: usize = 3; - - let cs = getcs(); - - // All parties should initialize with their secret randomness - let parties: Vec = (0..NUM_PARTIES).map(|_| Player::new(&cs)).collect(); - // All parties should reveal their s-pairs - let spairs: Vec>> = parties.iter().map(|p| p.spairs()).collect(); - - let mut transcript = vec![]; - - for (i, p) in parties.iter().enumerate() { - if i == 0 { - transcript.push(p.randompowers_start().unwrap()); - } else { - let v = p.randompowers(&transcript[i-1].0, &transcript[i-1].1).unwrap(); - transcript.push(v); - } - } - - // Verification - let mut last = None; - for i in 0..NUM_PARTIES { - // Wrong tau s-pair should fail - assert!(!verify_randompowers(&transcript[i], - last, - &spairs[(i+1)%NUM_PARTIES])); - - if last.is_some() { - // Verifying against wrong last transcript should fail - assert!(!verify_randompowers(&transcript[i], - Some(&transcript[i]), - &spairs[i])); - } - - // Correct check - assert!(verify_randompowers(&transcript[i], - last, - &spairs[i])); - - last = Some(&transcript[i]); - } -} diff --git a/src/util.rs b/src/sequences.rs similarity index 72% rename from src/util.rs rename to src/sequences.rs index fcaaf00..eab9f2a 100644 --- a/src/util.rs +++ b/src/sequences.rs @@ -1,5 +1,3 @@ -use snark::Fr; - pub struct Sequences<'a, T: 'a, I: Iterator> { v: I, last: Option<&'a T> @@ -36,26 +34,3 @@ fn test_sequences() { let expected = vec![(&a[0], &a[1]), (&a[1], &a[2]), (&a[2], &a[3])]; assert_eq!(b, expected); } - - - -pub struct TauPowers { - acc: Fr, - tau: Fr -} - -impl TauPowers { - pub fn new(tau: Fr) -> TauPowers { - TauPowers { acc: Fr::one(), tau: tau } - } -} - -impl Iterator for TauPowers { - type Item = Fr; - - fn next(&mut self) -> Option { - let tmp = self.acc; - self.acc = tmp * self.tau; - Some(tmp) - } -} diff --git a/src/spair.rs b/src/spair.rs index 8cb3ea2..55a82d6 100644 --- a/src/spair.rs +++ b/src/spair.rs @@ -1,5 +1,5 @@ use snark::*; -use util::*; +use sequences::*; pub struct Spair { p: G, @@ -8,7 +8,7 @@ pub struct Spair { impl Spair { pub fn random(s: &Fr) -> Self { - let mut p = G::zero(); + let mut p = G::random(); while p.is_zero() { p = G::random(); @@ -20,14 +20,14 @@ impl Spair { } } - pub fn new(p: &G, q: &G) -> Self { + pub fn new(p: &G, q: &G) -> Option { if p.is_zero() { - panic!("tried to initialize spair with zero base") - } - - Spair { - p: *p, - q: *q + None + } else { + Some(Spair { + p: *p, + q: *q + }) } } } @@ -57,7 +57,7 @@ where Group1: Pairing if p.is_zero() { return false; } - same_power(&Spair::new(&p, &q), &a) + same_power(&Spair::new(&p, &q).unwrap(), &a) } pub fn checkseq<'a, @@ -132,8 +132,6 @@ fn samepower_seq() { general_seq_test::(); } - -/* fn checkvec<'a, Group1: Group, Group2: Group, @@ -198,4 +196,3 @@ fn samepower_vec() { samepower_test_each_group(10, 5); samepower_test_each_group(100, 50); } -*/ diff --git a/src/taupowers.rs b/src/taupowers.rs new file mode 100644 index 0000000..4e60843 --- /dev/null +++ b/src/taupowers.rs @@ -0,0 +1,34 @@ +use snark; + +pub struct TauPowers { + acc: snark::Fr, + tau: snark::Fr +} + +impl TauPowers { + pub fn new(tau: snark::Fr) -> TauPowers { + TauPowers { acc: snark::Fr::one(), tau: tau } + } +} + +impl Iterator for TauPowers { + type Item = snark::Fr; + + fn next(&mut self) -> Option { + let tmp = self.acc; + self.acc = tmp * self.tau; + Some(tmp) + } +} + +#[test] +fn test_tau_powers() { + snark::initialize(); + + let tau = snark::Fr::random(); + let mut taupowers = TauPowers::new(tau); + assert!(taupowers.next() == Some(snark::Fr::one())); + assert!(taupowers.next() == Some(tau)); + assert!(taupowers.next() == Some(tau * tau)); + assert!(taupowers.next() == Some(tau * tau * tau)); +}