From f79321233db4988972b9abfbd980523882b2759a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 16 Oct 2022 03:55:39 -0400 Subject: [PATCH] Refactor to type V, type B --- substrate/tendermint/src/ext.rs | 17 ++++++++++++--- substrate/tendermint/src/lib.rs | 13 ------------ substrate/tendermint/src/message_log.rs | 28 ++++++++++++++++++------- substrate/tendermint/tests/ext.rs | 11 ++++++++-- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/substrate/tendermint/src/ext.rs b/substrate/tendermint/src/ext.rs index d46aa383..ed6150c4 100644 --- a/substrate/tendermint/src/ext.rs +++ b/substrate/tendermint/src/ext.rs @@ -3,6 +3,12 @@ use core::{hash::Hash, fmt::Debug}; pub trait ValidatorId: Clone + Copy + PartialEq + Eq + Hash + Debug {} impl 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 { +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>; } diff --git a/substrate/tendermint/src/lib.rs b/substrate/tendermint/src/lib.rs index 08b05675..7bb15baf 100644 --- a/substrate/tendermint/src/lib.rs +++ b/substrate/tendermint/src/lib.rs @@ -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, diff --git a/substrate/tendermint/src/message_log.rs b/substrate/tendermint/src/message_log.rs index ad240ba0..2df03548 100644 --- a/substrate/tendermint/src/message_log.rs +++ b/substrate/tendermint/src/message_log.rs @@ -2,19 +2,22 @@ use std::{sync::Arc, collections::HashMap}; use crate::{ext::*, Round, Step, Data, Message, TendermintError}; -pub(crate) struct MessageLog> { +pub(crate) struct MessageLog { network: Arc, - precommitted: HashMap, - log: HashMap>>>, + precommitted: HashMap::Id>, + log: HashMap>>>, } -impl> MessageLog { - pub(crate) fn new(network: Arc) -> MessageLog { +impl MessageLog { + pub(crate) fn new(network: Arc) -> MessageLog { MessageLog { network, precommitted: HashMap::new(), log: HashMap::new() } } // Returns true if it's a new message - pub(crate) fn log(&mut self, msg: Message) -> Result> { + pub(crate) fn log( + &mut self, + msg: Message, + ) -> Result> { 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> MessageLog { // 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) -> (u64, u64) { + pub(crate) fn message_instances(&self, round: Round, data: Data) -> (u64, u64) { let mut participating = 0; let mut weight = 0; for (participant, msgs) in &self.log[&round] { @@ -77,8 +80,17 @@ impl> MessageLog { } // Check if consensus has been reached on a specific piece of data - pub(crate) fn has_consensus(&self, round: Round, data: Data) -> bool { + pub(crate) fn has_consensus(&self, round: Round, data: Data) -> 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> { + self.log.get(&round).and_then(|round| round.get(&sender).and_then(|msgs| msgs.get(&step))) + } } diff --git a/substrate/tendermint/tests/ext.rs b/substrate/tendermint/tests/ext.rs index f4a37922..fe967b8b 100644 --- a/substrate/tendermint/tests/ext.rs +++ b/substrate/tendermint/tests/ext.rs @@ -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 for TestNetwork { +impl Network for TestNetwork { + type ValidatorId = u16; + type Block = TestBlock; + fn total_weight(&self) -> u64 { 5 } @@ -23,6 +26,10 @@ impl Network 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 }