Unverified Commit 5898cafc authored by André Silva's avatar André Silva Committed by GitHub
Browse files

node: migrate grandpa voting rule to async api (#2422)



* node: migrate grandpa voting rule to async api

* node: fix grandpa voting rule tests

* "Update Substrate"

* update Substrate

Co-authored-by: parity-processbot <>
Co-authored-by: asynchronous rob's avatarRobert Habermeier <rphmeier@gmail.com>
parent d376fe66
Pipeline #124217 passed with stages
in 33 minutes and 52 seconds
This diff is collapsed.
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
//! Polkadot-specific GRANDPA integration utilities. //! Polkadot-specific GRANDPA integration utilities.
use std::sync::Arc;
#[cfg(feature = "full-node")] #[cfg(feature = "full-node")]
use polkadot_primitives::v1::Hash; use polkadot_primitives::v1::Hash;
use sp_runtime::traits::{Block as BlockT, NumberFor}; use sp_runtime::traits::{Block as BlockT, NumberFor};
...@@ -24,6 +26,7 @@ use sp_runtime::traits::{Block as BlockT, NumberFor}; ...@@ -24,6 +26,7 @@ use sp_runtime::traits::{Block as BlockT, NumberFor};
/// same last finalized block) after a given block at height `N` has been /// same last finalized block) after a given block at height `N` has been
/// finalized and for a delay of `M` blocks, i.e. until the best block reaches /// finalized and for a delay of `M` blocks, i.e. until the best block reaches
/// `N` + `M`, the voter will keep voting for block `N`. /// `N` + `M`, the voter will keep voting for block `N`.
#[derive(Clone)]
pub(crate) struct PauseAfterBlockFor<N>(pub(crate) N, pub(crate) N); pub(crate) struct PauseAfterBlockFor<N>(pub(crate) N, pub(crate) N);
impl<Block, B> grandpa::VotingRule<Block, B> for PauseAfterBlockFor<NumberFor<Block>> impl<Block, B> grandpa::VotingRule<Block, B> for PauseAfterBlockFor<NumberFor<Block>>
...@@ -33,59 +36,66 @@ where ...@@ -33,59 +36,66 @@ where
{ {
fn restrict_vote( fn restrict_vote(
&self, &self,
backend: &B, backend: Arc<B>,
base: &Block::Header, base: &Block::Header,
best_target: &Block::Header, best_target: &Block::Header,
current_target: &Block::Header, current_target: &Block::Header,
) -> Option<(Block::Hash, NumberFor<Block>)> { ) -> grandpa::VotingRuleResult<Block> {
use sp_runtime::generic::BlockId; let aux = || {
use sp_runtime::traits::Header as _; use sp_runtime::generic::BlockId;
use sp_runtime::traits::Header as _;
// walk backwards until we find the target block
let find_target = |target_number: NumberFor<Block>, current_header: &Block::Header| { // walk backwards until we find the target block
let mut target_hash = current_header.hash(); let find_target = |target_number: NumberFor<Block>, current_header: &Block::Header| {
let mut target_header = current_header.clone(); let mut target_hash = current_header.hash();
let mut target_header = current_header.clone();
loop {
if *target_header.number() < target_number { loop {
unreachable!( if *target_header.number() < target_number {
"we are traversing backwards from a known block; \ unreachable!(
blocks are stored contiguously; \ "we are traversing backwards from a known block; \
qed" blocks are stored contiguously; \
qed"
);
}
if *target_header.number() == target_number {
return Some((target_hash, target_number));
}
target_hash = *target_header.parent_hash();
target_header = backend.header(BlockId::Hash(target_hash)).ok()?.expect(
"Header known to exist due to the existence of one of its descendents; qed",
); );
} }
};
if *target_header.number() == target_number {
return Some((target_hash, target_number)); // only restrict votes targeting a block higher than the block
// we've set for the pause
if *current_target.number() > self.0 {
// if we're past the pause period (i.e. `self.0 + self.1`)
// then we no longer need to restrict any votes
if *best_target.number() > self.0 + self.1 {
return None;
} }
target_hash = *target_header.parent_hash(); // if we've finalized the pause block, just keep returning it
target_header = backend.header(BlockId::Hash(target_hash)).ok()? // until best number increases enough to pass the condition above
.expect("Header known to exist due to the existence of one of its descendents; qed"); if *base.number() >= self.0 {
} return Some((base.hash(), *base.number()));
}; }
// only restrict votes targeting a block higher than the block // otherwise find the target header at the pause block
// we've set for the pause // to vote on
if *current_target.number() > self.0 { return find_target(self.0, current_target);
// if we're past the pause period (i.e. `self.0 + self.1`)
// then we no longer need to restrict any votes
if *best_target.number() > self.0 + self.1 {
return None;
} }
// if we've finalized the pause block, just keep returning it None
// until best number increases enough to pass the condition above };
if *base.number() >= self.0 {
return Some((base.hash(), *base.number()));
}
// otherwise find the target header at the pause block let target = aux();
// to vote on
return find_target(self.0, current_target);
}
None Box::pin(async move { target })
} }
} }
...@@ -276,7 +286,12 @@ mod tests { ...@@ -276,7 +286,12 @@ mod tests {
// we have not reached the pause block // we have not reached the pause block
// therefore nothing should be restricted // therefore nothing should be restricted
assert_eq!( assert_eq!(
voting_rule.restrict_vote(&*client, &get_header(0), &get_header(10), &get_header(10)), futures::executor::block_on(voting_rule.restrict_vote(
client.clone(),
&get_header(0),
&get_header(10),
&get_header(10)
)),
None, None,
); );
...@@ -287,7 +302,12 @@ mod tests { ...@@ -287,7 +302,12 @@ mod tests {
// we are targeting the pause block, // we are targeting the pause block,
// the vote should not be restricted // the vote should not be restricted
assert_eq!( assert_eq!(
voting_rule.restrict_vote(&*client, &get_header(10), &get_header(20), &get_header(20)), futures::executor::block_on(voting_rule.restrict_vote(
client.clone(),
&get_header(10),
&get_header(20),
&get_header(20)
)),
None, None,
); );
...@@ -295,19 +315,24 @@ mod tests { ...@@ -295,19 +315,24 @@ mod tests {
// be limited to the pause block. // be limited to the pause block.
let pause_block = get_header(20); let pause_block = get_header(20);
assert_eq!( assert_eq!(
voting_rule.restrict_vote(&*client, &get_header(10), &get_header(21), &get_header(21)), futures::executor::block_on(voting_rule.restrict_vote(
client.clone(),
&get_header(10),
&get_header(21),
&get_header(21)
)),
Some((pause_block.hash(), *pause_block.number())), Some((pause_block.hash(), *pause_block.number())),
); );
// we've finalized the pause block, so we'll keep // we've finalized the pause block, so we'll keep
// restricting our votes to it. // restricting our votes to it.
assert_eq!( assert_eq!(
voting_rule.restrict_vote( futures::executor::block_on(voting_rule.restrict_vote(
&*client, client.clone(),
&pause_block, // #20 &pause_block, // #20
&get_header(21), &get_header(21),
&get_header(21), &get_header(21),
), )),
Some((pause_block.hash(), *pause_block.number())), Some((pause_block.hash(), *pause_block.number())),
); );
...@@ -318,23 +343,23 @@ mod tests { ...@@ -318,23 +343,23 @@ mod tests {
// we're at the last block of the pause, this block // we're at the last block of the pause, this block
// should still be considered in the pause period // should still be considered in the pause period
assert_eq!( assert_eq!(
voting_rule.restrict_vote( futures::executor::block_on(voting_rule.restrict_vote(
&*client, client.clone(),
&pause_block, // #20 &pause_block, // #20
&get_header(50), &get_header(50),
&get_header(50), &get_header(50),
), )),
Some((pause_block.hash(), *pause_block.number())), Some((pause_block.hash(), *pause_block.number())),
); );
// we're past the pause period, no votes should be filtered // we're past the pause period, no votes should be filtered
assert_eq!( assert_eq!(
voting_rule.restrict_vote( futures::executor::block_on(voting_rule.restrict_vote(
&*client, client.clone(),
&pause_block, // #20 &pause_block, // #20
&get_header(51), &get_header(51),
&get_header(51), &get_header(51),
), )),
None, None,
); );
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment