use battleware_types::{leader_index, Evaluation, Identity, Signature};
use commonware_codec::Encode;
use commonware_consensus::{
aggregation::types::Epoch, threshold_simplex::types::View, Monitor, Supervisor as Su,
ThresholdSupervisor as TSu,
};
use commonware_cryptography::{
bls12381::{
dkg::ops::evaluate_all,
primitives::{
group,
poly::{self, Poly},
variant::MinSig,
},
},
ed25519,
};
use commonware_resolver::p2p;
use commonware_runtime::RwLock;
use futures::{channel::mpsc, SinkExt};
use std::{collections::HashMap, sync::Arc};
struct EpochManager {
epoch: Epoch,
subscribers: Vec<mpsc::Sender<Epoch>>,
}
impl EpochManager {
fn new() -> Self {
Self {
epoch: 0,
subscribers: Vec::new(),
}
}
async fn update(&mut self, epoch: Epoch) {
self.epoch = epoch;
let mut i = 0;
while i < self.subscribers.len() {
if self.subscribers[i].send(epoch).await.is_err() {
self.subscribers.swap_remove(i);
} else {
i += 1;
}
}
}
async fn subscribe(&mut self) -> (Epoch, mpsc::Receiver<Epoch>) {
let (tx, rx) = mpsc::channel(1);
self.subscribers.push(tx);
(self.epoch, rx)
}
fn current(&self) -> Epoch {
self.epoch
}
}
pub struct Supervisor {
identity: Identity,
polynomial: Vec<Evaluation>,
participants: Vec<ed25519::PublicKey>,
participants_map: HashMap<ed25519::PublicKey, u32>,
share: group::Share,
epoch_manager: RwLock<EpochManager>,
}
impl Supervisor {
pub fn new(
polynomial: Poly<Evaluation>,
mut participants: Vec<ed25519::PublicKey>,
share: group::Share,
) -> Arc<Self> {
participants.sort();
let mut participants_map = HashMap::new();
for (index, validator) in participants.iter().enumerate() {
participants_map.insert(validator.clone(), index as u32);
}
let identity = *poly::public::<MinSig>(&polynomial);
let polynomial = evaluate_all::<MinSig>(&polynomial, participants.len() as u32);
Arc::new(Self {
identity,
polynomial,
participants,
participants_map,
share,
epoch_manager: RwLock::new(EpochManager::new()),
})
}
}
#[derive(Clone)]
pub struct ViewSupervisor {
inner: Arc<Supervisor>,
}
impl ViewSupervisor {
pub fn new(supervisor: Arc<Supervisor>) -> Self {
Self { inner: supervisor }
}
}
impl p2p::Coordinator for ViewSupervisor {
type PublicKey = ed25519::PublicKey;
fn peers(&self) -> &Vec<Self::PublicKey> {
&self.inner.participants
}
fn peer_set_id(&self) -> u64 {
futures::executor::block_on(async { self.inner.epoch_manager.read().await.current() })
}
}
impl Su for ViewSupervisor {
type Index = View;
type PublicKey = ed25519::PublicKey;
fn leader(&self, _: Self::Index) -> Option<Self::PublicKey> {
unimplemented!("only defined in supertrait")
}
fn participants(&self, _: Self::Index) -> Option<&Vec<Self::PublicKey>> {
Some(&self.inner.participants)
}
fn is_participant(&self, _: Self::Index, candidate: &Self::PublicKey) -> Option<u32> {
self.inner.participants_map.get(candidate).cloned()
}
}
impl TSu for ViewSupervisor {
type Seed = Signature;
type Identity = Identity;
type Polynomial = Vec<Evaluation>;
type Share = group::Share;
fn leader(&self, _: Self::Index, seed: Self::Seed) -> Option<Self::PublicKey> {
let seed_bytes = seed.encode();
let index = leader_index(seed_bytes.as_ref(), self.inner.participants.len());
Some(self.inner.participants[index].clone())
}
fn identity(&self) -> &Self::Identity {
&self.inner.identity
}
fn polynomial(&self, _: Self::Index) -> Option<&Self::Polynomial> {
Some(&self.inner.polynomial)
}
fn share(&self, _: Self::Index) -> Option<&Self::Share> {
Some(&self.inner.share)
}
}
#[derive(Clone)]
pub struct EpochSupervisor {
inner: Arc<Supervisor>,
}
impl EpochSupervisor {
pub fn new(supervisor: Arc<Supervisor>) -> Self {
Self { inner: supervisor }
}
pub async fn update(&self, epoch: Epoch) {
self.inner.epoch_manager.write().await.update(epoch).await;
}
}
impl Su for EpochSupervisor {
type Index = Epoch;
type PublicKey = ed25519::PublicKey;
fn leader(&self, _: Self::Index) -> Option<Self::PublicKey> {
unimplemented!("only defined in supertrait")
}
fn participants(&self, _: Self::Index) -> Option<&Vec<Self::PublicKey>> {
Some(&self.inner.participants)
}
fn is_participant(&self, _: Self::Index, candidate: &Self::PublicKey) -> Option<u32> {
self.inner.participants_map.get(candidate).cloned()
}
}
impl TSu for EpochSupervisor {
type Identity = Identity;
type Polynomial = Vec<Evaluation>;
type Seed = Signature;
type Share = group::Share;
fn leader(&self, _: Self::Index, seed: Self::Seed) -> Option<Self::PublicKey> {
let seed_bytes = seed.encode();
let index = leader_index(seed_bytes.as_ref(), self.inner.participants.len());
Some(self.inner.participants[index].clone())
}
fn identity(&self) -> &Self::Identity {
&self.inner.identity
}
fn polynomial(&self, _: Self::Index) -> Option<&Self::Polynomial> {
Some(&self.inner.polynomial)
}
fn share(&self, _: Self::Index) -> Option<&Self::Share> {
Some(&self.inner.share)
}
}
impl Monitor for EpochSupervisor {
type Index = Epoch;
async fn subscribe(&mut self) -> (Self::Index, mpsc::Receiver<Self::Index>) {
self.inner.epoch_manager.write().await.subscribe().await
}
}