use generic block number in GRANDPA

This commit is contained in:
Robert Habermeier
2018-10-25 18:00:46 +02:00
parent 08890f2bc1
commit a422a14b52
2 changed files with 42 additions and 25 deletions
+2 -1
View File
@@ -581,10 +581,11 @@ dependencies = [
[[package]] [[package]]
name = "finality-grandpa" name = "finality-grandpa"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/paritytech/finality-grandpa#fffce2dc450e72ff8b3f43818f8aceb5cfacc2d7" source = "git+https://github.com/paritytech/finality-grandpa#f1ad8d7ca020e5db0e51e32cd62e8cd3c578d121"
dependencies = [ dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+40 -24
View File
@@ -58,7 +58,7 @@ use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher};
use tokio::timer::Interval; use tokio::timer::Interval;
use grandpa::Error as GrandpaError; use grandpa::Error as GrandpaError;
use grandpa::{voter, round::State as RoundState, Prevote, Precommit, Equivocation}; use grandpa::{voter, round::State as RoundState, Equivocation, BlockNumberOps};
use std::collections::{VecDeque, HashMap}; use std::collections::{VecDeque, HashMap};
use std::sync::Arc; use std::sync::Arc;
@@ -72,12 +72,21 @@ const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
/// round-number, round-state, set indicator /// round-number, round-state, set indicator
type LastCompleted<H> = (u64, RoundState<H>, u64); type LastCompleted<H, N> = (u64, RoundState<H, N>, u64);
/// A GRANDPA message for a substrate chain. /// A GRANDPA message for a substrate chain.
pub type Message<Block> = grandpa::Message<<Block as BlockT>::Hash>; pub type Message<Block> = grandpa::Message<<Block as BlockT>::Hash, NumberFor<Block>>;
/// A signed message. /// A signed message.
pub type SignedMessage<Block> = grandpa::SignedMessage<<Block as BlockT>::Hash, ed25519::Signature, AuthorityId>; pub type SignedMessage<Block> = grandpa::SignedMessage<
<Block as BlockT>::Hash,
NumberFor<Block>,
ed25519::Signature,
AuthorityId,
>;
/// A prevote message for this chain's block type.
pub type Prevote<Block> = grandpa::Prevote<<Block as BlockT>::Hash, NumberFor<Block>>;
/// A precommit message for this chain's block type.
pub type Precommit<Block> = grandpa::Precommit<<Block as BlockT>::Hash, NumberFor<Block>>;
/// Configuration for the GRANDPA service. /// Configuration for the GRANDPA service.
pub struct Config { pub struct Config {
@@ -134,18 +143,17 @@ pub trait BlockStatus<Block: BlockT> {
/// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block /// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block
/// is definitely known and has been imported. /// is definitely known and has been imported.
/// If an unexpected error occurs, return that. /// If an unexpected error occurs, return that.
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error>; fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error>;
} }
impl<B, E, Block: BlockT> BlockStatus<Block> for Arc<Client<B, E, Block>> where impl<B, E, Block: BlockT> BlockStatus<Block> for Arc<Client<B, E, Block>> where
B: Backend<Block, Blake2Hasher>, B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>, E: CallExecutor<Block, Blake2Hasher>,
NumberFor<Block>: As<u32>, NumberFor<Block>: BlockNumberOps,
{ {
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error> { fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error> {
self.block_number_from_id(&BlockId::Hash(hash)) self.block_number_from_id(&BlockId::Hash(hash))
.map_err(|e| Error::Blockchain(format!("{:?}", e))) .map_err(|e| Error::Blockchain(format!("{:?}", e)))
.map(|num| num.map(|n| n.as_()))
} }
} }
@@ -415,13 +423,13 @@ pub struct Environment<B, E, Block: BlockT, N: Network> {
network: N, network: N,
} }
impl<Block: BlockT, B, E, N> grandpa::Chain<Block::Hash> for Environment<B, E, Block, N> where impl<Block: BlockT, B, E, N> grandpa::Chain<Block::Hash, NumberFor<Block>> for Environment<B, E, Block, N> where
Block: 'static, Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static, E: CallExecutor<Block, Blake2Hasher> + 'static,
N: Network + 'static, N: Network + 'static,
N::In: 'static, N::In: 'static,
NumberFor<Block>: As<u32>, NumberFor<Block>: BlockNumberOps,
DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>, DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>,
{ {
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> { fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
@@ -450,13 +458,13 @@ impl<Block: BlockT, B, E, N> grandpa::Chain<Block::Hash> for Environment<B, E, B
Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect())
} }
fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, u32)> { fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, NumberFor<Block>)> {
match self.inner.best_containing(block, None) { match self.inner.best_containing(block, None) {
Ok(Some(hash)) => { Ok(Some(hash)) => {
let header = self.inner.header(&BlockId::Hash(hash)).ok()? let header = self.inner.header(&BlockId::Hash(hash)).ok()?
.expect("Header known to exist after `best_containing` call; qed"); .expect("Header known to exist after `best_containing` call; qed");
Some((hash, header.number().as_())) Some((hash, header.number().clone()))
} }
Ok(None) => None, Ok(None) => None,
Err(e) => { Err(e) => {
@@ -486,20 +494,26 @@ pub trait CompatibleDigestItem<N> {
fn scheduled_change(&self) -> Option<ScheduledChange<N>> { None } fn scheduled_change(&self) -> Option<ScheduledChange<N>> { None }
} }
impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B, E, Block, N> where impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash, NumberFor<Block>> for Environment<B, E, Block, N> where
Block: 'static, Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static, E: CallExecutor<Block, Blake2Hasher> + 'static,
N: Network + 'static, N: Network + 'static,
N::In: 'static, N::In: 'static,
NumberFor<Block>: As<u32>, NumberFor<Block>: BlockNumberOps,
DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>, DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>,
{ {
type Timer = Box<Future<Item = (), Error = Self::Error>>; type Timer = Box<Future<Item = (), Error = Self::Error>>;
type Id = AuthorityId; type Id = AuthorityId;
type Signature = ed25519::Signature; type Signature = ed25519::Signature;
type In = Box<Stream<Item = ::grandpa::SignedMessage<Block::Hash, Self::Signature, Self::Id>, Error = Self::Error>>; type In = Box<Stream<
type Out = Box<Sink<SinkItem = ::grandpa::Message<Block::Hash>, SinkError = Self::Error>>; Item = ::grandpa::SignedMessage<Block::Hash, NumberFor<Block>, Self::Signature, Self::Id>,
Error = Self::Error,
>>;
type Out = Box<Sink<
SinkItem = ::grandpa::Message<Block::Hash, NumberFor<Block>>,
SinkError = Self::Error,
>>;
type Error = Error; type Error = Error;
#[allow(unreachable_code)] #[allow(unreachable_code)]
@@ -560,7 +574,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
} }
} }
fn completed(&self, round: u64, state: RoundState<Block::Hash>) -> Result<(), Self::Error> { fn completed(&self, round: u64, state: RoundState<Block::Hash, NumberFor<Block>>) -> Result<(), Self::Error> {
let encoded_state = (round, state).encode(); let encoded_state = (round, state).encode();
if let Err(e) = self.inner.backend() if let Err(e) = self.inner.backend()
.insert_aux(&[(LAST_COMPLETED_KEY, &encoded_state[..])], &[]) .insert_aux(&[(LAST_COMPLETED_KEY, &encoded_state[..])], &[])
@@ -572,7 +586,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
} }
} }
fn finalize_block(&self, hash: Block::Hash, number: u32) -> Result<(), Self::Error> { fn finalize_block(&self, hash: Block::Hash, number: NumberFor<Block>) -> Result<(), Self::Error> {
// TODO: don't unconditionally notify. // TODO: don't unconditionally notify.
if let Err(e) = self.inner.finalize_block(BlockId::Hash(hash), true) { if let Err(e) = self.inner.finalize_block(BlockId::Hash(hash), true) {
warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e);
@@ -586,7 +600,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
fn prevote_equivocation( fn prevote_equivocation(
&self, &self,
_round: u64, _round: u64,
equivocation: ::grandpa::Equivocation<Self::Id, Prevote<Block::Hash>, Self::Signature> equivocation: ::grandpa::Equivocation<Self::Id, Prevote<Block>, Self::Signature>
) { ) {
warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation);
// nothing yet; this could craft misbehavior reports of some kind. // nothing yet; this could craft misbehavior reports of some kind.
@@ -595,7 +609,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
fn precommit_equivocation( fn precommit_equivocation(
&self, &self,
_round: u64, _round: u64,
equivocation: Equivocation<Self::Id, Precommit<Block::Hash>, Self::Signature> equivocation: Equivocation<Self::Id, Precommit<Block>, Self::Signature>
) { ) {
warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation);
// nothing yet // nothing yet
@@ -658,19 +672,21 @@ pub fn run_grandpa<B, E, Block: BlockT, N>(
E: CallExecutor<Block, Blake2Hasher> + 'static, E: CallExecutor<Block, Blake2Hasher> + 'static,
N: Network + 'static, N: Network + 'static,
N::In: 'static, N::In: 'static,
NumberFor<Block>: As<u32>, NumberFor<Block>: BlockNumberOps,
DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>, DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>,
{ {
use runtime_primitives::traits::Zero;
let chain_info = client.info()?; let chain_info = client.info()?;
let genesis_hash = chain_info.chain.genesis_hash; let genesis_hash = chain_info.chain.genesis_hash;
let last_finalized = ( let last_finalized = (
chain_info.chain.finalized_hash, chain_info.chain.finalized_hash,
chain_info.chain.finalized_number.as_() chain_info.chain.finalized_number,
); );
let (last_round_number, last_state) = match client.backend().get_aux(LAST_COMPLETED_KEY)? { let (last_round_number, last_state) = match client.backend().get_aux(LAST_COMPLETED_KEY)? {
None => (0, RoundState::genesis((genesis_hash, 0))), None => (0, RoundState::genesis((genesis_hash, <NumberFor<Block>>::zero()))),
Some(raw) => <(u64, RoundState<Block::Hash>)>::decode(&mut &raw[..]) Some(raw) => <(u64, RoundState<Block::Hash, NumberFor<Block>>)>::decode(&mut &raw[..])
.ok_or_else(|| ::client::error::ErrorKind::Backend( .ok_or_else(|| ::client::error::ErrorKind::Backend(
format!("Last GRANDPA round state kept in invalid format") format!("Last GRANDPA round state kept in invalid format")
))? ))?