mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-10 05:09:22 +00:00
Implement MuSig key aggregation into DKG
Isn't spec compliant due to the lack of a spec to be compliant too. Slight deviation from the paper by using a unique list instead of a multiset. Closes #186, progresses #277.
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
use core::ops::Deref;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use ciphersuite::{group::ff::Field, Ciphersuite};
|
||||
|
||||
use crate::{Participant, ThresholdCore, ThresholdKeys, lagrange};
|
||||
use crate::{Participant, ThresholdCore, ThresholdKeys, lagrange, musig as musig_fn};
|
||||
|
||||
mod musig;
|
||||
pub use musig::test_musig;
|
||||
|
||||
/// FROST key generation testing utility.
|
||||
pub mod frost;
|
||||
@@ -63,6 +67,28 @@ pub fn key_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
|
||||
res
|
||||
}
|
||||
|
||||
/// Generate MuSig keys for tests.
|
||||
pub fn musig_key_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
|
||||
rng: &mut R,
|
||||
) -> HashMap<Participant, ThresholdKeys<C>> {
|
||||
let mut keys = vec![];
|
||||
let mut pub_keys = vec![];
|
||||
for _ in 0 .. PARTICIPANTS {
|
||||
let key = Zeroizing::new(C::F::random(&mut *rng));
|
||||
pub_keys.push(C::generator() * *key);
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
let mut res = HashMap::new();
|
||||
for key in keys {
|
||||
let these_keys = musig_fn::<C>(&key, &pub_keys).unwrap();
|
||||
res.insert(these_keys.params().i(), ThresholdKeys::new(these_keys));
|
||||
}
|
||||
|
||||
assert_eq!(C::generator() * recover_key(&res), res[&Participant(1)].group_key());
|
||||
res
|
||||
}
|
||||
|
||||
/// Run the test suite on a ciphersuite.
|
||||
pub fn test_ciphersuite<R: RngCore + CryptoRng, C: Ciphersuite>(rng: &mut R) {
|
||||
key_gen::<_, C>(rng);
|
||||
|
||||
61
crypto/dkg/src/tests/musig.rs
Normal file
61
crypto/dkg/src/tests/musig.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use ciphersuite::{group::ff::Field, Ciphersuite};
|
||||
|
||||
use crate::{
|
||||
ThresholdKeys, musig,
|
||||
tests::{PARTICIPANTS, recover_key},
|
||||
};
|
||||
|
||||
/// Tests MuSig key generation.
|
||||
pub fn test_musig<R: RngCore + CryptoRng, C: Ciphersuite>(rng: &mut R) {
|
||||
let mut keys = vec![];
|
||||
let mut pub_keys = vec![];
|
||||
for _ in 0 .. PARTICIPANTS {
|
||||
let key = Zeroizing::new(C::F::random(&mut *rng));
|
||||
pub_keys.push(C::generator() * *key);
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
// Empty signing set
|
||||
assert!(musig::<C>(&Zeroizing::new(C::F::ZERO), &[]).is_err());
|
||||
// Signing set we're not part of
|
||||
assert!(musig::<C>(&Zeroizing::new(C::F::ZERO), &[C::generator()]).is_err());
|
||||
|
||||
// Test with n keys
|
||||
{
|
||||
let mut created_keys = HashMap::new();
|
||||
let mut verification_shares = HashMap::new();
|
||||
let mut group_key = None;
|
||||
for (i, key) in keys.iter().enumerate() {
|
||||
let these_keys = musig::<C>(key, &pub_keys).unwrap();
|
||||
assert_eq!(these_keys.params().t(), PARTICIPANTS);
|
||||
assert_eq!(these_keys.params().n(), PARTICIPANTS);
|
||||
assert_eq!(usize::from(these_keys.params().i().0), i + 1);
|
||||
|
||||
verification_shares
|
||||
.insert(these_keys.params().i(), C::generator() * **these_keys.secret_share());
|
||||
|
||||
if group_key.is_none() {
|
||||
group_key = Some(these_keys.group_key());
|
||||
}
|
||||
assert_eq!(these_keys.group_key(), group_key.unwrap());
|
||||
|
||||
created_keys.insert(these_keys.params().i(), ThresholdKeys::new(these_keys));
|
||||
}
|
||||
|
||||
for keys in created_keys.values() {
|
||||
assert_eq!(keys.verification_shares(), verification_shares);
|
||||
}
|
||||
|
||||
assert_eq!(C::generator() * recover_key(&created_keys), group_key.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn musig_literal() {
|
||||
test_musig::<_, ciphersuite::Ristretto>(&mut rand_core::OsRng)
|
||||
}
|
||||
Reference in New Issue
Block a user