mirror of https://github.com/zcash/mpc.git
Fundamental pieces of the random powers subprotocol
This commit is contained in:
parent
27ad4bb114
commit
79e5782089
|
@ -34,8 +34,31 @@ pub fn initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pairing(p: &G1, q: &G2) -> Gt {
|
||||
unsafe { libsnarkwrap_pairing(p, q) }
|
||||
pub trait Pairing<Other: Group> {
|
||||
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 +
|
||||
|
@ -45,7 +68,8 @@ pub trait Group: Sized +
|
|||
Add<Output=Self> +
|
||||
Sub<Output=Self> +
|
||||
Neg<Output=Self> +
|
||||
PartialEq {
|
||||
PartialEq +
|
||||
'static {
|
||||
fn zero() -> Self;
|
||||
fn one() -> 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 {
|
||||
use super::{Fr, G1, G2, initialize, Group};
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
extern crate snark;
|
||||
|
||||
mod randompowers;
|
||||
mod util;
|
||||
|
||||
use snark::*;
|
||||
|
||||
fn main() {
|
||||
initialize();
|
||||
initialize();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue