ap registration
This commit is contained in:
parent
9d61071dd7
commit
c62795d09b
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use super::{Height, Round, BlockHash, Step};
|
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)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct ConsensusMessage {
|
pub struct ConsensusMessage {
|
||||||
@ -30,6 +31,15 @@ pub struct ConsensusMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn is_height(&self, height: Height) -> bool {
|
||||||
self.height == height
|
self.height == height
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,8 @@ pub struct Tendermint {
|
|||||||
proposed_block: Mutex<Option<ExecutedBlock>>,
|
proposed_block: Mutex<Option<ExecutedBlock>>,
|
||||||
/// Channel for updating the sealing.
|
/// Channel for updating the sealing.
|
||||||
message_channel: Mutex<Option<IoChannel<ClientIoMessage>>>,
|
message_channel: Mutex<Option<IoChannel<ClientIoMessage>>>,
|
||||||
|
/// Used to sign messages and proposals.
|
||||||
|
account_provider: Mutex<Option<Arc<AccountProvider>>>,
|
||||||
/// Message for the last PoLC.
|
/// Message for the last PoLC.
|
||||||
last_lock: RwLock<Option<ConsensusMessage>>,
|
last_lock: RwLock<Option<ConsensusMessage>>,
|
||||||
/// Bare hash of the proposed block, used for seal submission.
|
/// Bare hash of the proposed block, used for seal submission.
|
||||||
@ -105,6 +107,7 @@ impl Tendermint {
|
|||||||
votes: VoteCollector::new(),
|
votes: VoteCollector::new(),
|
||||||
proposed_block: Mutex::new(None),
|
proposed_block: Mutex::new(None),
|
||||||
message_channel: Mutex::new(None),
|
message_channel: Mutex::new(None),
|
||||||
|
account_provider: Mutex::new(None),
|
||||||
last_lock: RwLock::new(None),
|
last_lock: RwLock::new(None),
|
||||||
proposal: RwLock::new(None)
|
proposal: RwLock::new(None)
|
||||||
});
|
});
|
||||||
@ -131,19 +134,31 @@ impl Tendermint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn broadcast_message(&self, message: Bytes) {
|
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() {
|
if let Some(ref channel) = *self.message_channel.lock() {
|
||||||
match channel.send(ClientIoMessage::BroadcastMessage(message)) {
|
match channel.send(ClientIoMessage::BroadcastMessage(message)) {
|
||||||
Ok(_) => trace!(target: "poa", "timeout: BroadcastMessage message sent."),
|
Ok(_) => trace!(target: "poa", "timeout: BroadcastMessage message sent."),
|
||||||
Err(err) => warn!(target: "poa", "timeout: Could not send a sealing message {}.", err),
|
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 {
|
fn generate_message(&self, block_hash: Option<BlockHash>) -> Option<Bytes> {
|
||||||
Ok(signature) = ap.sign(*author, None, block_hash(header))
|
if let Some(ref ap) = *self.account_provider.lock() {
|
||||||
ConsensusMessage { signatue
|
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) {
|
fn to_step(&self, step: Step) {
|
||||||
@ -154,19 +169,19 @@ impl Tendermint {
|
|||||||
self.update_sealing()
|
self.update_sealing()
|
||||||
},
|
},
|
||||||
Step::Prevote => {
|
Step::Prevote => {
|
||||||
self.broadcast_message()
|
self.broadcast_message(None)
|
||||||
},
|
},
|
||||||
Step::Precommit => {
|
Step::Precommit => {
|
||||||
let message = match self.last_lock.read() {
|
let block_hash = match *self.last_lock.read() {
|
||||||
Some(m) =>
|
Some(ref m) => None,
|
||||||
None => ConsensusMessage { signature: signature, height
|
None => None,
|
||||||
}
|
};
|
||||||
self.broadcast_message(::rlp::encode(message))
|
self.broadcast_message(block_hash);
|
||||||
},
|
},
|
||||||
Step::Commit => {
|
Step::Commit => {
|
||||||
// Commit the block using a complete signature set.
|
// Commit the block using a complete signature set.
|
||||||
let round = self.round.load(AtomicOrdering::SeqCst);
|
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![
|
let seal = vec![
|
||||||
::rlp::encode(&round).to_vec(),
|
::rlp::encode(&round).to_vec(),
|
||||||
::rlp::encode(proposer).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.
|
/// Attempt to seal the block internally using all available signatures.
|
||||||
fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
|
fn generate_seal(&self, block: &ExecutedBlock) -> Option<Vec<Bytes>> {
|
||||||
if let Some(ap) = accounts {
|
if let Some(ref ap) = *self.account_provider.lock() {
|
||||||
let header = block.header();
|
let header = block.header();
|
||||||
let author = header.author();
|
let author = header.author();
|
||||||
if let Ok(signature) = ap.sign(*author, None, block_hash(header)) {
|
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.
|
// Check if the message is known.
|
||||||
if self.votes.vote(message.clone(), sender).is_none() {
|
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
|
if is_newer_than_lock
|
||||||
&& message.step == Step::Prevote
|
&& message.step == Step::Prevote
|
||||||
&& self.has_enough_aligned_votes(&message) {
|
&& 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.
|
// Check if it can affect step transition.
|
||||||
if self.is_current(&message) {
|
if self.is_current(&message) {
|
||||||
@ -428,8 +446,11 @@ impl Engine for Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn register_message_channel(&self, message_channel: IoChannel<ClientIoMessage>) {
|
fn register_message_channel(&self, message_channel: IoChannel<ClientIoMessage>) {
|
||||||
let mut guard = self.message_channel.lock();
|
*self.message_channel.lock() = Some(message_channel);
|
||||||
*guard = Some(message_channel);
|
}
|
||||||
|
|
||||||
|
fn register_account_provider(&self, account_provider: Arc<AccountProvider>) {
|
||||||
|
*self.account_provider.lock() = Some(account_provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user