docs, tweaks
This commit is contained in:
parent
3ebfa1481d
commit
dca752e9bb
@ -14,7 +14,12 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Tendermint BFT consensus engine with round robin proof-of-authority.
|
/// Tendermint BFT consensus engine with round robin proof-of-authority.
|
||||||
|
/// At each blockchain `Height` there can be multiple `Round`s of voting.
|
||||||
|
/// Block is issued when there is enough `Precommit` votes collected on a particular block at the end of a `Round`.
|
||||||
|
/// Signatures always sign `Height`, `Round`, `Step` and `BlockHash` which is a block hash without seal.
|
||||||
|
/// First a block with `Seal::Proposal` is issued by the designated proposer.
|
||||||
|
/// Once enough votes have been gathered the proposer issues that block in the `Commit` step.
|
||||||
|
|
||||||
mod message;
|
mod message;
|
||||||
mod transition;
|
mod transition;
|
||||||
@ -191,10 +196,11 @@ impl Tendermint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_height(&self, height: Height) {
|
fn to_next_height(&self, height: Height) {
|
||||||
debug!(target: "poa", "Transitioning to height {}.", height);
|
let new_height = height + 1;
|
||||||
|
debug!(target: "poa", "Received a Commit, transitioning to height {}.", new_height);
|
||||||
self.last_lock.store(0, AtomicOrdering::SeqCst);
|
self.last_lock.store(0, AtomicOrdering::SeqCst);
|
||||||
self.height.store(height, AtomicOrdering::SeqCst);
|
self.height.store(new_height, AtomicOrdering::SeqCst);
|
||||||
self.round.store(0, AtomicOrdering::SeqCst);
|
self.round.store(0, AtomicOrdering::SeqCst);
|
||||||
*self.lock_change.write() = None;
|
*self.lock_change.write() = None;
|
||||||
}
|
}
|
||||||
@ -232,20 +238,21 @@ impl Tendermint {
|
|||||||
let height = self.height.load(AtomicOrdering::SeqCst);
|
let height = self.height.load(AtomicOrdering::SeqCst);
|
||||||
if let Some(block_hash) = *self.proposal.read() {
|
if let Some(block_hash) = *self.proposal.read() {
|
||||||
// Generate seal and remove old votes.
|
// Generate seal and remove old votes.
|
||||||
|
if self.is_proposer(&*self.authority.read()).is_ok() {
|
||||||
if let Some(seal) = self.votes.seal_signatures(height, round, block_hash) {
|
if let Some(seal) = self.votes.seal_signatures(height, round, block_hash) {
|
||||||
trace!(target: "poa", "to_step: Collected seal: {:?}", seal);
|
trace!(target: "poa", "to_step: Collected seal: {:?}", seal);
|
||||||
if self.is_proposer(&*self.authority.read()).is_ok() {
|
|
||||||
let seal = vec![
|
let seal = vec![
|
||||||
::rlp::encode(&round).to_vec(),
|
::rlp::encode(&round).to_vec(),
|
||||||
::rlp::encode(&seal.proposal).to_vec(),
|
::rlp::encode(&seal.proposal).to_vec(),
|
||||||
::rlp::encode(&seal.votes).to_vec()
|
::rlp::encode(&seal.votes).to_vec()
|
||||||
];
|
];
|
||||||
self.submit_seal(block_hash, seal);
|
self.submit_seal(block_hash, seal);
|
||||||
}
|
self.to_next_height(height);
|
||||||
} else {
|
} else {
|
||||||
warn!(target: "poa", "Proposal was not found!");
|
warn!(target: "poa", "Proposal was not found!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,10 +296,6 @@ impl Tendermint {
|
|||||||
self.round.fetch_add(n, AtomicOrdering::SeqCst);
|
self.round.fetch_add(n, AtomicOrdering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_height(&self) {
|
|
||||||
self.to_height(self.height.load(AtomicOrdering::SeqCst) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_unlock(&self, lock_change_round: Round) -> bool {
|
fn should_unlock(&self, lock_change_round: Round) -> bool {
|
||||||
self.last_lock.load(AtomicOrdering::SeqCst) < lock_change_round
|
self.last_lock.load(AtomicOrdering::SeqCst) < lock_change_round
|
||||||
&& lock_change_round < self.round.load(AtomicOrdering::SeqCst)
|
&& lock_change_round < self.round.load(AtomicOrdering::SeqCst)
|
||||||
@ -414,7 +417,7 @@ impl Engine for Tendermint {
|
|||||||
let header = block.header();
|
let header = block.header();
|
||||||
let author = header.author();
|
let author = header.author();
|
||||||
// Only proposer can generate seal if None was generated.
|
// Only proposer can generate seal if None was generated.
|
||||||
if self.is_proposer(author).is_err() && self.proposal.read().is_none() {
|
if self.is_proposer(author).is_err() || self.proposal.read().is_some() {
|
||||||
return Seal::None;
|
return Seal::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,6 +431,7 @@ impl Engine for Tendermint {
|
|||||||
self.votes.vote(ConsensusMessage::new(signature, height, round, Step::Propose, bh), *author);
|
self.votes.vote(ConsensusMessage::new(signature, height, round, Step::Propose, bh), *author);
|
||||||
// Remember proposal for later seal submission.
|
// Remember proposal for later seal submission.
|
||||||
*self.proposal.write() = bh;
|
*self.proposal.write() = bh;
|
||||||
|
assert!(self.is_round_proposer(height, round, author).is_ok());
|
||||||
Seal::Proposal(vec![
|
Seal::Proposal(vec![
|
||||||
::rlp::encode(&round).to_vec(),
|
::rlp::encode(&round).to_vec(),
|
||||||
::rlp::encode(&signature).to_vec(),
|
::rlp::encode(&signature).to_vec(),
|
||||||
@ -509,13 +513,8 @@ impl Engine for Tendermint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_above_threshold(signature_count) {
|
|
||||||
// Skip ahead if block is from the future.
|
|
||||||
if proposal.height > self.height.load(AtomicOrdering::SeqCst) {
|
|
||||||
self.to_height(proposal.height);
|
|
||||||
}
|
|
||||||
// Check if its a proposal if there is not enough precommits.
|
// Check if its a proposal if there is not enough precommits.
|
||||||
} else {
|
if !self.is_above_threshold(signature_count) {
|
||||||
let signatures_len = signatures_field.len();
|
let signatures_len = signatures_field.len();
|
||||||
// Proposal has to have an empty signature list.
|
// Proposal has to have an empty signature list.
|
||||||
if signatures_len != 1 {
|
if signatures_len != 1 {
|
||||||
@ -563,9 +562,9 @@ impl Engine for Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
||||||
trace!(target: "poa", "new_header: {}, best_header: {}", new_header.number(), best_header.number());
|
|
||||||
let new_number = new_header.number();
|
let new_number = new_header.number();
|
||||||
let best_number = best_header.number();
|
let best_number = best_header.number();
|
||||||
|
trace!(target: "poa", "new_header: {}, best_header: {}", new_number, best_number);
|
||||||
if new_number != best_number {
|
if new_number != best_number {
|
||||||
new_number > best_number
|
new_number > best_number
|
||||||
} else {
|
} else {
|
||||||
@ -586,10 +585,12 @@ impl Engine for Tendermint {
|
|||||||
fn is_proposal(&self, header: &Header) -> bool {
|
fn is_proposal(&self, header: &Header) -> bool {
|
||||||
let signatures_len = header.seal()[2].len();
|
let signatures_len = header.seal()[2].len();
|
||||||
// Signatures have to be an empty list rlp.
|
// Signatures have to be an empty list rlp.
|
||||||
|
let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed");
|
||||||
if signatures_len != 1 {
|
if signatures_len != 1 {
|
||||||
|
// New Commit received, skip to next height.
|
||||||
|
self.to_next_height(proposal.height);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed");
|
|
||||||
let proposer = proposal.verify().expect("block went through full verification; this Engine tries verify; qed");
|
let proposer = proposal.verify().expect("block went through full verification; this Engine tries verify; qed");
|
||||||
debug!(target: "poa", "Received a new proposal for height {}, round {} from {}.", proposal.height, proposal.round, proposer);
|
debug!(target: "poa", "Received a new proposal for height {}, round {} from {}.", proposal.height, proposal.round, proposer);
|
||||||
if self.is_round(&proposal) {
|
if self.is_round(&proposal) {
|
||||||
|
@ -106,7 +106,6 @@ impl IoHandler<Step> for TransitionHandler {
|
|||||||
Step::Commit => {
|
Step::Commit => {
|
||||||
trace!(target: "poa", "timeout: Commit timeout.");
|
trace!(target: "poa", "timeout: Commit timeout.");
|
||||||
set_timeout(io, engine.our_params.timeouts.propose);
|
set_timeout(io, engine.our_params.timeouts.propose);
|
||||||
engine.new_height();
|
|
||||||
Some(Step::Propose)
|
Some(Step::Propose)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -469,9 +469,11 @@ impl Miner {
|
|||||||
// Save proposal for later seal submission and broadcast it.
|
// Save proposal for later seal submission and broadcast it.
|
||||||
Seal::Proposal(seal) => {
|
Seal::Proposal(seal) => {
|
||||||
trace!(target: "miner", "Received a Proposal seal.");
|
trace!(target: "miner", "Received a Proposal seal.");
|
||||||
|
{
|
||||||
let mut sealing_work = self.sealing_work.lock();
|
let mut sealing_work = self.sealing_work.lock();
|
||||||
sealing_work.queue.push(block.clone());
|
sealing_work.queue.push(block.clone());
|
||||||
sealing_work.queue.use_last_ref();
|
sealing_work.queue.use_last_ref();
|
||||||
|
}
|
||||||
block
|
block
|
||||||
.lock()
|
.lock()
|
||||||
.seal(&*self.engine, seal)
|
.seal(&*self.engine, seal)
|
||||||
|
Loading…
Reference in New Issue
Block a user