use crate::{
ordered_broadcast::types::Context,
types::{Epoch, Height},
Automaton as A, Relay as R,
};
use bytes::Bytes;
use commonware_cryptography::{sha256, Hasher, PublicKey, Sha256};
use commonware_utils::channel::oneshot;
use tracing::trace;
#[derive(Clone)]
pub struct Automaton<P: PublicKey> {
invalid_when: fn(Height) -> bool,
_phantom: std::marker::PhantomData<P>,
}
impl<P: PublicKey> Automaton<P> {
pub fn new(invalid_when: fn(Height) -> bool) -> Self {
Self {
invalid_when,
_phantom: std::marker::PhantomData,
}
}
}
impl<P: PublicKey> A for Automaton<P> {
type Context = Context<P>;
type Digest = sha256::Digest;
async fn genesis(&mut self, _epoch: Epoch) -> Self::Digest {
unimplemented!()
}
async fn propose(&mut self, context: Self::Context) -> oneshot::Receiver<Self::Digest> {
let (sender, receiver) = oneshot::channel();
let Self::Context { sequencer, height } = context;
let payload = Bytes::from(format!("hello world, {sequencer} {height}"));
let mut hasher = Sha256::default();
hasher.update(&payload);
if (self.invalid_when)(height) {
hasher.update(&payload);
}
let digest = hasher.finalize();
sender.send(digest).unwrap();
receiver
}
async fn verify(
&mut self,
context: Self::Context,
payload: Self::Digest,
) -> oneshot::Receiver<bool> {
trace!(?context, ?payload, "verify");
let (sender, receiver) = oneshot::channel();
sender.send(true).unwrap();
receiver
}
}
impl<P: PublicKey> R for Automaton<P> {
type Digest = sha256::Digest;
type Plan = ();
type PublicKey = P;
async fn broadcast(&mut self, payload: Self::Digest, _plan: ()) {
trace!(?payload, "broadcast");
}
}