removes use of sc_client::Client from sc_finality_grandpa (#5030)

* removes use of sc_client::Client from sc_finality_grandpa

* code formatting

* code formatting

* removes use of sc_client::Client from sc_finality_grandpa
This commit is contained in:
Seun Lanlege
2020-02-27 12:19:07 +01:00
committed by GitHub
parent bad9647af9
commit 5907b0d902
13 changed files with 333 additions and 309 deletions
+2 -1
View File
@@ -21,8 +21,9 @@ assert_matches = "1.3.0"
parity-scale-codec = { version = "1.0.0", features = ["derive"] }
sp-arithmetic = { version = "2.0.0-alpha.2", path = "../../primitives/arithmetic" }
sp-runtime = { version = "2.0.0-alpha.2", path = "../../primitives/runtime" }
sp-consensus = { version = "0.8.0-alpha.2", path = "../../primitives/consensus/common" }
sp-consensus = { version = "0.8.0-alpha.1", path = "../../primitives/consensus/common" }
sp-core = { version = "2.0.0-alpha.2", path = "../../primitives/core" }
sp-api = { version = "2.0.0-alpha.2", path = "../../primitives/api" }
sc-telemetry = { version = "2.0.0-alpha.2", path = "../telemetry" }
sc-keystore = { version = "2.0.0-alpha.2", path = "../keystore" }
serde_json = "1.0.41"
@@ -25,18 +25,14 @@ use parity_scale_codec::{Decode, Encode};
use futures::prelude::*;
use futures_timer::Delay;
use parking_lot::RwLock;
use sp_blockchain::{HeaderBackend, Error as ClientError};
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
use std::marker::PhantomData;
use sc_client_api::{
BlockchainEvents,
backend::{AuxStore, Backend},
Finalizer,
call_executor::CallExecutor,
backend::Backend,
utils::is_descendent_of,
};
use sc_client::{
apply_aux, Client,
};
use sc_client::apply_aux;
use finality_grandpa::{
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet,
@@ -377,8 +373,8 @@ impl<Block: BlockT> SharedVoterSetState<Block> {
}
/// The environment we run GRANDPA in.
pub(crate) struct Environment<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> {
pub(crate) client: Arc<Client<B, E, Block, RA>>,
pub(crate) struct Environment<Backend, Block: BlockT, C, N: NetworkT<Block>, SC, VR> {
pub(crate) client: Arc<C>,
pub(crate) select_chain: SC,
pub(crate) voters: Arc<VoterSet<AuthorityId>>,
pub(crate) config: Config,
@@ -388,9 +384,10 @@ pub(crate) struct Environment<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, V
pub(crate) set_id: SetId,
pub(crate) voter_set_state: SharedVoterSetState<Block>,
pub(crate) voting_rule: VR,
pub(crate) _phantom: PhantomData<Backend>,
}
impl<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> Environment<B, E, Block, N, RA, SC, VR> {
impl<Backend, Block: BlockT, C, N: NetworkT<Block>, SC, VR> Environment<Backend, Block, C, N, SC, VR> {
/// Updates the voter set state using the given closure. The write lock is
/// held during evaluation of the closure and the environment's voter set
/// state is set to its result if successful.
@@ -406,17 +403,16 @@ impl<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> Environment<B, E, Bloc
}
}
impl<Block: BlockT, B, E, N, RA, SC, VR>
impl<BE, Block: BlockT, C, N, SC, VR>
finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
for Environment<BE, Block, C, N, SC, VR>
where
Block: 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync,
BE: Backend<Block>,
C: crate::ClientForGrandpa<Block, BE>,
N: NetworkT<Block> + 'static + Send,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
RA: Send + Sync,
VR: VotingRule<Block, C>,
NumberFor<Block>: BlockNumberOps,
{
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
@@ -432,7 +428,7 @@ where
return None;
}
let base_header = match self.client.header(&BlockId::Hash(block)).ok()? {
let base_header = match self.client.header(BlockId::Hash(block)).ok()? {
Some(h) => h,
None => {
debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find base block", block);
@@ -450,7 +446,7 @@ where
match self.select_chain.finality_target(block, None) {
Ok(Some(best_hash)) => {
let best_header = self.client.header(&BlockId::Hash(best_hash)).ok()?
let best_header = self.client.header(BlockId::Hash(best_hash)).ok()?
.expect("Header known to exist after `finality_target` call; qed");
// check if our vote is currently being limited due to a pending change
@@ -474,7 +470,7 @@ where
break;
}
target_header = self.client.header(&BlockId::Hash(*target_header.parent_hash())).ok()?
target_header = self.client.header(BlockId::Hash(*target_header.parent_hash())).ok()?
.expect("Header known to exist after `finality_target` call; qed");
}
@@ -519,17 +515,16 @@ where
}
pub(crate) fn ancestry<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
pub(crate) fn ancestry<Block: BlockT, Client>(
client: &Arc<Client>,
base: Block::Hash,
block: Block::Hash,
) -> Result<Vec<Block::Hash>, GrandpaError> where
B: Backend<Block>,
E: CallExecutor<Block>,
Client: HeaderMetadata<Block, Error = sp_blockchain::Error>,
{
if base == block { return Err(GrandpaError::NotDescendent) }
let tree_route_res = sp_blockchain::tree_route(client, block, base);
let tree_route_res = sp_blockchain::tree_route(&**client, block, base);
let tree_route = match tree_route_res {
Ok(tree_route) => tree_route,
@@ -550,19 +545,17 @@ pub(crate) fn ancestry<B, Block: BlockT, E, RA>(
Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect())
}
impl<B, E, Block: BlockT, N, RA, SC, VR>
impl<B, Block: BlockT, C, N, SC, VR>
voter::Environment<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
for Environment<B, Block, C, N, SC, VR>
where
Block: 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Send + Sync,
B: Backend<Block>,
C: crate::ClientForGrandpa<Block, B> + 'static,
N: NetworkT<Block> + 'static + Send,
RA: 'static + Send + Sync,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
VR: VotingRule<Block, C>,
NumberFor<Block>: BlockNumberOps,
Client<B, E, Block, RA>: AuxStore,
{
type Timer = Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send>>;
type Id = AuthorityId;
@@ -882,7 +875,7 @@ where
commit: Commit<Block>,
) -> Result<(), Self::Error> {
finalize_block(
&*self.client,
self.client.clone(),
&self.authority_set,
&self.consensus_changes,
Some(self.config.justification_period.into()),
@@ -940,8 +933,8 @@ impl<Block: BlockT> From<GrandpaJustification<Block>> for JustificationOrCommit<
/// authority set change is enacted then a justification is created (if not
/// given) and stored with the block when finalizing it.
/// This method assumes that the block being finalized has already been imported.
pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
pub(crate) fn finalize_block<BE, Block, Client>(
client: Arc<Client>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
justification_period: Option<NumberFor<Block>>,
@@ -949,16 +942,16 @@ pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
number: NumberFor<Block>,
justification_or_commit: JustificationOrCommit<Block>,
) -> Result<(), CommandOrError<Block::Hash, NumberFor<Block>>> where
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
Block: BlockT,
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
{
// NOTE: lock must be held through writing to DB to avoid race. this lock
// also implicitly synchronizes the check for last finalized number
// below.
let mut authority_set = authority_set.inner().write();
let status = client.chain_info();
let status = client.info();
if number <= status.finalized_number && client.hash(number)? == Some(hash) {
// This can happen after a forced change (triggered by the finality tracker when finality is stalled), since
// the voter will be restarted at the median last finalized block, which can be lower than the local best
@@ -981,14 +974,14 @@ pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
let mut consensus_changes = consensus_changes.lock();
let canon_at_height = |canon_number| {
// "true" because the block is finalized
canonical_at_height(client, (hash, number), true, canon_number)
canonical_at_height(&*client, (hash, number), true, canon_number)
};
let update_res: Result<_, Error> = client.lock_import_and_run(|import_op| {
let status = authority_set.apply_standard_changes(
hash,
number,
&is_descendent_of::<Block, _>(client, None),
&is_descendent_of::<Block, _>(&*client, None),
).map_err(|e| Error::Safety(e.to_string()))?;
// check if this is this is the first finalization of some consensus changes
@@ -1031,7 +1024,7 @@ pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
// finalization to remote nodes
if !justification_required {
if let Some(justification_period) = justification_period {
let last_finalized_number = client.chain_info().finalized_number;
let last_finalized_number = client.info().finalized_number;
justification_required =
(!last_finalized_number.is_zero() || number - last_finalized_number == justification_period) &&
(last_finalized_number / justification_period != number / justification_period);
@@ -1040,7 +1033,7 @@ pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
if justification_required {
let justification = GrandpaJustification::from_commit(
client,
&client,
round_number,
commit,
)?;
+44 -43
View File
@@ -21,9 +21,10 @@ use parity_scale_codec::Encode;
use futures::channel::mpsc;
use parking_lot::RwLockWriteGuard;
use sp_blockchain::{HeaderBackend, BlockStatus, well_known_cache_keys};
use sc_client_api::{backend::{TransactionFor, Backend}, CallExecutor, utils::is_descendent_of};
use sc_client::Client;
use sp_blockchain::{BlockStatus, well_known_cache_keys};
use sc_client_api::{backend::Backend, utils::is_descendent_of};
use sp_api::{TransactionFor};
use sp_consensus::{
BlockImport, Error as ConsensusError,
BlockCheckParams, BlockImportParams, ImportResult, JustificationImport,
@@ -41,6 +42,7 @@ use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingCha
use crate::consensus_changes::SharedConsensusChanges;
use crate::environment::finalize_block;
use crate::justification::GrandpaJustification;
use std::marker::PhantomData;
/// A block-import handler for GRANDPA.
///
@@ -51,16 +53,17 @@ use crate::justification::GrandpaJustification;
///
/// When using GRANDPA, the block import worker should be using this block import
/// object.
pub struct GrandpaBlockImport<B, E, Block: BlockT, RA, SC> {
inner: Arc<Client<B, E, Block, RA>>,
pub struct GrandpaBlockImport<Backend, Block: BlockT, Client, SC> {
inner: Arc<Client>,
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
_phantom: PhantomData<Backend>,
}
impl<B, E, Block: BlockT, RA, SC: Clone> Clone for
GrandpaBlockImport<B, E, Block, RA, SC>
impl<Backend, Block: BlockT, Client, SC: Clone> Clone for
GrandpaBlockImport<Backend, Block, Client, SC>
{
fn clone(&self) -> Self {
GrandpaBlockImport {
@@ -69,24 +72,24 @@ impl<B, E, Block: BlockT, RA, SC: Clone> Clone for
authority_set: self.authority_set.clone(),
send_voter_commands: self.send_voter_commands.clone(),
consensus_changes: self.consensus_changes.clone(),
_phantom: PhantomData,
}
}
}
impl<B, E, Block: BlockT, RA, SC> JustificationImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
impl<BE, Block: BlockT, Client, SC> JustificationImport<Block>
for GrandpaBlockImport<BE, Block, Client, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
SC: SelectChain<Block>,
{
type Error = ConsensusError;
fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor<Block>)> {
let mut out = Vec::new();
let chain_info = self.inner.chain_info();
let chain_info = self.inner.info();
// request justifications for all pending changes for which change blocks have already been imported
let authorities = self.authority_set.inner().read();
@@ -105,7 +108,7 @@ impl<B, E, Block: BlockT, RA, SC> JustificationImport<Block>
};
if let Ok(Some(hash)) = effective_block_hash {
if let Ok(Some(header)) = self.inner.header(&BlockId::Hash(hash)) {
if let Ok(Some(header)) = self.inner.header(BlockId::Hash(hash)) {
if *header.number() == pending_change.effective_number() {
out.push((header.hash(), *header.number()));
}
@@ -123,7 +126,7 @@ impl<B, E, Block: BlockT, RA, SC> JustificationImport<Block>
number: NumberFor<Block>,
justification: Justification,
) -> Result<(), Self::Error> {
self.import_justification(hash, number, justification, false)
GrandpaBlockImport::import_justification(self, hash, number, justification, false)
}
}
@@ -200,14 +203,13 @@ fn find_forced_change<B: BlockT>(header: &B::Header)
header.digest().convert_first(|l| l.try_to(id).and_then(filter_log))
}
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
impl<BE, Block: BlockT, Client, SC>
GrandpaBlockImport<BE, Block, Client, SC>
where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
{
// check for a new authority set change.
fn check_new_change(&self, header: &Block::Header, hash: Block::Hash)
@@ -235,11 +237,11 @@ where
})
}
fn make_authorities_changes<'a>(
&'a self,
block: &mut BlockImportParams<Block, TransactionFor<B, Block>>,
fn make_authorities_changes(
&self,
block: &mut BlockImportParams<Block, TransactionFor<Client, Block>>,
hash: Block::Hash,
) -> Result<PendingSetChanges<'a, Block>, ConsensusError> {
) -> Result<PendingSetChanges<Block>, ConsensusError> {
// when we update the authorities, we need to hold the lock
// until the block is written to prevent a race if we need to restore
// the old authority set on error or panic.
@@ -325,10 +327,10 @@ where
// for the canon block the new authority set should start
// with. we use the minimum between the median and the local
// best finalized block.
let best_finalized_number = self.inner.chain_info().finalized_number;
let best_finalized_number = self.inner.info().finalized_number;
let canon_number = best_finalized_number.min(median_last_finalized_number);
let canon_hash =
self.inner.header(&BlockId::Number(canon_number))
self.inner.header(BlockId::Number(canon_number))
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?
.expect("the given block number is less or equal than the current best finalized number; \
current best finalized number must exist in chain; qed.")
@@ -380,18 +382,17 @@ where
}
}
impl<B, E, Block: BlockT, RA, SC> BlockImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
impl<BE, Block: BlockT, Client, SC> BlockImport<Block>
for GrandpaBlockImport<BE, Block, Client, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>,
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
for<'a> &'a Client:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<Client, Block>>,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
type Transaction = TransactionFor<Client, Block>;
fn import_block(
&mut self,
@@ -521,31 +522,31 @@ impl<B, E, Block: BlockT, RA, SC> BlockImport<Block>
}
}
impl<B, E, Block: BlockT, RA, SC> GrandpaBlockImport<B, E, Block, RA, SC> {
impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Client, SC> {
pub(crate) fn new(
inner: Arc<Client<B, E, Block, RA>>,
inner: Arc<Client>,
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
) -> GrandpaBlockImport<B, E, Block, RA, SC> {
) -> GrandpaBlockImport<Backend, Block, Client, SC> {
GrandpaBlockImport {
inner,
select_chain,
authority_set,
send_voter_commands,
consensus_changes,
_phantom: PhantomData,
}
}
}
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
impl<BE, Block: BlockT, Client, SC>
GrandpaBlockImport<BE, Block, Client, SC>
where
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
/// Import a block justification and finalize the block.
@@ -572,7 +573,7 @@ where
};
let result = finalize_block(
&*self.inner,
self.inner.clone(),
&self.authority_set,
&self.consensus_changes,
None,
@@ -15,10 +15,9 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use sc_client::Client;
use sc_client_api::{CallExecutor, backend::Backend};
use sp_blockchain::Error as ClientError;
use sp_blockchain::{Error as ClientError, HeaderBackend};
use parity_scale_codec::{Encode, Decode};
use finality_grandpa::voter_set::VoterSet;
use finality_grandpa::{Error as GrandpaError};
@@ -47,14 +46,12 @@ pub struct GrandpaJustification<Block: BlockT> {
impl<Block: BlockT> GrandpaJustification<Block> {
/// Create a GRANDPA justification from the given commit. This method
/// assumes the commit is valid and well-formed.
pub(crate) fn from_commit<B, E, RA>(
client: &Client<B, E, Block, RA>,
pub(crate) fn from_commit<C>(
client: &Arc<C>,
round: u64,
commit: Commit<Block>,
) -> Result<GrandpaJustification<Block>, Error> where
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
C: HeaderBackend<Block>,
{
let mut votes_ancestries_hashes = HashSet::new();
let mut votes_ancestries = Vec::new();
@@ -69,7 +66,7 @@ impl<Block: BlockT> GrandpaJustification<Block> {
loop {
if current_hash == commit.target_hash { break; }
match client.header(&BlockId::Hash(current_hash))? {
match client.header(BlockId::Hash(current_hash))? {
Some(current_header) => {
if *current_header.number() <= commit.target_number {
return error();
+75 -60
View File
@@ -56,15 +56,18 @@ use futures::prelude::*;
use futures::StreamExt;
use log::{debug, info};
use futures::channel::mpsc;
use sc_client_api::{BlockchainEvents, CallExecutor, backend::{AuxStore, Backend}, ExecutionStrategy};
use sp_blockchain::{HeaderBackend, Error as ClientError};
use sc_client_api::{
LockImportRun, BlockchainEvents, CallExecutor,
backend::{AuxStore, Backend}, ExecutionStrategy, Finalizer, TransactionFor,
};
use sp_blockchain::{HeaderBackend, Error as ClientError, HeaderMetadata};
use sc_client::Client;
use parity_scale_codec::{Decode, Encode};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero};
use sc_keystore::KeyStorePtr;
use sp_inherents::InherentDataProviders;
use sp_consensus::SelectChain;
use sp_consensus::{SelectChain, BlockImport};
use sp_core::Pair;
use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG};
use serde_json;
@@ -109,6 +112,8 @@ use sp_finality_grandpa::{AuthorityList, AuthorityPair, AuthoritySignature, SetI
// Re-export these two because it's just so damn convenient.
pub use sp_finality_grandpa::{AuthorityId, ScheduledChange};
use sp_api::ProvideRuntimeApi;
use std::marker::PhantomData;
#[cfg(test)]
mod tests;
@@ -245,10 +250,8 @@ pub(crate) trait BlockStatus<Block: BlockT> {
fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error>;
}
impl<B, E, Block: BlockT, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>> where
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
impl<Block: BlockT, Client> BlockStatus<Block> for Arc<Client> where
Client: HeaderBackend<Block>,
NumberFor<Block>: BlockNumberOps,
{
fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error> {
@@ -257,6 +260,29 @@ impl<B, E, Block: BlockT, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>
}
}
/// A trait that includes all the client functionalities grandpa requires.
/// Ideally this would be a trait alias, we're not there yet.
/// tracking issue https://github.com/rust-lang/rust/issues/41517
pub trait ClientForGrandpa<Block, BE>:
LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block>
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>
where
BE: Backend<Block>,
Block: BlockT,
{}
impl<Block, BE, T> ClientForGrandpa<Block, BE> for T
where
BE: Backend<Block>,
Block: BlockT,
T: LockImportRun<Block, BE> + Finalizer<Block, BE> + AuxStore
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block>
+ BlockchainEvents<Block> + ProvideRuntimeApi<Block>
+ BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = sp_consensus::Error>,
{}
/// Something that one can ask to do a block sync request.
pub(crate) trait BlockSyncRequester<Block: BlockT> {
/// Notifies the sync service to try and sync the given block from the given
@@ -348,8 +374,8 @@ impl<H, N> fmt::Display for CommandOrError<H, N> {
}
}
pub struct LinkHalf<B, E, Block: BlockT, RA, SC> {
client: Arc<Client<B, E, Block, RA>>,
pub struct LinkHalf<Block: BlockT, C, SC> {
client: Arc<C>,
select_chain: SC,
persistent_data: PersistentData<Block>,
voter_commands_rx: mpsc::UnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
@@ -390,22 +416,20 @@ impl<B, E, Block: BlockT, RA> GenesisAuthoritySetProvider<Block> for Client<B, E
/// Make block importer and link half necessary to tie the background voter
/// to it.
pub fn block_import<B, E, Block: BlockT, RA, SC>(
client: Arc<Client<B, E, Block, RA>>,
pub fn block_import<BE, Block: BlockT, Client, SC>(
client: Arc<Client>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
) -> Result<(
GrandpaBlockImport<B, E, Block, RA, SC>,
LinkHalf<B, E, Block, RA, SC>
GrandpaBlockImport<BE, Block, Client, SC>,
LinkHalf<Block, Client, SC>,
), ClientError>
where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
SC: SelectChain<Block>,
Client<B, E, Block, RA>: AuxStore,
BE: Backend<Block> + 'static,
Client: ClientForGrandpa<Block, BE> + 'static,
{
let chain_info = client.chain_info();
let chain_info = client.info();
let genesis_hash = chain_info.genesis_hash;
let persistent_data = aux_schema::load_persistent(
@@ -440,10 +464,10 @@ where
))
}
fn global_communication<Block: BlockT, B, E, N, RA>(
fn global_communication<BE, Block: BlockT, C, N>(
set_id: SetId,
voters: &Arc<VoterSet<AuthorityId>>,
client: &Arc<Client<B, E, Block, RA>>,
client: Arc<C>,
network: &NetworkBridge<Block, N>,
keystore: &Option<KeyStorePtr>,
) -> (
@@ -455,10 +479,9 @@ fn global_communication<Block: BlockT, B, E, N, RA>(
Error = CommandOrError<Block::Hash, NumberFor<Block>>,
> + Unpin,
) where
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
BE: Backend<Block> + 'static,
C: ClientForGrandpa<Block, BE> + 'static,
N: NetworkT<Block>,
RA: Send + Sync,
NumberFor<Block>: BlockNumberOps,
{
let is_voter = is_voter(voters, keystore).is_some();
@@ -487,20 +510,18 @@ fn global_communication<Block: BlockT, B, E, N, RA>(
/// Register the finality tracker inherent data provider (which is used by
/// GRANDPA), if not registered already.
fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
fn register_finality_tracker_inherent_data_provider<Block: BlockT, Client>(
client: Arc<Client>,
inherent_data_providers: &InherentDataProviders,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
Client: HeaderBackend<Block> + 'static,
{
if !inherent_data_providers.has_provider(&sp_finality_tracker::INHERENT_IDENTIFIER) {
inherent_data_providers
.register_provider(sp_finality_tracker::InherentDataProvider::new(move || {
#[allow(deprecated)]
{
let info = client.chain_info();
let info = client.info();
telemetry!(CONSENSUS_INFO; "afg.finalized";
"finalized_number" => ?info.finalized_number,
"finalized_hash" => ?info.finalized_hash,
@@ -515,11 +536,11 @@ fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT, RA>(
}
/// Parameters used to run Grandpa.
pub struct GrandpaParams<B, E, Block: BlockT, N, RA, SC, VR, X> {
pub struct GrandpaParams<Block: BlockT, C, N, SC, VR, X> {
/// Configuration for the GRANDPA service.
pub config: Config,
/// A link to the block import worker.
pub link: LinkHalf<B, E, Block, RA, SC>,
pub link: LinkHalf<Block, C, SC>,
/// The Network instance.
pub network: N,
/// The inherent data providers.
@@ -534,20 +555,18 @@ pub struct GrandpaParams<B, E, Block: BlockT, N, RA, SC, VR, X> {
/// Run a GRANDPA voter as a task. Provide configuration and a link to a
/// block import worker that has already been instantiated with `block_import`.
pub fn run_grandpa_voter<B, E, Block: BlockT, N, RA, SC, VR, X>(
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X>,
pub fn run_grandpa_voter<Block: BlockT, BE: 'static, C, N, SC, VR, X>(
grandpa_params: GrandpaParams<Block, C, N, SC, VR, X>,
) -> sp_blockchain::Result<impl Future<Output = ()> + Unpin + Send + 'static> where
Block::Hash: Ord,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
BE: Backend<Block> + 'static,
N: NetworkT<Block> + Send + Sync + Clone + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
VR: VotingRule<Block, C> + Clone + 'static,
NumberFor<Block>: BlockNumberOps,
DigestFor<Block>: Encode,
RA: Send + Sync + 'static,
X: futures::Future<Output=()> + Clone + Send + Unpin + 'static,
Client<B, E, Block, RA>: AuxStore,
C: ClientForGrandpa<Block, BE> + 'static,
{
let GrandpaParams {
mut config,
@@ -629,27 +648,25 @@ pub fn run_grandpa_voter<B, E, Block: BlockT, N, RA, SC, VR, X>(
/// Future that powers the voter.
#[must_use]
struct VoterWork<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> {
struct VoterWork<B, Block: BlockT, C, N: NetworkT<Block>, SC, VR> {
voter: Pin<Box<dyn Future<Output = Result<(), CommandOrError<Block::Hash, NumberFor<Block>>>> + Send>>,
env: Arc<Environment<B, E, Block, N, RA, SC, VR>>,
env: Arc<Environment<B, Block, C, N, SC, VR>>,
voter_commands_rx: mpsc::UnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
network: NetworkBridge<Block, N>,
}
impl<B, E, Block, N, RA, SC, VR> VoterWork<B, E, Block, N, RA, SC, VR>
impl<B, Block, C, N, SC, VR> VoterWork<B, Block, C, N, SC, VR>
where
Block: BlockT,
B: Backend<Block> + 'static,
C: ClientForGrandpa<Block, B> + 'static,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block> + Send + Sync + 'static,
B: Backend<Block> + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
Client<B, E, Block, RA>: AuxStore,
VR: VotingRule<Block, C> + Clone + 'static,
{
fn new(
client: Arc<Client<B, E, Block, RA>>,
client: Arc<C>,
config: Config,
network: NetworkBridge<Block, N>,
select_chain: SC,
@@ -670,6 +687,7 @@ where
authority_set: persistent_data.authority_set.clone(),
consensus_changes: persistent_data.consensus_changes.clone(),
voter_set_state: persistent_data.set_state.clone(),
_phantom: PhantomData,
});
let mut work = VoterWork {
@@ -700,7 +718,7 @@ where
"authority_id" => authority_id.to_string(),
);
let chain_info = self.env.client.chain_info();
let chain_info = self.env.client.info();
telemetry!(CONSENSUS_INFO; "afg.authority_set";
"number" => ?chain_info.finalized_number,
"hash" => ?chain_info.finalized_hash,
@@ -724,7 +742,7 @@ where
let global_comms = global_communication(
self.env.set_id,
&self.env.voters,
&self.env.client,
self.env.client.clone(),
&self.env.network,
&self.env.config.keystore,
);
@@ -789,6 +807,7 @@ where
consensus_changes: self.env.consensus_changes.clone(),
network: self.env.network.clone(),
voting_rule: self.env.voting_rule.clone(),
_phantom: PhantomData,
});
self.rebuild_voter();
@@ -813,17 +832,15 @@ where
}
}
impl<B, E, Block, N, RA, SC, VR> Future for VoterWork<B, E, Block, N, RA, SC, VR>
impl<B, Block, C, N, SC, VR> Future for VoterWork<B, Block, C, N, SC, VR>
where
Block: BlockT,
B: Backend<Block> + 'static,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block> + Send + Sync + 'static,
B: Backend<Block> + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
Client<B, E, Block, RA>: AuxStore,
C: ClientForGrandpa<Block, B> + 'static,
VR: VotingRule<Block, C> + Clone + 'static,
{
type Output = Result<(), Error>;
@@ -868,15 +885,13 @@ where
/// discards all GRANDPA messages (otherwise, we end up banning nodes that send
/// us a `Neighbor` message, since there is no registered gossip validator for
/// the engine id defined in the message.)
pub fn setup_disabled_grandpa<B, E, Block: BlockT, RA, N>(
client: Arc<Client<B, E, Block, RA>>,
pub fn setup_disabled_grandpa<Block: BlockT, Client, N>(
client: Arc<Client>,
inherent_data_providers: &InherentDataProviders,
network: N,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
Client: HeaderBackend<Block> + 'static,
{
register_finality_tracker_inherent_data_provider(
client,
@@ -18,8 +18,7 @@ use std::collections::HashMap;
use std::sync::Arc;
use log::{info, trace, warn};
use parking_lot::RwLock;
use sc_client::Client;
use sc_client_api::{CallExecutor, backend::{AuxStore, Backend, Finalizer, TransactionFor}};
use sc_client_api::backend::{AuxStore, Backend, Finalizer, TransactionFor};
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
use parity_scale_codec::{Encode, Decode};
use sp_consensus::{
@@ -48,17 +47,15 @@ const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes";
/// Create light block importer.
pub fn light_block_import<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
pub fn light_block_import<BE, Block: BlockT, Client>(
client: Arc<Client>,
backend: Arc<BE>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<GrandpaLightBlockImport<B, E, Block, RA>, ClientError>
) -> Result<GrandpaLightBlockImport<BE, Block, Client>, ClientError>
where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: AuxStore,
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
{
let info = client.info();
let import_data = load_aux_import_data(
@@ -79,14 +76,14 @@ pub fn light_block_import<B, E, Block: BlockT, RA>(
/// It is responsible for:
/// - checking GRANDPA justifications;
/// - fetching finality proofs for blocks that are enacting consensus changes.
pub struct GrandpaLightBlockImport<B, E, Block: BlockT, RA> {
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
pub struct GrandpaLightBlockImport<BE, Block: BlockT, Client> {
client: Arc<Client>,
backend: Arc<BE>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
data: Arc<RwLock<LightImportData<Block>>>,
}
impl<B, E, Block: BlockT, RA> Clone for GrandpaLightBlockImport<B, E, Block, RA> {
impl<BE, Block: BlockT, Client> Clone for GrandpaLightBlockImport<BE, Block, Client> {
fn clone(&self) -> Self {
GrandpaLightBlockImport {
client: self.client.clone(),
@@ -111,27 +108,26 @@ struct LightAuthoritySet {
authorities: AuthorityList,
}
impl<B, E, Block: BlockT, RA> GrandpaLightBlockImport<B, E, Block, RA> {
impl<BE, Block: BlockT, Client> GrandpaLightBlockImport<BE, Block, Client> {
/// Create finality proof request builder.
pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder<Block> {
Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _
}
}
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
impl<BE, Block: BlockT, Client> BlockImport<Block>
for GrandpaLightBlockImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
BE: Backend<Block> + 'static,
for<'a> &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
type Transaction = TransactionFor<BE, Block>;
fn import_block(
&mut self,
@@ -151,23 +147,22 @@ impl<B, E, Block: BlockT, RA> BlockImport<Block>
}
}
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
impl<BE, Block: BlockT, Client> FinalityProofImport<Block>
for GrandpaLightBlockImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
BE: Backend<Block> + 'static,
for<'a> &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor<Block>)> {
let mut out = Vec::new();
let chain_info = self.client.chain_info();
let chain_info = (&*self.client).info();
let data = self.data.read();
for (pending_number, pending_hash) in data.consensus_changes.pending_changes() {
@@ -567,7 +562,7 @@ fn on_post_finalization_error(error: ClientError, value_type: &str) -> Consensus
#[cfg(test)]
pub mod tests {
use super::*;
use sp_consensus::ForkChoiceStrategy;
use sp_consensus::{ForkChoiceStrategy, BlockImport};
use sp_finality_grandpa::AuthorityId;
use sp_core::{H256, crypto::Public};
use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryAuxStore;
@@ -575,37 +570,36 @@ pub mod tests {
use crate::tests::TestApi;
use crate::finality_proof::tests::TestJustification;
pub struct NoJustificationsImport<B, E, Block: BlockT, RA>(
pub GrandpaLightBlockImport<B, E, Block, RA>
pub struct NoJustificationsImport<BE, Block: BlockT, Client>(
pub GrandpaLightBlockImport<BE, Block, Client>
);
impl<B, E, Block: BlockT, RA> Clone
for NoJustificationsImport<B, E, Block, RA> where
impl<BE, Block: BlockT, Client> Clone
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
BE: Backend<Block> + 'static,
{
fn clone(&self) -> Self {
NoJustificationsImport(self.0.clone())
}
}
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
impl<BE, Block: BlockT, Client> BlockImport<Block>
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
BE: Backend<Block> + 'static,
for <'a > &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
GrandpaLightBlockImport<BE, Block, Client>:
BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = ConsensusError>
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
type Transaction = TransactionFor<BE, Block>;
fn import_block(
&mut self,
@@ -624,16 +618,15 @@ pub mod tests {
}
}
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
impl<BE, Block: BlockT, Client> FinalityProofImport<Block>
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
BE: Backend<Block> + 'static,
DigestFor<Block>: Encode,
RA: Send + Sync,
for<'a> &'a Client<B, E, Block, RA>:
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<B, Block>>
+ Finalizer<Block, B>
for <'a > &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
@@ -654,19 +647,15 @@ pub mod tests {
}
/// Creates light block import that ignores justifications that came outside of finality proofs.
pub fn light_block_import_without_justifications<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
pub fn light_block_import_without_justifications<BE, Block: BlockT, Client>(
client: Arc<Client>,
backend: Arc<BE>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<NoJustificationsImport<B, E, Block, RA>, ClientError>
) -> Result<NoJustificationsImport<BE, Block, Client>, ClientError>
where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: BlockImport<Block, Error = ConsensusError>
+ Finalizer<Block, B>
+ AuxStore,
BE: Backend<Block> + 'static,
Client: crate::ClientForGrandpa<Block, BE>,
{
light_block_import(client, backend, genesis_authorities_provider, authority_set_provider)
.map(NoJustificationsImport)
@@ -677,6 +666,7 @@ pub mod tests {
justification: Option<Justification>,
) -> ImportResult {
let (client, _backend) = substrate_test_runtime_client::new_light();
let client = Arc::new(client);
let mut import_data = LightImportData {
last_finalized: Default::default(),
authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]),
@@ -696,7 +686,7 @@ pub mod tests {
block.fork_choice = Some(ForkChoiceStrategy::LongestChain);
do_import_block::<_, _, _, TestJustification>(
&client,
&*client,
&mut import_data,
block,
new_cache,
@@ -26,10 +26,9 @@ use finality_grandpa::{
use log::{debug, info, warn};
use sp_consensus::SelectChain;
use sc_client_api::{CallExecutor, backend::{Backend, AuxStore}};
use sc_client::Client;
use sc_client_api::backend::Backend;
use sp_runtime::traits::{NumberFor, Block as BlockT};
use sp_blockchain::HeaderMetadata;
use crate::{
global_communication, CommandOrError, CommunicationIn, Config, environment,
LinkHalf, Error, aux_schema::PersistentData, VoterCommand, VoterSetState,
@@ -38,17 +37,21 @@ use crate::authorities::SharedAuthoritySet;
use crate::communication::{Network as NetworkT, NetworkBridge};
use crate::consensus_changes::SharedConsensusChanges;
use sp_finality_grandpa::AuthorityId;
use std::marker::{PhantomData, Unpin};
struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client<B, E, Block, RA>);
struct ObserverChain<'a, Block: BlockT, Client> {
client: &'a Arc<Client>,
_phantom: PhantomData<Block>,
}
impl<'a, Block: BlockT, B, E, RA> finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for ObserverChain<'a, Block, B, E, RA> where
B: Backend<Block>,
E: CallExecutor<Block>,
impl<'a, Block, Client> finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for ObserverChain<'a, Block, Client> where
Block: BlockT,
Client: HeaderMetadata<Block, Error = sp_blockchain::Error>,
NumberFor<Block>: BlockNumberOps,
{
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
environment::ancestry(&self.0, base, block)
environment::ancestry(&self.client, base, block)
}
fn best_chain_containing(&self, _block: Block::Hash) -> Option<(Block::Hash, NumberFor<Block>)> {
@@ -57,8 +60,8 @@ impl<'a, Block: BlockT, B, E, RA> finality_grandpa::Chain<Block::Hash, NumberFor
}
}
fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
client: &Arc<Client<B, E, Block, RA>>,
fn grandpa_observer<BE, Block: BlockT, Client, S, F>(
client: &Arc<Client>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
voters: &Arc<VoterSet<AuthorityId>>,
@@ -67,13 +70,12 @@ fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
note_round: F,
) -> impl Future<Output=Result<(), CommandOrError<Block::Hash, NumberFor<Block>>>> where
NumberFor<Block>: BlockNumberOps,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync,
S: Stream<
Item = Result<CommunicationIn<Block>, CommandOrError<Block::Hash, NumberFor<Block>>>,
>,
F: Fn(u64),
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
{
let authority_set = authority_set.clone();
let consensus_changes = consensus_changes.clone();
@@ -101,7 +103,7 @@ fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
let validation_result = match finality_grandpa::validate_commit(
&commit,
&voters,
&ObserverChain(&*client),
&ObserverChain { client: &client, _phantom: PhantomData },
) {
Ok(r) => r,
Err(e) => return future::err(e.into()),
@@ -113,7 +115,7 @@ fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
// commit is valid, finalize the block it targets
match environment::finalize_block(
&client,
client.clone(),
&authority_set,
&consensus_changes,
None,
@@ -153,19 +155,17 @@ fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
/// NOTE: this is currently not part of the crate's public API since we don't consider
/// it stable enough to use on a live network.
#[allow(unused)]
pub fn run_grandpa_observer<B, E, Block: BlockT, N, RA, SC>(
pub fn run_grandpa_observer<BE, Block: BlockT, Client, N, SC>(
config: Config,
link: LinkHalf<B, E, Block, RA, SC>,
link: LinkHalf<Block, Client, SC>,
network: N,
on_exit: impl futures::Future<Output=()> + Clone + Send + Unpin + 'static,
) -> sp_blockchain::Result<impl Future<Output = ()> + Unpin + Send + 'static> where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
BE: Backend<Block> + Unpin + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
SC: SelectChain<Block> + 'static,
NumberFor<Block>: BlockNumberOps,
RA: Send + Sync + 'static,
Client<B, E, Block, RA>: AuxStore,
Client: crate::ClientForGrandpa<Block, BE> + 'static,
{
let LinkHalf {
client,
@@ -199,28 +199,27 @@ pub fn run_grandpa_observer<B, E, Block: BlockT, N, RA, SC>(
/// Future that powers the observer.
#[must_use]
struct ObserverWork<B: BlockT, N: NetworkT<B>, E, Backend, RA> {
struct ObserverWork<B: BlockT, BE, Client, N: NetworkT<B>> {
observer: Pin<Box<dyn Future<Output = Result<(), CommandOrError<B::Hash, NumberFor<B>>>> + Send>>,
client: Arc<Client<Backend, E, B, RA>>,
client: Arc<Client>,
network: NetworkBridge<B, N>,
persistent_data: PersistentData<B>,
keystore: Option<sc_keystore::KeyStorePtr>,
voter_commands_rx: mpsc::UnboundedReceiver<VoterCommand<B::Hash, NumberFor<B>>>,
_phantom: PhantomData<BE>,
}
impl<B, N, E, Bk, RA> ObserverWork<B, N, E, Bk, RA>
impl<B, BE, Client, Network> ObserverWork<B, BE, Client, Network>
where
B: BlockT,
N: NetworkT<B>,
BE: Backend<B> + 'static,
Client: crate::ClientForGrandpa<B, BE> + 'static,
Network: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B> + Send + Sync + 'static,
Bk: Backend<B> + 'static,
Client<Bk, E, B, RA>: AuxStore,
{
fn new(
client: Arc<Client<Bk, E, B, RA>>,
network: NetworkBridge<B, N>,
client: Arc<Client>,
network: NetworkBridge<B, Network>,
persistent_data: PersistentData<B>,
keystore: Option<sc_keystore::KeyStorePtr>,
voter_commands_rx: mpsc::UnboundedReceiver<VoterCommand<B::Hash, NumberFor<B>>>,
@@ -235,6 +234,7 @@ where
persistent_data,
keystore,
voter_commands_rx,
_phantom: PhantomData,
};
work.rebuild_observer();
work
@@ -251,12 +251,12 @@ where
let (global_in, _) = global_communication(
set_id,
&voters,
&self.client,
self.client.clone(),
&self.network,
&self.keystore,
);
let last_finalized_number = self.client.chain_info().finalized_number;
let last_finalized_number = self.client.info().finalized_number;
// NOTE: since we are not using `round_communication` we have to
// manually note the round with the gossip validator, otherwise we won't
@@ -324,15 +324,13 @@ where
}
}
impl<B, N, E, Bk, RA> Future for ObserverWork<B, N, E, Bk, RA>
impl<B, BE, C, N> Future for ObserverWork<B, BE, C, N>
where
B: BlockT,
BE: Backend<B> + Unpin + 'static,
C: crate::ClientForGrandpa<B, BE>+ 'static,
N: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B> + Send + Sync + 'static,
Bk: Backend<B> + 'static,
Client<Bk, E, B, RA>: AuxStore,
{
type Output = Result<(), Error>;
@@ -379,6 +377,7 @@ mod tests {
use crate::{aux_schema, communication::tests::{Event, make_test_network}};
use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt};
use sc_network::PeerId;
use sp_blockchain::HeaderBackend as _;
use futures::executor;
@@ -406,7 +405,7 @@ mod tests {
let persistent_data = aux_schema::load_persistent(
&*backend,
client.chain_info().genesis_hash,
client.info().genesis_hash,
0,
|| Ok(vec![]),
).unwrap();
@@ -20,7 +20,7 @@ use super::*;
use environment::HasVoted;
use sc_network_test::{
Block, Hash, TestNetFactory, BlockImportAdapter, Peer,
PeersClient, PassThroughVerifier,
PeersClient, PassThroughVerifier, PeersFullClient,
};
use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder};
use parking_lot::Mutex;
@@ -60,10 +60,8 @@ type PeerData =
Mutex<
Option<
LinkHalf<
substrate_test_runtime_client::Backend,
substrate_test_runtime_client::Executor,
Block,
substrate_test_runtime_client::runtime::RuntimeApi,
PeersFullClient,
LongestChain<substrate_test_runtime_client::Backend, Block>
>
>
@@ -1654,6 +1652,7 @@ fn grandpa_environment_respects_voting_rules() {
voters: Arc::new(authority_set.current_authorities()),
network,
voting_rule,
_phantom: PhantomData,
}
};