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 {
|
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};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
extern crate snark;
|
extern crate snark;
|
||||||
|
|
||||||
|
mod randompowers;
|
||||||
|
mod util;
|
||||||
|
|
||||||
use snark::*;
|
use snark::*;
|
||||||
|
|
||||||
fn main() {
|
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