diff --git a/substrate/tendermint/src/ext.rs b/substrate/tendermint/src/ext.rs index 407baf61..969eaf00 100644 --- a/substrate/tendermint/src/ext.rs +++ b/substrate/tendermint/src/ext.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use parity_scale_codec::{Encode, Decode}; -use crate::Message; +use crate::SignedMessage; pub trait ValidatorId: Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + Encode + Decode @@ -20,10 +20,10 @@ pub struct BlockNumber(pub u32); #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)] pub struct Round(pub u16); -pub trait SignatureScheme { +pub trait SignatureScheme: Send + Sync { type ValidatorId: ValidatorId; - type Signature: Clone + Copy + PartialEq; - type AggregateSignature: Clone + PartialEq; + type Signature: Send + Sync + Clone + Copy + PartialEq + Debug + Encode + Decode; + type AggregateSignature: Send + Sync + Clone + PartialEq + Debug + Encode + Decode; fn sign(&self, msg: &[u8]) -> Self::Signature; #[must_use] @@ -65,7 +65,7 @@ pub trait Block: Send + Sync + Clone + PartialEq + Debug + Encode + Decode { #[async_trait::async_trait] pub trait Network: Send + Sync { type ValidatorId: ValidatorId; - type SignatureScheme: SignatureScheme; + type SignatureScheme: SignatureScheme; type Weights: Weights; type Block: Block; @@ -75,7 +75,14 @@ pub trait Network: Send + Sync { fn signature_scheme(&self) -> Arc; fn weights(&self) -> Arc; - async fn broadcast(&mut self, msg: Message); + async fn broadcast( + &mut self, + msg: SignedMessage< + Self::ValidatorId, + Self::Block, + ::Signature, + >, + ); // TODO: Should this take a verifiable reason? async fn slash(&mut self, validator: Self::ValidatorId); diff --git a/substrate/tendermint/src/lib.rs b/substrate/tendermint/src/lib.rs index 7b7666ec..f413a6f6 100644 --- a/substrate/tendermint/src/lib.rs +++ b/substrate/tendermint/src/lib.rs @@ -1,3 +1,5 @@ +use core::fmt::Debug; + use std::{ sync::Arc, time::{Instant, Duration}, @@ -54,6 +56,12 @@ pub struct Message { data: Data, } +#[derive(Clone, PartialEq, Debug, Encode, Decode)] +pub struct SignedMessage { + msg: Message, + sig: S, +} + #[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, Decode)] pub enum TendermintError { Malicious(V), @@ -62,6 +70,7 @@ pub enum TendermintError { pub struct TendermintMachine { network: Arc>, + signer: Arc, weights: Arc, proposer: N::ValidatorId, @@ -81,7 +90,9 @@ pub struct TendermintMachine { pub struct TendermintHandle { // Messages received - pub messages: mpsc::Sender>, + pub messages: mpsc::Sender< + SignedMessage::Signature>, + >, // Async task executing the machine pub handle: JoinHandle<()>, } @@ -106,7 +117,9 @@ impl TendermintMachine { let msg = Message { sender: self.proposer, number: self.number, round: self.round, data }; let res = self.message(msg.clone()).await.unwrap(); self.step = step; // TODO: Before or after the above handling call? - self.network.write().await.broadcast(msg).await; + + let sig = self.signer.sign(&msg.encode()); + self.network.write().await.broadcast(SignedMessage { msg, sig }).await; res } @@ -167,10 +180,12 @@ impl TendermintMachine { TendermintHandle { messages: msg_send, handle: tokio::spawn(async move { + let signer = network.signature_scheme(); let weights = network.weights(); let network = Arc::new(RwLock::new(network)); let mut machine = TendermintMachine { network, + signer, weights: weights.clone(), proposer, @@ -214,17 +229,24 @@ impl TendermintMachine { // If there's a message, handle it match msg_recv.try_recv() { - Ok(msg) => match machine.message(msg).await { - Ok(None) => (), - Ok(Some(block)) => { - let proposal = machine.network.write().await.add_block(block); - machine.reset(proposal).await + Ok(msg) => { + if !machine.signer.verify(msg.msg.sender, &msg.msg.encode(), msg.sig) { + yield_now().await; + continue; } - Err(TendermintError::Malicious(validator)) => { - machine.network.write().await.slash(validator).await + + match machine.message(msg.msg).await { + Ok(None) => (), + Ok(Some(block)) => { + let proposal = machine.network.write().await.add_block(block); + machine.reset(proposal).await + } + Err(TendermintError::Malicious(validator)) => { + machine.network.write().await.slash(validator).await + } + Err(TendermintError::Temporal) => (), } - Err(TendermintError::Temporal) => (), - }, + } Err(TryRecvError::Empty) => yield_now().await, Err(TryRecvError::Disconnected) => break, } diff --git a/substrate/tendermint/tests/ext.rs b/substrate/tendermint/tests/ext.rs index 7c15f57b..c0b45c91 100644 --- a/substrate/tendermint/tests/ext.rs +++ b/substrate/tendermint/tests/ext.rs @@ -4,7 +4,7 @@ use parity_scale_codec::{Encode, Decode}; use tokio::sync::RwLock; -use tendermint_machine::{ext::*, Message, TendermintMachine, TendermintHandle}; +use tendermint_machine::{ext::*, SignedMessage, TendermintMachine, TendermintHandle}; type TestValidatorId = u16; type TestBlockId = u32; @@ -80,7 +80,7 @@ impl Network for TestNetwork { Arc::new(TestWeights) } - async fn broadcast(&mut self, msg: Message) { + async fn broadcast(&mut self, msg: SignedMessage) { for handle in self.1.write().await.iter_mut() { handle.messages.send(msg.clone()).await.unwrap(); }