From 1cb3c164da6294ce6b7bb32baa6623b81d55b4c8 Mon Sep 17 00:00:00 2001 From: keorn Date: Wed, 24 Aug 2016 11:58:49 +0200 Subject: [PATCH] propose step --- ethcore/src/client/client.rs | 11 ++++++----- ethcore/src/engines/mod.rs | 2 +- ethcore/src/engines/tendermint.rs | 29 ++++++++++++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 1dcc23d02..51376fc0a 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1024,12 +1024,13 @@ impl BlockChainClient for Client { fn queue_infinity_message(&self, message: Bytes) { let full_rlp = UntrustedRlp::new(&message); - let signature = full_rlp.val_at(0).unwrap_or(return); - let message: Vec<_> = full_rlp.val_at(1).unwrap_or(return); + let signature = full_rlp.val_at(0).unwrap_or_else(|| return); + let message: Vec<_> = full_rlp.val_at(1).unwrap_or_else(|| return); let message_rlp = UntrustedRlp::new(&message); - let pub_key = recover(&signature, &message.sha3()).unwrap_or(return); - if let Some(new_message) = self.engine.handle_message(pub_key.sha3().into(), message_rlp) { - self.notify(|notify| notify.broadcast(new_message.as_raw())); + let pub_key = recover(&signature, &message.sha3()).unwrap_or_else(|| return); + if let Some(new_message) = self.engine.handle_message(pub_key.sha3().into(), message_rlp) + { + self.notify(|notify| notify.broadcast(&new_message)); } } } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 59464a85b..ef7590540 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -121,7 +121,7 @@ pub trait Engine : Sync + Send { /// Handle any potential consensus messages; /// updating consensus state and potentially issuing a new one. - fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Option { None } + fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Option { None } // TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic // from Spec into here and removing the Spec::builtins field. diff --git a/ethcore/src/engines/tendermint.rs b/ethcore/src/engines/tendermint.rs index 5726ab2ba..0a6747390 100644 --- a/ethcore/src/engines/tendermint.rs +++ b/ethcore/src/engines/tendermint.rs @@ -38,7 +38,7 @@ pub struct TendermintParams { /// Consensus round. r: u64, /// Consensus step. - s: Step, + s: RwLock, /// Used to swith proposer. proposer_nonce: usize } @@ -61,7 +61,7 @@ impl From for TendermintParams { validators: val, validator_n: val_n, r: 0, - s: Step::Propose, + s: RwLock::new(Step::Propose), proposer_nonce: 0 } } @@ -89,9 +89,27 @@ impl Tendermint { p.validators.get(p.proposer_nonce%p.validator_n).unwrap().clone() } - fn propose_message(&self, message: UntrustedRlp) -> Option { + fn propose_message(&self, message: UntrustedRlp) -> Option { + match *self.our_params.s.try_read().unwrap() { + Step::Propose => (), + _ => return None, + } + let proposal = message.val_at(0).unwrap_or_else(|| return None); + let vote = ProposeCollect::new(proposal, + self.our_params.validators.iter().cloned().collect(), + self.threshold()); + let mut guard = self.our_params.s.try_write().unwrap(); + *guard = Step::Prevote(vote); + Some(message.as_raw().to_vec()) + } + + fn prevote_message(&self, sender: Address, message: UntrustedRlp) -> Option { None } + + fn threshold(&self) -> usize { + self.our_params.validator_n*2/3 + } } impl Engine for Tendermint { @@ -144,9 +162,10 @@ impl Engine for Tendermint { }) } - fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Option { - match message.val_at(0).unwrap_or(return None) { + fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Option { + match message.val_at(0).unwrap_or_else(|| return None) { 0u8 if sender == self.proposer() => self.propose_message(message), + 1 => self.prevote_message(sender, message), _ => None, } }