diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index ade14a28d..dbfcbda31 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -28,6 +28,8 @@ use spec::CommonParams; use engines::{Engine, EngineError}; use header::Header; use error::{Error, BlockError}; +use blockchain::extras::BlockDetails; +use views::HeaderView; use evm::Schedule; use ethjson; use io::{IoContext, IoHandler, TimerToken, IoService, IoChannel}; @@ -196,7 +198,6 @@ impl Engine for AuthorityRound { } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { - header.set_difficulty(parent.difficulty().clone()); header.set_gas_limit({ let gas_limit = parent.gas_limit().clone(); let bound_divisor = self.our_params.gas_limit_bound_divisor; @@ -308,6 +309,10 @@ impl Engine for AuthorityRound { t.sender().map(|_|()) // Perform EC recovery and cache sender } + fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool { + new_header.number() > best_header.number() + } + fn register_message_channel(&self, message_channel: IoChannel) { *self.message_channel.lock() = Some(message_channel); } diff --git a/ethcore/src/engines/tendermint/message.rs b/ethcore/src/engines/tendermint/message.rs index 5cc37b5f4..06ee551ba 100644 --- a/ethcore/src/engines/tendermint/message.rs +++ b/ethcore/src/engines/tendermint/message.rs @@ -39,6 +39,16 @@ fn consensus_round(header: &Header) -> Result { } impl ConsensusMessage { + pub fn new(signature: H520, height: Height, round: Round, step: Step, block_hash: Option) -> Self { + ConsensusMessage { + signature: signature, + height: height, + round: round, + step: step, + block_hash: block_hash + } + } + pub fn new_proposal(header: &Header) -> Result { Ok(ConsensusMessage { signature: try!(UntrustedRlp::new(header.seal()[1].as_slice()).as_val()), @@ -156,7 +166,7 @@ impl Encodable for ConsensusMessage { pub fn message_info_rlp(height: Height, round: Round, step: Step, block_hash: Option) -> Bytes { // TODO: figure out whats wrong with nested list encoding let mut s = RlpStream::new_list(5); - s.append(&height).append(&round).append(&step).append(&block_hash.unwrap_or(H256::zero())); + s.append(&height).append(&round).append(&step).append(&block_hash.unwrap_or_else(H256::zero)); s.out() } @@ -165,13 +175,10 @@ pub fn message_info_rlp_from_header(header: &Header) -> Result(signer: F, height: Height, round: Round, step: Step, block_hash: Option) -> Result where F: FnOnce(H256) -> Result { - let vote_info = message_info_rlp(height, round, step, block_hash); - signer(vote_info.sha3()).map(|ref signature| { - let mut s = RlpStream::new_list(2); - s.append(signature).append_raw(&vote_info, 1); - s.out() - }) +pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes { + let mut s = RlpStream::new_list(2); + s.append(signature).append_raw(vote_info, 1); + s.out() } #[cfg(test)] @@ -214,13 +221,9 @@ mod tests { let addr = tap.insert_account("0".sha3(), "0").unwrap(); tap.unlock_account_permanently(addr, "0".into()).unwrap(); - let raw_rlp = message_full_rlp( - |mh| tap.sign(addr, None, mh).map(H520::from), - 123, - 2, - Step::Precommit, - Some(H256::default()) - ).unwrap(); + let mi = message_info_rlp(123, 2, Step::Precommit, Some(H256::default())); + + let raw_rlp = message_full_rlp(&tap.sign(addr, None, mi.sha3()).unwrap().into(), &mi); let rlp = UntrustedRlp::new(&raw_rlp); let message: ConsensusMessage = rlp.as_val().unwrap(); diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 33c768007..0cc8085d0 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -134,7 +134,6 @@ impl Tendermint { fn broadcast_message(&self, message: Bytes) { if let Some(ref channel) = *self.message_channel.lock() { - trace!(target: "poa", "broadcast_message: {:?}", &message); match channel.send(ClientIoMessage::BroadcastMessage(message)) { Ok(_) => trace!(target: "poa", "broadcast_message: BroadcastMessage message sent."), Err(err) => warn!(target: "poa", "broadcast_message: Could not send a sealing message {}.", err), @@ -146,14 +145,17 @@ impl Tendermint { fn generate_message(&self, block_hash: Option) -> Option { if let Some(ref ap) = *self.account_provider.lock() { - match message_full_rlp( - |mh| ap.sign(*self.authority.read(), self.password.read().clone(), mh).map(H520::from), - self.height.load(AtomicOrdering::SeqCst), - self.round.load(AtomicOrdering::SeqCst), - *self.step.read(), - block_hash - ) { - Ok(m) => Some(m), + let h = self.height.load(AtomicOrdering::SeqCst); + let r = self.round.load(AtomicOrdering::SeqCst); + let s = self.step.read(); + let vote_info = message_info_rlp(h, r, *s, block_hash); + let authority = self.authority.read(); + match ap.sign(*authority, self.password.read().clone(), vote_info.sha3()).map(Into::into) { + Ok(signature) => { + let message_rlp = message_full_rlp(&signature, &vote_info); + self.votes.vote(ConsensusMessage::new(signature, h, r, *s, block_hash), *authority); + Some(message_rlp) + }, Err(e) => { trace!(target: "poa", "generate_message: Could not sign the message {}", e); None @@ -309,7 +311,6 @@ impl Engine for Tendermint { } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { - header.set_difficulty(parent.difficulty().clone()); header.set_gas_limit({ let gas_limit = parent.gas_limit().clone(); let bound_divisor = self.our_params.gas_limit_bound_divisor; @@ -344,7 +345,7 @@ impl Engine for Tendermint { let vote_info = message_info_rlp(height, round, Step::Propose, bh); if let Ok(signature) = ap.sign(*author, self.password.read().clone(), vote_info.sha3()).map(H520::from) { // Insert Propose vote. - self.votes.vote(ConsensusMessage { signature: signature, height: height, round: round, step: Step::Propose, block_hash: bh }, *author); + self.votes.vote(ConsensusMessage::new(signature, height, round, Step::Propose, bh), *author); // Remember proposal for later seal submission. *self.proposal.write() = Some(header.bare_hash()); Some(vec![ @@ -489,9 +490,14 @@ impl Engine for Tendermint { } fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool { - let new_signatures = new_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); - let best_signatures = best_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); - new_signatures > best_signatures + trace!(target: "poa", "new_header: {}, best_header: {}", new_header.number(), best_header.number()); + if new_header.number() > best_header.number() { + true + } else { + let new_signatures = new_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); + let best_signatures = best_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); + new_signatures > best_signatures + } } fn register_message_channel(&self, message_channel: IoChannel) { @@ -544,7 +550,8 @@ mod tests { } fn vote(engine: &Arc, signer: F, height: usize, round: usize, step: Step, block_hash: Option) where F: FnOnce(H256) -> Result { - let m = message_full_rlp(signer, height, round, step, block_hash).unwrap(); + let mi = message_info_rlp(height, round, step, block_hash); + let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi); engine.handle_message(UntrustedRlp::new(&m)).unwrap(); }