use crate::{
async_protocols::{remote::AsyncProtocolRemote, BatchKey, KeygenPartyId},
gossip_engine::GossipEngineIface,
utils::SendFuture,
worker::{DKGWorker, ProtoStageType},
Client,
};
use async_trait::async_trait;
use dkg_primitives::types::{DKGError, SSID};
use dkg_runtime_primitives::{
crypto::{AuthorityId, Public},
BatchId, DKGApi, MaxAuthorities, MaxProposalLength, MaxProposalsInBatch, SessionId,
StoredUnsignedProposalBatch,
};
use mp_ecdsa::MpEcdsaDKG;
use parking_lot::RwLock;
use sc_client_api::Backend;
use sp_runtime::traits::{Block, NumberFor};
use std::{marker::PhantomData, pin::Pin, sync::Arc};
use wt_frost::WTFrostDKG;
pub mod mp_ecdsa;
pub mod wt_frost;
pub enum KeygenProtocolSetupParameters<B: Block> {
MpEcdsa {
best_authorities: Vec<(KeygenPartyId, Public)>,
authority_public_key: Public,
party_i: KeygenPartyId,
session_id: SessionId,
associated_block: NumberFor<B>,
threshold: u16,
stage: ProtoStageType,
keygen_protocol_hash: [u8; 32],
},
WTFrost {
authority_id: AuthorityId,
best_authorities: Vec<(KeygenPartyId, Public)>,
authority_public_key: Public,
keygen_protocol_hash: [u8; 32],
threshold: u32,
session_id: SessionId,
associated_block: NumberFor<B>,
stage: ProtoStageType,
},
}
pub enum SigningProtocolSetupParameters<B: Block> {
MpEcdsa {
best_authorities: Vec<(KeygenPartyId, Public)>,
authority_public_key: Public,
party_i: KeygenPartyId,
session_id: SessionId,
threshold: u16,
stage: ProtoStageType,
unsigned_proposal_batch: StoredUnsignedProposalBatch<
BatchId,
MaxProposalLength,
MaxProposalsInBatch,
NumberFor<B>,
>,
signing_set: Vec<KeygenPartyId>,
associated_block_id: NumberFor<B>,
ssid: SSID,
},
WTFrost {
authority_id: AuthorityId,
unsigned_proposal_hash: [u8; 32],
unsigned_proposal_batch: StoredUnsignedProposalBatch<
BatchId,
MaxProposalLength,
MaxProposalsInBatch,
NumberFor<B>,
>,
threshold: u32,
session_id: SessionId,
batch_key: BatchKey,
associated_block: NumberFor<B>,
stage: ProtoStageType,
ssid: SSID,
},
}
pub type ProtocolInitReturn<B> =
(AsyncProtocolRemote<NumberFor<B>>, Pin<Box<dyn SendFuture<'static, ()>>>);
#[async_trait]
pub trait DKG<B: Block>: Send + Sync {
async fn initialize_keygen_protocol(
&self,
params: KeygenProtocolSetupParameters<B>,
) -> Option<ProtocolInitReturn<B>>;
async fn initialize_signing_protocol(
&self,
params: SigningProtocolSetupParameters<B>,
) -> Result<ProtocolInitReturn<B>, DKGError>;
fn can_handle_keygen_request(&self, params: &KeygenProtocolSetupParameters<B>) -> bool;
fn can_handle_signing_request(&self, params: &SigningProtocolSetupParameters<B>) -> bool;
}
pub struct DKGModules<B: Block, BE, C, GE> {
dkgs: Arc<RwLock<Vec<Arc<dyn DKG<B>>>>>,
_pd: PhantomData<(BE, C, GE)>,
}
impl<B, BE, C, GE> DKGModules<B, BE, C, GE>
where
B: Block,
BE: Backend<B> + Unpin + 'static,
C: Client<B, BE> + 'static,
GE: GossipEngineIface,
C::Api: DKGApi<B, AuthorityId, NumberFor<B>, MaxProposalLength, MaxAuthorities>,
{
pub fn initialize(&self, dkg_worker: DKGWorker<B, BE, C, GE>) {
*self.dkgs.write() = vec![
Arc::new(MpEcdsaDKG { dkg_worker: dkg_worker.clone() }),
Arc::new(WTFrostDKG { dkg_worker }),
]
}
pub fn get_keygen_protocol(
&self,
params: &KeygenProtocolSetupParameters<B>,
) -> Option<Arc<dyn DKG<B>>> {
self.dkgs
.read()
.iter()
.find(|dkg| dkg.can_handle_keygen_request(params))
.cloned()
}
pub fn get_signing_protocol(
&self,
params: &SigningProtocolSetupParameters<B>,
) -> Option<Arc<dyn DKG<B>>> {
self.dkgs
.read()
.iter()
.find(|dkg| dkg.can_handle_signing_request(params))
.cloned()
}
}
impl<B, BE, C, GE> Default for DKGModules<B, BE, C, GE>
where
B: Block,
BE: Backend<B> + 'static,
C: Client<B, BE> + 'static,
GE: GossipEngineIface,
{
fn default() -> Self {
Self { dkgs: Arc::new(RwLock::new(vec![])), _pd: PhantomData }
}
}
impl<B, BE, C, GE> Clone for DKGModules<B, BE, C, GE>
where
B: Block,
BE: Backend<B> + 'static,
C: Client<B, BE> + 'static,
GE: GossipEngineIface,
{
fn clone(&self) -> Self {
Self { dkgs: self.dkgs.clone(), _pd: PhantomData }
}
}