mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-24 11:36:18 +00:00
Implement usage of the signature scheme
This commit is contained in:
parent
987aa5189a
commit
329a48c19d
3 changed files with 48 additions and 19 deletions
|
@ -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<ValidatorId = Self::ValidatorId>;
|
||||
type Weights: Weights<ValidatorId = Self::ValidatorId>;
|
||||
type Block: Block;
|
||||
|
||||
|
@ -75,7 +75,14 @@ pub trait Network: Send + Sync {
|
|||
fn signature_scheme(&self) -> Arc<Self::SignatureScheme>;
|
||||
fn weights(&self) -> Arc<Self::Weights>;
|
||||
|
||||
async fn broadcast(&mut self, msg: Message<Self::ValidatorId, Self::Block>);
|
||||
async fn broadcast(
|
||||
&mut self,
|
||||
msg: SignedMessage<
|
||||
Self::ValidatorId,
|
||||
Self::Block,
|
||||
<Self::SignatureScheme as SignatureScheme>::Signature,
|
||||
>,
|
||||
);
|
||||
|
||||
// TODO: Should this take a verifiable reason?
|
||||
async fn slash(&mut self, validator: Self::ValidatorId);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use core::fmt::Debug;
|
||||
|
||||
use std::{
|
||||
sync::Arc,
|
||||
time::{Instant, Duration},
|
||||
|
@ -54,6 +56,12 @@ pub struct Message<V: ValidatorId, B: Block> {
|
|||
data: Data<B>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Encode, Decode)]
|
||||
pub struct SignedMessage<V: ValidatorId, B: Block, S: Clone + PartialEq + Debug + Encode + Decode> {
|
||||
msg: Message<V, B>,
|
||||
sig: S,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, Decode)]
|
||||
pub enum TendermintError<V: ValidatorId> {
|
||||
Malicious(V),
|
||||
|
@ -62,6 +70,7 @@ pub enum TendermintError<V: ValidatorId> {
|
|||
|
||||
pub struct TendermintMachine<N: Network> {
|
||||
network: Arc<RwLock<N>>,
|
||||
signer: Arc<N::SignatureScheme>,
|
||||
weights: Arc<N::Weights>,
|
||||
proposer: N::ValidatorId,
|
||||
|
||||
|
@ -81,7 +90,9 @@ pub struct TendermintMachine<N: Network> {
|
|||
|
||||
pub struct TendermintHandle<N: Network> {
|
||||
// Messages received
|
||||
pub messages: mpsc::Sender<Message<N::ValidatorId, N::Block>>,
|
||||
pub messages: mpsc::Sender<
|
||||
SignedMessage<N::ValidatorId, N::Block, <N::SignatureScheme as SignatureScheme>::Signature>,
|
||||
>,
|
||||
// Async task executing the machine
|
||||
pub handle: JoinHandle<()>,
|
||||
}
|
||||
|
@ -106,7 +117,9 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
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<N: Network + 'static> TendermintMachine<N> {
|
|||
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<N: Network + 'static> TendermintMachine<N> {
|
|||
|
||||
// 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,
|
||||
}
|
||||
|
|
|
@ -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<TestValidatorId, Self::Block>) {
|
||||
async fn broadcast(&mut self, msg: SignedMessage<TestValidatorId, Self::Block, [u8; 32]>) {
|
||||
for handle in self.1.write().await.iter_mut() {
|
||||
handle.messages.send(msg.clone()).await.unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue