Fundamental pieces of the random powers subprotocol

This commit is contained in:
Sean Bowe 2016-08-02 14:01:25 -06:00
parent 27ad4bb114
commit 79e5782089
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 271 additions and 4 deletions

View File

@ -34,8 +34,31 @@ pub fn initialize() {
} }
} }
pub fn pairing(p: &G1, q: &G2) -> Gt { pub trait Pairing<Other: Group> {
unsafe { libsnarkwrap_pairing(p, q) } fn g1<'a>(&'a self, other: &'a Other) -> &'a G1;
fn g2<'a>(&'a self, other: &'a Other) -> &'a G2;
}
impl Pairing<G2> for G1 {
fn g1<'a>(&'a self, _: &'a G2) -> &'a G1 {
self
}
fn g2<'a>(&'a self, other: &'a G2) -> &'a G2 {
other
}
}
impl Pairing<G1> for G2 {
fn g1<'a>(&'a self, other: &'a G1) -> &'a G1 {
other
}
fn g2<'a>(&'a self, _: &'a G1) -> &'a G2 {
self
}
}
pub fn pairing<Ga: Group, Gb: Group>(p: &Ga, q: &Gb) -> Gt where Ga: Pairing<Gb> {
unsafe { libsnarkwrap_pairing(p.g1(q), p.g2(q)) }
} }
pub trait Group: Sized + pub trait Group: Sized +
@ -45,7 +68,8 @@ pub trait Group: Sized +
Add<Output=Self> + Add<Output=Self> +
Sub<Output=Self> + Sub<Output=Self> +
Neg<Output=Self> + Neg<Output=Self> +
PartialEq { PartialEq +
'static {
fn zero() -> Self; fn zero() -> Self;
fn one() -> Self; fn one() -> Self;
fn random() -> Self; fn random() -> Self;
@ -73,6 +97,20 @@ fn pairing_test() {
} }
} }
#[test]
fn pairing_ordering_irrelevant() {
initialize();
let p = G1::random();
let q = G2::random();
let a = pairing(&p, &q);
let b = pairing(&q, &p);
assert!(a == b);
}
#[cfg(test)]
mod test_groups { mod test_groups {
use super::{Fr, G1, G2, initialize, Group}; use super::{Fr, G1, G2, initialize, Group};

View File

@ -1,7 +1,12 @@
extern crate snark; extern crate snark;
mod randompowers;
mod util;
use snark::*; use snark::*;
fn main() { fn main() {
initialize(); initialize();
} }

196
src/randompowers.rs Normal file
View File

@ -0,0 +1,196 @@
use snark::*;
use util::Sequences;
struct Spair<G: Group> {
p: G,
q: G
}
impl<G: Group> Spair<G> {
fn random(s: &Fr) -> Self {
let mut p = G::zero();
while p.is_zero() {
p = G::random();
}
Spair {
p: p,
q: p * (*s)
}
}
fn new(p: &G, q: &G) -> Self {
if p.is_zero() {
panic!("tried to initialize spair with zero base")
}
Spair {
p: *p,
q: *q
}
}
}
fn same_power<Group1: Group, Group2: Group>(a: &Spair<Group1>, b: &Spair<Group2>) -> bool
where Group1: Pairing<Group2> {
pairing(&a.p, &b.q) == pairing(&a.q, &b.p)
}
fn check<'a,
Group1: Group,
Group2: Group,
I: IntoIterator<Item=(&'a Group1, &'a Group1)>>
(i: I, a: &Spair<Group2>) -> bool
where Group1: Pairing<Group2>
{
let mut p = Group1::zero();
let mut q = Group1::zero();
for v in i {
let alpha = Fr::random();
p = p + *v.0 * alpha;
q = q + *v.1 * alpha;
}
if p.is_zero() { return false; }
same_power(&Spair::new(&p, &q), &a)
}
fn checkvec<'a,
Group1: Group,
Group2: Group,
I: IntoIterator<Item=&'a Spair<Group1>>>
(i: I, a: &Spair<Group2>) -> bool
where Group1: Pairing<Group2>
{
check(i.into_iter().map(|s| (&s.p, &s.q)), a)
}
fn checkseq<'a,
Group1: Group,
Group2: Group,
I: Iterator<Item=&'a Group1>>
(i: I, a: &Spair<Group2>) -> bool
where Group1: Pairing<Group2>
{
check(Sequences::new(i), a)
}
#[test]
fn samepower_seq() {
initialize();
fn general_seq_test<Group1: Group, Group2: Group>()
where Group1: Pairing<Group2>
{
// Test working
{
let s = Fr::random();
let p = Spair::<Group2>::random(&s);
let mut a = vec![];
a.push(Group1::random());
for _ in 0..50 {
let n = *a.last().unwrap() * s;
a.push(n);
}
assert!(checkseq(a.iter(), &p));
}
// Test not working.
{
let s = Fr::random();
let p = Spair::<Group2>::random(&s);
let mut a = vec![];
a.push(Group1::random());
for i in 0..50 {
if i == 10 {
a.push(Group1::random());
} else {
let n = *a.last().unwrap() * s;
a.push(n);
}
}
assert!(!checkseq(a.iter(), &p));
}
}
general_seq_test::<G1, G2>();
general_seq_test::<G2, G1>();
}
#[test]
fn samepower_vec() {
initialize();
fn samepower_general_test<Group1: Group, Group2: Group>(i: usize, f: usize)
where Group1: Pairing<Group2>
{
// Test working
{
let s = Fr::random();
let p = Spair::<Group2>::random(&s);
let a: Vec<Spair<Group1>> = (0..i).map(|_| Spair::random(&s)).collect();
assert!(checkvec(&a, &p));
}
// Test different scalar
{
let s = Fr::random();
let p = Spair::<Group2>::random(&Fr::random());
let a: Vec<Spair<Group1>> = (0..i).map(|_| Spair::random(&s)).collect();
assert!(!checkvec(&a, &p));
}
// Test incorrect spair
{
let s = Fr::random();
let p = Spair::<Group2>::random(&s);
let a: Vec<Spair<Group1>> = (0..i).map(|i| {
if i == f {
Spair::random(&Fr::random())
} else {
Spair::random(&s)
}
}).collect();
assert!(!checkvec(&a, &p));
}
}
fn samepower_test_each_group(i: usize, f: usize)
{
samepower_general_test::<G1, G2>(i, f);
samepower_general_test::<G2, G1>(i, f);
}
samepower_test_each_group(1, 0);
samepower_test_each_group(10, 5);
samepower_test_each_group(100, 50);
}
#[test]
fn trivial_samepower() {
initialize();
let f = Fr::random();
let a = Spair::<G1>::random(&f);
let b = Spair::<G2>::random(&f);
let c = Spair::<G1>::random(&Fr::random());
assert!(same_power(&a, &b));
assert!(same_power(&b, &a));
assert!(!same_power(&b, &c));
}

28
src/util.rs Normal file
View File

@ -0,0 +1,28 @@
pub struct Sequences<'a, T: 'a, I: Iterator<Item=&'a T>> {
v: I,
last: Option<&'a T>
}
impl<'a, T: 'a, I: Iterator<Item=&'a T>> Sequences<'a, T, I> {
pub fn new(v: I) -> Self {
Sequences { v: v, last: None }
}
}
impl<'a, T: 'a, I: Iterator<Item=&'a T>> Iterator for Sequences<'a, T, I> {
type Item = (&'a T, &'a T);
fn next(&mut self) -> Option<(&'a T, &'a T)> {
match (self.last, self.v.next()) {
(Some(a), Some(b)) => {
self.last = Some(b);
Some((a, b))
},
(None, Some(b)) => {
self.last = Some(b);
self.next()
},
_ => None
}
}
}