//! Byzantine participant that sends impersonated (and invalid) notarize/finalize messages. use crate::{ simplex::{ scheme, types::{Finalize, Notarize, Vote}, }, types::Participant, }; use commonware_codec::{DecodeExt, Encode}; use commonware_cryptography::{certificate::Scheme, Hasher}; use commonware_p2p::{Receiver, Recipients, Sender}; use commonware_runtime::{spawn_cell, Clock, ContextCell, Handle, Spawner}; use rand_core::CryptoRngCore; use std::marker::PhantomData; use tracing::debug; pub struct Config { pub scheme: S, } pub struct Impersonator { context: ContextCell, scheme: S, _hasher: PhantomData, } impl, H: Hasher> Impersonator { pub fn new(context: E, cfg: Config) -> Self { Self { context: ContextCell::new(context), scheme: cfg.scheme, _hasher: PhantomData, } } pub fn start(mut self, vote_network: (impl Sender, impl Receiver)) -> Handle<()> { spawn_cell!(self.context, self.run(vote_network).await) } async fn run(self, vote_network: (impl Sender, impl Receiver)) { let (mut sender, mut receiver) = vote_network; while let Ok((s, msg)) = receiver.recv().await { // Parse message let msg = match Vote::::decode(msg) { Ok(msg) => msg, Err(err) => { debug!(?err, sender = ?s, "failed to decode message"); continue; } }; // Process message match msg { Vote::Notarize(notarize) => { // Notarize received digest let mut n = Notarize::sign(&self.scheme, notarize.proposal).unwrap(); // Manipulate index if n.attestation.signer == Participant::new(0) { n.attestation.signer = Participant::new(1); } else { n.attestation.signer = Participant::new(0); } // Send invalid message let msg = Vote::Notarize(n).encode(); sender.send(Recipients::All, msg, true).await.unwrap(); } Vote::Finalize(finalize) => { // Finalize provided digest let mut f = Finalize::sign(&self.scheme, finalize.proposal).unwrap(); // Manipulate signature if f.attestation.signer == Participant::new(0) { f.attestation.signer = Participant::new(1); } else { f.attestation.signer = Participant::new(0); } // Send invalid message let msg = Vote::Finalize(f).encode(); sender.send(Recipients::All, msg, true).await.unwrap(); } _ => continue, } } } }