use std::{marker::PhantomData, collections::HashMap};
use rand_core::{RngCore, CryptoRng};
use zeroize::Zeroize;
use group::Group;
use crate::{
Curve, promote::{GeneratorPromotion },
tests::{clone_without, key_gen, schnorr::sign_core},
};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
struct AltGenerator<C: Curve> {
_curve: PhantomData<C>,
}
impl<C: Curve> Curve for AltGenerator<C> {
type F = C::F;
type G = C::G;
const ID: &'static [u8] = b"alt_generator";
fn generator() -> Self::G {
C::G::generator() * C::hash_to_F(b"FROST_tests", b"generator")
}
fn hash_to_vec(dst: &[u8], data: &[u8]) -> Vec<u8> {
C::hash_to_vec(&[b"FROST_tests_alt", dst].concat(), data)
}
fn hash_to_F(dst: &[u8], data: &[u8]) -> Self::F {
C::hash_to_F(&[b"FROST_tests_alt", dst].concat(), data)
}
}
fn test_generator_promotion<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
let keys = key_gen::<_, C>(&mut *rng);
let mut promotions = HashMap::new();
let mut proofs = HashMap::new();
for (i, keys) in &keys {
let promotion = GeneratorPromotion::<_, AltGenerator<C>>::promote(&mut *rng, keys.clone());
promotions.insert(*i, promotion.0);
proofs.insert(*i, promotion.1);
}
let mut new_keys = HashMap::new();
let mut group_key = None;
let mut verification_shares = None;
for (i, promoting) in promotions.drain() {
let promoted = promoting.complete(&clone_without(&proofs, &i)).unwrap();
assert_eq!(keys[&i].params(), promoted.params());
assert_eq!(keys[&i].secret_share(), promoted.secret_share());
if group_key.is_none() {
group_key = Some(keys[&i].group_key());
verification_shares = Some(keys[&i].verification_shares());
}
assert_eq!(keys[&i].group_key(), group_key.unwrap());
assert_eq!(&keys[&i].verification_shares(), verification_shares.as_ref().unwrap());
new_keys.insert(i, promoted);
}
sign_core(rng, &new_keys);
}
pub fn test_promotion<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
test_generator_promotion::<_, C>(rng);
}