ap registration

This commit is contained in:
keorn 2016-11-17 23:36:24 +00:00
parent 9d61071dd7
commit c62795d09b
2 changed files with 54 additions and 23 deletions

View File

@ -18,7 +18,8 @@
use util::*;
use super::{Height, Round, BlockHash, Step};
use rlp::{View, DecoderError, Decodable, Decoder, Encodable, RlpStream, Stream};
use rlp::*;
use error::Error;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ConsensusMessage {
@ -30,6 +31,15 @@ pub struct ConsensusMessage {
}
impl ConsensusMessage {
pub fn new_rlp<F>(signer: F, height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Option<Bytes> where F: FnOnce(H256) -> Option<H520> {
let mut s = RlpStream::new_list(4);
s.append(&height);
s.append(&round);
s.append(&step);
s.append(&block_hash.unwrap_or(H256::zero()));
Some(s.out())
}
pub fn is_height(&self, height: Height) -> bool {
self.height == height
}

View File

@ -82,6 +82,8 @@ pub struct Tendermint {
proposed_block: Mutex<Option<ExecutedBlock>>,
/// Channel for updating the sealing.
message_channel: Mutex<Option<IoChannel<ClientIoMessage>>>,
/// Used to sign messages and proposals.
account_provider: Mutex<Option<Arc<AccountProvider>>>,
/// Message for the last PoLC.
last_lock: RwLock<Option<ConsensusMessage>>,
/// Bare hash of the proposed block, used for seal submission.
@ -105,6 +107,7 @@ impl Tendermint {
votes: VoteCollector::new(),
proposed_block: Mutex::new(None),
message_channel: Mutex::new(None),
account_provider: Mutex::new(None),
last_lock: RwLock::new(None),
proposal: RwLock::new(None)
});
@ -131,19 +134,31 @@ impl Tendermint {
}
}
fn broadcast_message(&self, message: Bytes) {
if let Some(ref channel) = *self.message_channel.lock() {
match channel.send(ClientIoMessage::BroadcastMessage(message)) {
Ok(_) => trace!(target: "poa", "timeout: BroadcastMessage message sent."),
Err(err) => warn!(target: "poa", "timeout: Could not send a sealing message {}.", err),
fn broadcast_message(&self, block_hash: Option<BlockHash>) {
if let Some(message) = self.generate_message(block_hash) {
if let Some(ref channel) = *self.message_channel.lock() {
match channel.send(ClientIoMessage::BroadcastMessage(message)) {
Ok(_) => trace!(target: "poa", "timeout: BroadcastMessage message sent."),
Err(err) => warn!(target: "poa", "timeout: Could not send a sealing message {}.", err),
}
}
} else {
warn!(target: "poa", "broadcast_message: Message could not be generated.");
}
}
fn generate_message(&self, block_hash: Option<BlockHash>) -> ConsensusMessage {
Ok(signature) = ap.sign(*author, None, block_hash(header))
ConsensusMessage { signatue
fn generate_message(&self, block_hash: Option<BlockHash>) -> Option<Bytes> {
if let Some(ref ap) = *self.account_provider.lock() {
ConsensusMessage::new_rlp(
|mh| ap.sign(*self.authority.read(), None, mh).ok().map(H520::from),
self.height.load(AtomicOrdering::SeqCst),
self.round.load(AtomicOrdering::SeqCst),
*self.step.read(),
block_hash
)
} else {
None
}
}
fn to_step(&self, step: Step) {
@ -154,19 +169,19 @@ impl Tendermint {
self.update_sealing()
},
Step::Prevote => {
self.broadcast_message()
self.broadcast_message(None)
},
Step::Precommit => {
let message = match self.last_lock.read() {
Some(m) =>
None => ConsensusMessage { signature: signature, height
}
self.broadcast_message(::rlp::encode(message))
let block_hash = match *self.last_lock.read() {
Some(ref m) => None,
None => None,
};
self.broadcast_message(block_hash);
},
Step::Commit => {
// Commit the block using a complete signature set.
let round = self.round.load(AtomicOrdering::SeqCst);
if let Some((proposer, votes)) = self.votes.seal_signatures(header.number() as Height, round, Some(block_hash(header))) {
if let Some((proposer, votes)) = self.votes.seal_signatures(self.height.load(AtomicOrdering::SeqCst), round, *self.proposal.read()) {
let seal = vec![
::rlp::encode(&round).to_vec(),
::rlp::encode(proposer).to_vec(),
@ -286,8 +301,8 @@ impl Engine for Tendermint {
}
/// Attempt to seal the block internally using all available signatures.
fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
if let Some(ap) = accounts {
fn generate_seal(&self, block: &ExecutedBlock) -> Option<Vec<Bytes>> {
if let Some(ref ap) = *self.account_provider.lock() {
let header = block.header();
let author = header.author();
if let Ok(signature) = ap.sign(*author, None, block_hash(header)) {
@ -317,11 +332,14 @@ impl Engine for Tendermint {
// Check if the message is known.
if self.votes.vote(message.clone(), sender).is_none() {
let is_newer_than_lock = self.last_lock.read().map_or(true, |lock| message > lock);
let is_newer_than_lock = match *self.last_lock.read() {
Some(ref lock) => &message > lock,
None => true,
};
if is_newer_than_lock
&& message.step == Step::Prevote
&& self.has_enough_aligned_votes(&message) {
*self.last_lock.write() = Some(message);
*self.last_lock.write() = Some(message.clone());
}
// Check if it can affect step transition.
if self.is_current(&message) {
@ -428,8 +446,11 @@ impl Engine for Tendermint {
}
fn register_message_channel(&self, message_channel: IoChannel<ClientIoMessage>) {
let mut guard = self.message_channel.lock();
*guard = Some(message_channel);
*self.message_channel.lock() = Some(message_channel);
}
fn register_account_provider(&self, account_provider: Arc<AccountProvider>) {
*self.account_provider.lock() = Some(account_provider);
}
}