mirror of https://github.com/zcash/mpc.git
Randompowers subprotocol simulation
This commit is contained in:
parent
79e5782089
commit
c05c8c0d90
|
@ -1,6 +1,6 @@
|
|||
# mpc
|
||||
|
||||
This is a multi-party computation protocol for the key-generation step of Pinnochio zkSNARKs [[PGHR13]](https://eprint.iacr.org/2013/279) designed for use in the Zcash "Sprout" public parameter ceremony.
|
||||
This is a multi-party computation protocol for the key-generation step of Pinocchio zkSNARKs [[PGHR13]](https://eprint.iacr.org/2013/279) designed for use in the Zcash "Sprout" public parameter ceremony.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ extern "C" {
|
|||
fn libsnarkwrap_Fr_mul(a: *const Fr, b: *const Fr) -> Fr;
|
||||
fn libsnarkwrap_Fr_sub(a: *const Fr, b: *const Fr) -> Fr;
|
||||
fn libsnarkwrap_Fr_neg(a: *const Fr) -> Fr;
|
||||
fn libsnarkwrap_Fr_is_zero(a: *const Fr) -> bool;
|
||||
}
|
||||
|
||||
impl Fr {
|
||||
|
@ -21,6 +22,20 @@ impl Fr {
|
|||
unsafe { libsnarkwrap_Fr_random() }
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
unsafe { libsnarkwrap_Fr_is_zero(self) }
|
||||
}
|
||||
|
||||
pub fn random_nonzero() -> Self {
|
||||
let mut tmp = Self::random();
|
||||
|
||||
while tmp.is_zero() {
|
||||
tmp = Self::random();
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Self {
|
||||
for c in s.chars() {
|
||||
if c != '0' &&
|
||||
|
@ -74,3 +89,28 @@ impl Neg for Fr {
|
|||
unsafe { libsnarkwrap_Fr_neg(&self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_arith() {
|
||||
super::initialize();
|
||||
|
||||
let a = Fr::from_str("34563126457335463");
|
||||
let b = Fr::from_str("23463856875665981");
|
||||
let ab = Fr::from_str("810984252370463483215040853984203");
|
||||
let aplusb = Fr::from_str("58026983333001444");
|
||||
let aminusb = Fr::from_str("11099269581669482");
|
||||
let aneg = Fr::from_str("21888242871839275222246405745257275088548364400416034343698169623449351160154");
|
||||
|
||||
assert!(ab == (a * b));
|
||||
assert!(aplusb == (a + b));
|
||||
assert!(aminusb == (a - b));
|
||||
assert!(aneg == (-a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitives() {
|
||||
let a = Fr::from_str("0");
|
||||
assert!(a.is_zero());
|
||||
let a = Fr::from_str("1");
|
||||
assert!(!a.is_zero());
|
||||
}
|
||||
|
|
|
@ -33,22 +33,26 @@ extern "C" FieldT libsnarkwrap_Fr_from(const char *a) {
|
|||
return FieldT(a);
|
||||
}
|
||||
|
||||
extern "C" FieldT libsnarkwrap_Fr_add(const char *a, const char *b) {
|
||||
extern "C" FieldT libsnarkwrap_Fr_add(FieldT *a, FieldT *b) {
|
||||
return *a + *b;
|
||||
}
|
||||
|
||||
extern "C" FieldT libsnarkwrap_Fr_sub(const char *a, const char *b) {
|
||||
extern "C" FieldT libsnarkwrap_Fr_sub(FieldT *a, FieldT *b) {
|
||||
return *a - *b;
|
||||
}
|
||||
|
||||
extern "C" FieldT libsnarkwrap_Fr_mul(const char *a, const char *b) {
|
||||
extern "C" FieldT libsnarkwrap_Fr_mul(FieldT *a, FieldT *b) {
|
||||
return *a * *b;
|
||||
}
|
||||
|
||||
extern "C" FieldT libsnarkwrap_Fr_neg(const char *a) {
|
||||
extern "C" FieldT libsnarkwrap_Fr_neg(FieldT *a) {
|
||||
return -(*a);
|
||||
}
|
||||
|
||||
extern "C" bool libsnarkwrap_Fr_is_zero(FieldT *a) {
|
||||
return a->is_zero();
|
||||
}
|
||||
|
||||
// G1
|
||||
|
||||
extern "C" alt_bn128_G1 libsnarkwrap_G1_zero() {
|
||||
|
|
|
@ -37,6 +37,8 @@ where Group1: Pairing<Group2> {
|
|||
pairing(&a.p, &b.q) == pairing(&a.q, &b.p)
|
||||
}
|
||||
|
||||
/// This performs a check to see if a large number of (p,q) pairs in G
|
||||
/// have the same power, with only one pairing.
|
||||
fn check<'a,
|
||||
Group1: Group,
|
||||
Group2: Group,
|
||||
|
@ -48,7 +50,7 @@ where Group1: Pairing<Group2>
|
|||
let mut q = Group1::zero();
|
||||
|
||||
for v in i {
|
||||
let alpha = Fr::random();
|
||||
let alpha = Fr::random_nonzero();
|
||||
p = p + *v.0 * alpha;
|
||||
q = q + *v.1 * alpha;
|
||||
}
|
||||
|
@ -78,6 +80,72 @@ where Group1: Pairing<Group2>
|
|||
check(Sequences::new(i), a)
|
||||
}
|
||||
|
||||
struct TauPowers {
|
||||
acc: Fr,
|
||||
tau: Fr
|
||||
}
|
||||
|
||||
impl TauPowers {
|
||||
fn new(tau: Fr) -> TauPowers {
|
||||
TauPowers { acc: Fr::from_str("1"), tau: tau }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TauPowers {
|
||||
type Item = Fr;
|
||||
|
||||
fn next(&mut self) -> Option<Fr> {
|
||||
let tmp = self.acc;
|
||||
self.acc = tmp * self.tau;
|
||||
Some(tmp)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn randompowers_simulation() {
|
||||
initialize();
|
||||
|
||||
let parties = 3;
|
||||
let d = 1024;
|
||||
|
||||
let mut messages: Vec<(Spair<G2>, Vec<G1>, Vec<G2>)> = vec![];
|
||||
messages.reserve(parties);
|
||||
|
||||
for i in 0..parties {
|
||||
let tau = Fr::random_nonzero();
|
||||
let rp = Spair::random(&tau);
|
||||
|
||||
if i == 0 {
|
||||
messages.push((
|
||||
rp,
|
||||
TauPowers::new(tau).map(|p| G1::one() * p).take(d).collect(),
|
||||
TauPowers::new(tau).map(|p| G2::one() * p).take(d).collect()
|
||||
));
|
||||
} else {
|
||||
let v1 = messages[i-1].1.iter().zip(TauPowers::new(tau)).map(|(b, p)| *b * p).collect();
|
||||
let v2 = messages[i-1].2.iter().zip(TauPowers::new(tau)).map(|(b, p)| *b * p).collect();
|
||||
|
||||
messages.push((
|
||||
rp,
|
||||
v1,
|
||||
v2
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Check validity
|
||||
for i in 0..parties {
|
||||
if i == 0 {
|
||||
assert!(checkseq(messages[i].1.iter(), &messages[i].0));
|
||||
assert!(checkseq(messages[i].2.iter(), &Spair::new(&messages[i].1[0], &messages[i].1[1])));
|
||||
} else {
|
||||
assert!(checkseq(messages[i].1.iter(), &Spair::new(&messages[i].2[0], &messages[i].2[1])));
|
||||
assert!(checkseq(messages[i].2.iter(), &Spair::new(&messages[i].1[0], &messages[i].1[1])));
|
||||
assert!(same_power(&Spair::new(&messages[i-1].1[1], &messages[i].1[1]), &messages[i].0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn samepower_seq() {
|
||||
initialize();
|
||||
|
|
|
@ -26,3 +26,11 @@ impl<'a, T: 'a, I: Iterator<Item=&'a T>> Iterator for Sequences<'a, T, I> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sequences() {
|
||||
let a = vec![10, 57, 34, 12];
|
||||
let b: Vec<(&usize, &usize)> = Sequences::new(a.iter()).collect();
|
||||
let expected = vec![(&a[0], &a[1]), (&a[1], &a[2]), (&a[2], &a[3])];
|
||||
assert_eq!(b, expected);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue