use crate::orchestrator::EpochTransition;
use commonware_consensus::{simplex, types::Epoch};
use commonware_cryptography::{
bls12381::{
dkg,
primitives::variant::{MinSig, Variant},
},
certificate::{self, Scheme},
ed25519, PublicKey, Signer,
};
use commonware_utils::sync::Mutex;
use std::{collections::HashMap, sync::Arc};
pub type ThresholdScheme<V> =
simplex::scheme::bls12381_threshold::vrf::Scheme<ed25519::PublicKey, V>;
pub type EdScheme = simplex::scheme::ed25519::Scheme;
#[derive(Clone)]
pub struct Provider<S: Scheme, C: Signer> {
schemes: Arc<Mutex<HashMap<Epoch, Arc<S>>>>,
namespace: Vec<u8>,
certificate_verifier: Option<Arc<S>>,
signer: C,
}
impl<S: Scheme, C: Signer> Provider<S, C> {
pub fn new(namespace: Vec<u8>, signer: C, certificate_verifier: Option<S>) -> Self {
Self {
schemes: Arc::new(Mutex::new(HashMap::new())),
namespace,
certificate_verifier: certificate_verifier.map(Arc::new),
signer,
}
}
}
impl<S: Scheme, C: Signer> Provider<S, C> {
pub fn register(&self, epoch: Epoch, scheme: S) -> bool {
let mut schemes = self.schemes.lock();
schemes.insert(epoch, Arc::new(scheme)).is_none()
}
pub fn unregister(&self, epoch: &Epoch) -> bool {
let mut schemes = self.schemes.lock();
schemes.remove(epoch).is_some()
}
}
impl<S: Scheme, C: Signer> certificate::Provider for Provider<S, C> {
type Scope = Epoch;
type Scheme = S;
fn scoped(&self, epoch: Epoch) -> Option<Arc<S>> {
let schemes = self.schemes.lock();
schemes.get(&epoch).cloned()
}
fn all(&self) -> Option<Arc<S>> {
self.certificate_verifier.clone()
}
}
pub trait EpochProvider {
type Variant: Variant;
type PublicKey: PublicKey;
type Scheme: Scheme;
fn scheme_for_epoch(
&self,
transition: &EpochTransition<Self::Variant, Self::PublicKey>,
) -> Self::Scheme;
fn certificate_verifier(
namespace: &[u8],
output: &dkg::Output<Self::Variant, Self::PublicKey>,
) -> Option<Self::Scheme>;
}
impl<V: Variant> EpochProvider for Provider<ThresholdScheme<V>, ed25519::PrivateKey> {
type Variant = V;
type PublicKey = ed25519::PublicKey;
type Scheme = ThresholdScheme<V>;
fn scheme_for_epoch(
&self,
transition: &EpochTransition<Self::Variant, Self::PublicKey>,
) -> Self::Scheme {
transition.share.as_ref().map_or_else(
|| {
ThresholdScheme::verifier(
&self.namespace,
transition.dealers.clone(),
transition
.poly
.clone()
.expect("group polynomial must exist"),
)
},
|share| {
ThresholdScheme::signer(
&self.namespace,
transition.dealers.clone(),
transition
.poly
.clone()
.expect("group polynomial must exist"),
share.clone(),
)
.expect("share must be in dealers")
},
)
}
fn certificate_verifier(
namespace: &[u8],
output: &dkg::Output<Self::Variant, Self::PublicKey>,
) -> Option<Self::Scheme> {
Some(ThresholdScheme::certificate_verifier(
namespace,
*output.public().public(),
))
}
}
impl EpochProvider for Provider<EdScheme, ed25519::PrivateKey> {
type Variant = MinSig;
type PublicKey = ed25519::PublicKey;
type Scheme = EdScheme;
fn scheme_for_epoch(
&self,
transition: &EpochTransition<Self::Variant, Self::PublicKey>,
) -> Self::Scheme {
EdScheme::signer(
&self.namespace,
transition.dealers.clone(),
self.signer.clone(),
)
.unwrap_or_else(|| EdScheme::verifier(&self.namespace, transition.dealers.clone()))
}
fn certificate_verifier(
_namespace: &[u8],
_output: &dkg::Output<Self::Variant, Self::PublicKey>,
) -> Option<Self::Scheme> {
None
}
}