mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Refactor <V, B> to type V, type B
This commit is contained in:
@@ -3,6 +3,12 @@ use core::{hash::Hash, fmt::Debug};
|
|||||||
pub trait ValidatorId: Clone + Copy + PartialEq + Eq + Hash + Debug {}
|
pub trait ValidatorId: Clone + Copy + PartialEq + Eq + Hash + Debug {}
|
||||||
impl<V: Clone + Copy + PartialEq + Eq + Hash + Debug> ValidatorId for V {}
|
impl<V: Clone + Copy + PartialEq + Eq + Hash + Debug> ValidatorId for V {}
|
||||||
|
|
||||||
|
// Type aliases which are distinct according to the type system
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct BlockNumber(pub u32);
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct Round(pub u16);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum BlockError {
|
pub enum BlockError {
|
||||||
// Invalid behavior entirely
|
// Invalid behavior entirely
|
||||||
@@ -17,12 +23,17 @@ pub trait Block: Clone + PartialEq {
|
|||||||
fn id(&self) -> Self::Id;
|
fn id(&self) -> Self::Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Network<V: ValidatorId, B: Block> {
|
pub trait Network {
|
||||||
|
type ValidatorId: ValidatorId;
|
||||||
|
type Block: Block;
|
||||||
|
|
||||||
fn total_weight(&self) -> u64;
|
fn total_weight(&self) -> u64;
|
||||||
fn weight(&self, validator: V) -> u64;
|
fn weight(&self, validator: Self::ValidatorId) -> u64;
|
||||||
fn threshold(&self) -> u64 {
|
fn threshold(&self) -> u64 {
|
||||||
((self.total_weight() * 2) / 3) + 1
|
((self.total_weight() * 2) / 3) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&mut self, block: B) -> Result<(), BlockError>;
|
fn proposer(&self, number: BlockNumber, round: Round) -> Self::ValidatorId;
|
||||||
|
|
||||||
|
fn validate(&mut self, block: Self::Block) -> Result<(), BlockError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,6 @@ use ext::*;
|
|||||||
|
|
||||||
mod message_log;
|
mod message_log;
|
||||||
|
|
||||||
// Type aliases which are distinct according to the type system
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub(crate) struct BlockNumber(u32);
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub(crate) struct Round(u32);
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
enum Step {
|
enum Step {
|
||||||
Propose,
|
Propose,
|
||||||
@@ -58,13 +52,6 @@ use tokio::{
|
|||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ValidatorId = u16;
|
|
||||||
const VALIDATORS: ValidatorId = 5;
|
|
||||||
|
|
||||||
fn proposer(number: u32, round: u32) -> ValidatorId {
|
|
||||||
ValidatorId::try_from((number + round) % u32::try_from(VALIDATORS).unwrap()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TendermintMachine {
|
struct TendermintMachine {
|
||||||
proposer: ValidatorId,
|
proposer: ValidatorId,
|
||||||
|
|||||||
@@ -2,19 +2,22 @@ use std::{sync::Arc, collections::HashMap};
|
|||||||
|
|
||||||
use crate::{ext::*, Round, Step, Data, Message, TendermintError};
|
use crate::{ext::*, Round, Step, Data, Message, TendermintError};
|
||||||
|
|
||||||
pub(crate) struct MessageLog<V: ValidatorId, B: Block, N: Network<V, B>> {
|
pub(crate) struct MessageLog<N: Network> {
|
||||||
network: Arc<N>,
|
network: Arc<N>,
|
||||||
precommitted: HashMap<V, B::Id>,
|
precommitted: HashMap<N::ValidatorId, <N::Block as Block>::Id>,
|
||||||
log: HashMap<Round, HashMap<V, HashMap<Step, Data<B>>>>,
|
log: HashMap<Round, HashMap<N::ValidatorId, HashMap<Step, Data<N::Block>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: ValidatorId, B: Block, N: Network<V, B>> MessageLog<V, B, N> {
|
impl<N: Network> MessageLog<N> {
|
||||||
pub(crate) fn new(network: Arc<N>) -> MessageLog<V, B, N> {
|
pub(crate) fn new(network: Arc<N>) -> MessageLog<N> {
|
||||||
MessageLog { network, precommitted: HashMap::new(), log: HashMap::new() }
|
MessageLog { network, precommitted: HashMap::new(), log: HashMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if it's a new message
|
// Returns true if it's a new message
|
||||||
pub(crate) fn log(&mut self, msg: Message<V, B>) -> Result<bool, TendermintError<V>> {
|
pub(crate) fn log(
|
||||||
|
&mut self,
|
||||||
|
msg: Message<N::ValidatorId, N::Block>,
|
||||||
|
) -> Result<bool, TendermintError<N::ValidatorId>> {
|
||||||
let round = self.log.entry(msg.round).or_insert_with(HashMap::new);
|
let round = self.log.entry(msg.round).or_insert_with(HashMap::new);
|
||||||
let msgs = round.entry(msg.sender).or_insert_with(HashMap::new);
|
let msgs = round.entry(msg.sender).or_insert_with(HashMap::new);
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ impl<V: ValidatorId, B: Block, N: Network<V, B>> MessageLog<V, B, N> {
|
|||||||
|
|
||||||
// For a given round, return the participating weight for this step, and the weight agreeing with
|
// For a given round, return the participating weight for this step, and the weight agreeing with
|
||||||
// the data.
|
// the data.
|
||||||
pub(crate) fn message_instances(&self, round: Round, data: Data<B>) -> (u64, u64) {
|
pub(crate) fn message_instances(&self, round: Round, data: Data<N::Block>) -> (u64, u64) {
|
||||||
let mut participating = 0;
|
let mut participating = 0;
|
||||||
let mut weight = 0;
|
let mut weight = 0;
|
||||||
for (participant, msgs) in &self.log[&round] {
|
for (participant, msgs) in &self.log[&round] {
|
||||||
@@ -77,8 +80,17 @@ impl<V: ValidatorId, B: Block, N: Network<V, B>> MessageLog<V, B, N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if consensus has been reached on a specific piece of data
|
// Check if consensus has been reached on a specific piece of data
|
||||||
pub(crate) fn has_consensus(&self, round: Round, data: Data<B>) -> bool {
|
pub(crate) fn has_consensus(&self, round: Round, data: Data<N::Block>) -> bool {
|
||||||
let (_, weight) = self.message_instances(round, data);
|
let (_, weight) = self.message_instances(round, data);
|
||||||
weight >= self.network.threshold()
|
weight >= self.network.threshold()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get(
|
||||||
|
&self,
|
||||||
|
round: Round,
|
||||||
|
sender: N::ValidatorId,
|
||||||
|
step: Step,
|
||||||
|
) -> Option<&Data<N::Block>> {
|
||||||
|
self.log.get(&round).and_then(|round| round.get(&sender).and_then(|msgs| msgs.get(&step)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use tendermint_machine::ext::{BlockError, Block, Network};
|
use tendermint_machine::ext::*;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
struct TestBlock {
|
struct TestBlock {
|
||||||
@@ -15,7 +15,10 @@ impl Block for TestBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TestNetwork;
|
struct TestNetwork;
|
||||||
impl Network<u16, TestBlock> for TestNetwork {
|
impl Network for TestNetwork {
|
||||||
|
type ValidatorId = u16;
|
||||||
|
type Block = TestBlock;
|
||||||
|
|
||||||
fn total_weight(&self) -> u64 {
|
fn total_weight(&self) -> u64 {
|
||||||
5
|
5
|
||||||
}
|
}
|
||||||
@@ -23,6 +26,10 @@ impl Network<u16, TestBlock> for TestNetwork {
|
|||||||
[1, 1, 1, 1, 1][usize::try_from(id).unwrap()]
|
[1, 1, 1, 1, 1][usize::try_from(id).unwrap()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proposer(&self, number: BlockNumber, round: Round) -> u16 {
|
||||||
|
u16::try_from((number.0 + u32::from(round.0)) % 5).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn validate(&mut self, block: TestBlock) -> Result<(), BlockError> {
|
fn validate(&mut self, block: TestBlock) -> Result<(), BlockError> {
|
||||||
block.valid
|
block.valid
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user