Refactor <V, B> to type V, type B

This commit is contained in:
Luke Parker
2022-10-16 03:55:39 -04:00
parent a5f1ddaf1b
commit f79321233d
4 changed files with 43 additions and 26 deletions

View File

@@ -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>;
} }

View File

@@ -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,

View File

@@ -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)))
}
} }

View File

@@ -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
} }