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
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
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 {}
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)]
pub enum BlockError {
// Invalid behavior entirely
@ -17,12 +23,17 @@ pub trait Block: Clone + PartialEq {
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 weight(&self, validator: V) -> u64;
fn weight(&self, validator: Self::ValidatorId) -> u64;
fn threshold(&self) -> u64 {
((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;
// 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)]
enum Step {
Propose,
@ -58,13 +52,6 @@ use tokio::{
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)]
struct TendermintMachine {
proposer: ValidatorId,

View file

@ -2,19 +2,22 @@ use std::{sync::Arc, collections::HashMap};
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>,
precommitted: HashMap<V, B::Id>,
log: HashMap<Round, HashMap<V, HashMap<Step, Data<B>>>>,
precommitted: HashMap<N::ValidatorId, <N::Block as Block>::Id>,
log: HashMap<Round, HashMap<N::ValidatorId, HashMap<Step, Data<N::Block>>>>,
}
impl<V: ValidatorId, B: Block, N: Network<V, B>> MessageLog<V, B, N> {
pub(crate) fn new(network: Arc<N>) -> MessageLog<V, B, N> {
impl<N: Network> MessageLog<N> {
pub(crate) fn new(network: Arc<N>) -> MessageLog<N> {
MessageLog { network, precommitted: HashMap::new(), log: HashMap::new() }
}
// 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 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
// 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 weight = 0;
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
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);
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)]
struct TestBlock {
@ -15,7 +15,10 @@ impl Block for TestBlock {
}
struct TestNetwork;
impl Network<u16, TestBlock> for TestNetwork {
impl Network for TestNetwork {
type ValidatorId = u16;
type Block = TestBlock;
fn total_weight(&self) -> u64 {
5
}
@ -23,6 +26,10 @@ impl Network<u16, TestBlock> for TestNetwork {
[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> {
block.valid
}