Remove requirement on Hash = H256, make Proposer return StorageChanges and Proof (#3860)

* Extend `Proposer` to optionally generate a proof of the proposal

* Something

* Refactor sr-api to not depend on client anymore

* Fix benches

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Apply suggestions from code review

* Introduce new `into_storage_changes` function

* Switch to runtime api for `execute_block` and don't require `H256`
anywhere in the code

* Put the `StorageChanges` into the `Proposal`

* Move the runtime api error to its own trait

* Adds `StorageTransactionCache` to the runtime api

This requires that we add `type NodeBlock = ` to the
`impl_runtime_apis!` macro to work around some bugs in rustc :(

* Remove `type NodeBlock` and switch to a "better" hack

* Start using the transaction cache from the runtime api

* Make it compile

* Move `InMemory` to its own file

* Make all tests work again

* Return block, storage_changes and proof from Blockbuilder::bake()

* Make sure that we use/set `storage_changes` when possible

* Add test

* Fix deadlock

* Remove accidentally added folders

* Introduce `RecordProof` as argument type to be more explicit

* Update client/src/client.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update primitives/state-machine/src/ext.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Integrates review feedback

* Remove `unsafe` usage

* Update client/block-builder/src/lib.rs

Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org>

* Update client/src/call_executor.rs

* Bump versions

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
Bastian Köcher
2020-01-10 10:48:32 +01:00
committed by GitHub
parent 74d6e660c6
commit fd6b29dd2c
140 changed files with 4860 additions and 3339 deletions
@@ -29,7 +29,7 @@ use sp_blockchain::{HeaderBackend, Error as ClientError};
use sc_client_api::{
BlockchainEvents,
backend::{Backend},
backend::{AuxStore, Backend},
Finalizer,
call_executor::CallExecutor,
utils::is_descendent_of,
@@ -41,7 +41,7 @@ use finality_grandpa::{
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet,
};
use sp_core::{Blake2Hasher, H256, Pair};
use sp_core::Pair;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, One, Zero,
@@ -406,13 +406,13 @@ impl<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> Environment<B, E, Bloc
}
}
impl<Block: BlockT<Hash=H256>, B, E, N, RA, SC, VR>
impl<Block: BlockT, B, E, N, RA, SC, VR>
finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + 'static + Send,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
@@ -519,13 +519,13 @@ where
}
pub(crate) fn ancestry<B, Block: BlockT<Hash=H256>, E, RA>(
pub(crate) fn ancestry<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
base: Block::Hash,
block: Block::Hash,
) -> Result<Vec<Block::Hash>, GrandpaError> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
B: Backend<Block>,
E: CallExecutor<Block>,
{
if base == block { return Err(GrandpaError::NotDescendent) }
@@ -550,18 +550,19 @@ pub(crate) fn ancestry<B, Block: BlockT<Hash=H256>, E, RA>(
Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect())
}
impl<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR>
impl<B, E, Block: BlockT, N, RA, SC, VR>
voter::Environment<Block::Hash, NumberFor<Block>>
for Environment<B, E, Block, N, RA, SC, VR>
where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Send + Sync,
N: NetworkT<Block> + 'static + Send,
RA: 'static + Send + Sync,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>>,
NumberFor<Block>: BlockNumberOps,
Client<B, E, Block, RA>: AuxStore,
{
type Timer = Box<dyn Future<Item = (), Error = Self::Error> + Send>;
type Id = AuthorityId;
@@ -940,7 +941,7 @@ 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<Hash=H256>, E, RA>(
pub(crate) fn finalize_block<B, Block: BlockT, E, RA>(
client: &Client<B, E, Block, RA>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -949,8 +950,8 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
number: NumberFor<Block>,
justification_or_commit: JustificationOrCommit<Block>,
) -> Result<(), CommandOrError<Block::Hash, NumberFor<Block>>> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
{
// NOTE: lock must be held through writing to DB to avoid race. this lock
@@ -988,7 +989,7 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
let status = authority_set.apply_standard_changes(
hash,
number,
&is_descendent_of::<_, _, Block::Hash>(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
@@ -1124,8 +1125,8 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
/// Using the given base get the block at the given height on this chain. The
/// target block must be an ancestor of base, therefore `height <= base.height`.
pub(crate) fn canonical_at_height<Block: BlockT<Hash=H256>, C: HeaderBackend<Block>>(
provider: C,
pub(crate) fn canonical_at_height<Block: BlockT, C: HeaderBackend<Block>>(
provider: &C,
base: (Block::Hash, NumberFor<Block>),
base_is_canonical: bool,
height: NumberFor<Block>,
@@ -50,7 +50,7 @@ use sp_runtime::{
Justification, generic::BlockId,
traits::{NumberFor, Block as BlockT, Header as HeaderT, One},
};
use sp_core::{H256, Blake2Hasher, storage::StorageKey};
use sp_core::storage::StorageKey;
use sc_telemetry::{telemetry, CONSENSUS_INFO};
use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
@@ -68,10 +68,10 @@ pub trait AuthoritySetForFinalityProver<Block: BlockT>: Send + Sync {
}
/// Client-based implementation of AuthoritySetForFinalityProver.
impl<B, E, Block: BlockT<Hash=H256>, RA> AuthoritySetForFinalityProver<Block> for Client<B, E, Block, RA>
impl<B, E, Block: BlockT, RA> AuthoritySetForFinalityProver<Block> for Client<B, E, Block, RA>
where
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
@@ -134,13 +134,13 @@ impl<Block: BlockT> AuthoritySetForFinalityChecker<Block> for Arc<dyn FetchCheck
}
/// Finality proof provider for serving network requests.
pub struct FinalityProofProvider<B, Block: BlockT<Hash=H256>> {
pub struct FinalityProofProvider<B, Block: BlockT> {
backend: Arc<B>,
authority_provider: Arc<dyn AuthoritySetForFinalityProver<Block>>,
}
impl<B, Block: BlockT<Hash=H256>> FinalityProofProvider<B, Block>
where B: Backend<Block, Blake2Hasher> + Send + Sync + 'static
impl<B, Block: BlockT> FinalityProofProvider<B, Block>
where B: Backend<Block> + Send + Sync + 'static
{
/// Create new finality proof provider using:
///
@@ -156,9 +156,9 @@ impl<B, Block: BlockT<Hash=H256>> FinalityProofProvider<B, Block>
impl<B, Block> sc_network::FinalityProofProvider<Block> for FinalityProofProvider<B, Block>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
NumberFor<Block>: BlockNumberOps,
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + Send + Sync + 'static,
{
fn prove_finality(
&self,
@@ -252,7 +252,7 @@ pub(crate) fn make_finality_proof_request<H: Encode + Decode>(last_finalized: H,
/// It is assumed that the caller already knows all blocks in the range (begin; end].
///
/// Returns None if there are no finalized blocks unknown to the caller.
pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Block>, J>(
pub(crate) fn prove_finality<Block: BlockT, B: BlockchainBackend<Block>, J>(
blockchain: &B,
authorities_provider: &dyn AuthoritySetForFinalityProver<Block>,
authorities_set_id: u64,
@@ -410,7 +410,7 @@ pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Bloc
///
/// Returns the vector of headers that MUST be validated + imported
/// AND if at least one of those headers is invalid, all other MUST be considered invalid.
pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
pub(crate) fn check_finality_proof<Block: BlockT, B>(
blockchain: &B,
current_set_id: u64,
current_authorities: AuthorityList,
@@ -429,7 +429,7 @@ pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
remote_proof)
}
fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
fn do_check_finality_proof<Block: BlockT, B, J>(
blockchain: &B,
current_set_id: u64,
current_authorities: AuthorityList,
@@ -484,7 +484,7 @@ fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
}
/// Check finality proof for the single block.
fn check_finality_proof_fragment<Block: BlockT<Hash=H256>, B, J>(
fn check_finality_proof_fragment<Block: BlockT, B, J>(
blockchain: &B,
authority_set: AuthoritiesOrEffects<Block::Header>,
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
@@ -569,7 +569,7 @@ pub(crate) trait ProvableJustification<Header: HeaderT>: Encode + Decode {
}
}
impl<Block: BlockT<Hash=H256>> ProvableJustification<Block::Header> for GrandpaJustification<Block>
impl<Block: BlockT> ProvableJustification<Block::Header> for GrandpaJustification<Block>
where
NumberFor<Block>: BlockNumberOps,
{
+36 -26
View File
@@ -22,7 +22,7 @@ use futures::sync::mpsc;
use parking_lot::RwLockWriteGuard;
use sp_blockchain::{HeaderBackend, BlockStatus, well_known_cache_keys};
use sc_client_api::{backend::Backend, CallExecutor, utils::is_descendent_of};
use sc_client_api::{backend::{TransactionFor, Backend}, CallExecutor, utils::is_descendent_of};
use sc_client::Client;
use sp_consensus::{
BlockImport, Error as ConsensusError,
@@ -35,7 +35,6 @@ use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
use sp_runtime::traits::{
Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero,
};
use sp_core::{H256, Blake2Hasher};
use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand};
use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange};
@@ -52,7 +51,7 @@ 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<Hash=H256>, RA, SC> {
pub struct GrandpaBlockImport<B, E, Block: BlockT, RA, SC> {
inner: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
@@ -60,7 +59,7 @@ pub struct GrandpaBlockImport<B, E, Block: BlockT<Hash=H256>, RA, SC> {
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC: Clone> Clone for
impl<B, E, Block: BlockT, RA, SC: Clone> Clone for
GrandpaBlockImport<B, E, Block, RA, SC>
{
fn clone(&self) -> Self {
@@ -74,11 +73,11 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC: Clone> Clone for
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC> JustificationImport<Block>
impl<B, E, Block: BlockT, RA, SC> JustificationImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
SC: SelectChain<Block>,
@@ -201,12 +200,12 @@ 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<Hash=H256>, RA, SC>
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
{
@@ -236,9 +235,11 @@ where
})
}
fn make_authorities_changes<'a>(&'a self, block: &mut BlockImportParams<Block>, hash: Block::Hash)
-> Result<PendingSetChanges<'a, Block>, ConsensusError>
{
fn make_authorities_changes<'a>(
&'a self,
block: &mut BlockImportParams<Block, TransactionFor<B, Block>>,
hash: Block::Hash,
) -> Result<PendingSetChanges<'a, 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.
@@ -285,7 +286,7 @@ where
// returns a function for checking whether a block is a descendent of another
// consistent with querying client directly after importing the block.
let parent_hash = *block.header.parent_hash();
let is_descendent_of = is_descendent_of(&*self.inner, Some((&hash, &parent_hash)));
let is_descendent_of = is_descendent_of(&*self.inner, Some((hash, parent_hash)));
let mut guard = InnerGuard {
guard: Some(self.authority_set.inner().write()),
@@ -379,19 +380,22 @@ where
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
impl<B, E, Block: BlockT, RA, SC> BlockImport<Block>
for GrandpaBlockImport<B, E, Block, RA, SC> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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>>,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -416,12 +420,20 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
match import_result {
Ok(ImportResult::Imported(aux)) => aux,
Ok(r) => {
debug!(target: "afg", "Restoring old authority set after block import result: {:?}", r);
debug!(
target: "afg",
"Restoring old authority set after block import result: {:?}",
r,
);
pending_changes.revert();
return Ok(r);
},
Err(e) => {
debug!(target: "afg", "Restoring old authority set after block import error: {:?}", e);
debug!(
target: "afg",
"Restoring old authority set after block import error: {:?}",
e,
);
pending_changes.revert();
return Err(ConsensusError::ClientImport(e.to_string()).into());
},
@@ -509,9 +521,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
{
impl<B, E, Block: BlockT, RA, SC> GrandpaBlockImport<B, E, Block, RA, SC> {
pub(crate) fn new(
inner: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
@@ -529,12 +539,12 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, SC>
impl<B, E, Block: BlockT, RA, SC>
GrandpaBlockImport<B, E, Block, RA, SC>
where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
@@ -24,7 +24,6 @@ use finality_grandpa::voter_set::VoterSet;
use finality_grandpa::{Error as GrandpaError};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT};
use sp_core::{H256, Blake2Hasher};
use sp_finality_grandpa::AuthorityId;
use crate::{Commit, Error};
@@ -45,7 +44,7 @@ pub struct GrandpaJustification<Block: BlockT> {
votes_ancestries: Vec<Block::Header>,
}
impl<Block: BlockT<Hash=H256>> GrandpaJustification<Block> {
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>(
@@ -53,8 +52,8 @@ impl<Block: BlockT<Hash=H256>> GrandpaJustification<Block> {
round: u64,
commit: Commit<Block>,
) -> Result<GrandpaJustification<Block>, Error> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
{
let mut votes_ancestries_hashes = HashSet::new();
+44 -39
View File
@@ -55,7 +55,7 @@
use futures::prelude::*;
use log::{debug, error, info};
use futures::sync::mpsc;
use sc_client_api::{BlockchainEvents, CallExecutor, backend::Backend, ExecutionStrategy};
use sc_client_api::{BlockchainEvents, CallExecutor, backend::{AuxStore, Backend}, ExecutionStrategy};
use sp_blockchain::{HeaderBackend, Error as ClientError};
use sc_client::Client;
use parity_scale_codec::{Decode, Encode};
@@ -64,7 +64,7 @@ use sp_runtime::traits::{NumberFor, Block as BlockT, DigestFor, Zero};
use sc_keystore::KeyStorePtr;
use sp_inherents::InherentDataProviders;
use sp_consensus::SelectChain;
use sp_core::{H256, Blake2Hasher, Pair};
use sp_core::Pair;
use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG, CONSENSUS_WARN};
use serde_json;
@@ -252,9 +252,9 @@ pub(crate) trait BlockStatus<Block: BlockT> {
fn block_number(&self, hash: Block::Hash) -> Result<Option<NumberFor<Block>>, Error>;
}
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
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,
NumberFor<Block>: BlockNumberOps,
{
@@ -355,7 +355,7 @@ impl<H, N> fmt::Display for CommandOrError<H, N> {
}
}
pub struct LinkHalf<B, E, Block: BlockT<Hash=H256>, RA, SC> {
pub struct LinkHalf<B, E, Block: BlockT, RA, SC> {
client: Arc<Client<B, E, Block, RA>>,
select_chain: SC,
persistent_data: PersistentData<Block>,
@@ -368,10 +368,10 @@ pub trait GenesisAuthoritySetProvider<Block: BlockT> {
fn get(&self) -> Result<AuthorityList, ClientError>;
}
impl<B, E, Block: BlockT<Hash=H256>, RA> GenesisAuthoritySetProvider<Block> for Client<B, E, Block, RA>
impl<B, E, Block: BlockT, RA> GenesisAuthoritySetProvider<Block> for Client<B, E, Block, RA>
where
B: Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
fn get(&self) -> Result<AuthorityList, ClientError> {
@@ -397,7 +397,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> GenesisAuthoritySetProvider<Block> for
/// Make block importer and link half necessary to tie the background voter
/// to it.
pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, SC>(
pub fn block_import<B, E, Block: BlockT, RA, SC>(
client: Arc<Client<B, E, Block, RA>>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
@@ -406,10 +406,11 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, SC>(
LinkHalf<B, E, Block, RA, SC>
), ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
SC: SelectChain<Block>,
Client<B, E, Block, RA>: AuxStore,
{
let chain_info = client.chain_info();
let genesis_hash = chain_info.genesis_hash;
@@ -446,7 +447,7 @@ where
))
}
fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
fn global_communication<Block: BlockT, B, E, N, RA>(
set_id: SetId,
voters: &Arc<VoterSet<AuthorityId>>,
client: &Arc<Client<B, E, Block, RA>>,
@@ -454,16 +455,16 @@ fn global_communication<Block: BlockT<Hash=H256>, B, E, N, RA>(
keystore: &Option<KeyStorePtr>,
) -> (
impl Stream<
Item = CommunicationInH<Block, H256>,
Error = CommandOrError<H256, NumberFor<Block>>,
Item = CommunicationInH<Block, Block::Hash>,
Error = CommandOrError<Block::Hash, NumberFor<Block>>,
>,
impl Sink<
SinkItem = CommunicationOutH<Block, H256>,
SinkError = CommandOrError<H256, NumberFor<Block>>,
SinkItem = CommunicationOutH<Block, Block::Hash>,
SinkError = CommandOrError<Block::Hash, NumberFor<Block>>,
>,
) where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
N: NetworkT<Block>,
RA: Send + Sync,
NumberFor<Block>: BlockNumberOps,
@@ -494,12 +495,12 @@ fn global_communication<Block: BlockT<Hash=H256>, 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<Hash=H256>, RA>(
fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
inherent_data_providers: &InherentDataProviders,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
{
if !inherent_data_providers.has_provider(&sp_finality_tracker::INHERENT_IDENTIFIER) {
@@ -522,7 +523,7 @@ fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT<Hash=H25
}
/// Parameters used to run Grandpa.
pub struct GrandpaParams<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp> {
pub struct GrandpaParams<B, E, Block: BlockT, N, RA, SC, VR, X, Sp> {
/// Configuration for the GRANDPA service.
pub config: Config,
/// A link to the block import worker.
@@ -543,12 +544,12 @@ pub struct GrandpaParams<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp> {
/// 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<Hash=H256>, N, RA, SC, VR, X, Sp>(
pub fn run_grandpa_voter<B, E, Block: BlockT, N, RA, SC, VR, X, Sp>(
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X, Sp>,
) -> sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
Block::Hash: Ord,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Sync + Clone + 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
@@ -556,6 +557,7 @@ pub fn run_grandpa_voter<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
DigestFor<Block>: Encode,
RA: Send + Sync + 'static,
X: futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
Client<B, E, Block, RA>: AuxStore,
Sp: futures03::task::Spawn + 'static,
{
let GrandpaParams {
@@ -650,14 +652,15 @@ struct VoterWork<B, E, Block: BlockT, N: NetworkT<Block>, RA, SC, VR> {
impl<B, E, Block, N, RA, SC, VR> VoterWork<B, E, Block, N, RA, SC, VR>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block, Blake2Hasher> + 'static,
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,
{
fn new(
client: Arc<Client<B, E, Block, RA>>,
@@ -825,14 +828,15 @@ where
impl<B, E, Block, N, RA, SC, VR> Future for VoterWork<B, E, Block, N, RA, SC, VR>
where
Block: BlockT<Hash=H256>,
Block: BlockT,
N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block, Blake2Hasher> + 'static,
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,
{
type Item = ();
type Error = Error;
@@ -877,12 +881,12 @@ where
}
#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")]
pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
pub fn run_grandpa<B, E, Block: BlockT, N, RA, SC, VR, X, Sp>(
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X, Sp>,
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
) -> sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
Block::Hash: Ord,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Sync + Clone + 'static,
SC: SelectChain<Block> + 'static,
NumberFor<Block>: BlockNumberOps,
@@ -890,6 +894,7 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
RA: Send + Sync + 'static,
VR: VotingRule<Block, Client<B, E, Block, RA>> + Clone + 'static,
X: futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
Client<B, E, Block, RA>: AuxStore,
Sp: futures03::task::Spawn + 'static,
{
run_grandpa_voter(grandpa_params)
@@ -901,13 +906,13 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X, Sp>(
/// 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<Hash=H256>, RA, N>(
pub fn setup_disabled_grandpa<B, E, Block: BlockT, RA, N>(
client: Arc<Client<B, E, Block, RA>>,
inherent_data_providers: &InherentDataProviders,
network: N,
) -> Result<(), sp_consensus::Error> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
RA: Send + Sync + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
{
@@ -19,7 +19,7 @@ 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}};
use sc_client_api::{CallExecutor, 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::{
@@ -32,7 +32,6 @@ use sp_runtime::Justification;
use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor};
use sp_finality_grandpa::{self, AuthorityList};
use sp_runtime::generic::BlockId;
use sp_core::{H256, Blake2Hasher};
use crate::GenesisAuthoritySetProvider;
use crate::aux_schema::load_decode;
@@ -49,16 +48,17 @@ 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<Hash=H256>, RA>(
pub fn light_block_import<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<GrandpaLightBlockImport<B, E, Block, RA>, ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: AuxStore,
{
let info = client.info();
let import_data = load_aux_import_data(
@@ -79,14 +79,14 @@ pub fn light_block_import<B, E, Block: BlockT<Hash=H256>, 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<Hash=H256>, RA> {
pub struct GrandpaLightBlockImport<B, E, Block: BlockT, RA> {
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
data: Arc<RwLock<LightImportData<Block>>>,
}
impl<B, E, Block: BlockT<Hash=H256>, RA> Clone for GrandpaLightBlockImport<B, E, Block, RA> {
impl<B, E, Block: BlockT, RA> Clone for GrandpaLightBlockImport<B, E, Block, RA> {
fn clone(&self) -> Self {
GrandpaLightBlockImport {
client: self.client.clone(),
@@ -98,7 +98,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> Clone for GrandpaLightBlockImport<B, E,
}
/// Mutable data of light block importer.
struct LightImportData<Block: BlockT<Hash=H256>> {
struct LightImportData<Block: BlockT> {
last_finalized: Block::Hash,
authority_set: LightAuthoritySet,
consensus_changes: ConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -111,26 +111,31 @@ struct LightAuthoritySet {
authorities: AuthorityList,
}
impl<B, E, Block: BlockT<Hash=H256>, RA> GrandpaLightBlockImport<B, E, Block, RA> {
impl<B, E, Block: BlockT, RA> GrandpaLightBlockImport<B, E, Block, RA> {
/// 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<Hash=H256>, RA> BlockImport<Block>
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
block: BlockImportParams<Block>,
block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
do_import_block::<_, _, _, GrandpaJustification<Block>>(
@@ -146,13 +151,17 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> BlockImport<Block>
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for GrandpaLightBlockImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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>
+ AuxStore,
{
type Error = ConsensusError;
@@ -162,7 +171,9 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
let data = self.data.read();
for (pending_number, pending_hash) in data.consensus_changes.pending_changes() {
if *pending_number > chain_info.finalized_number && *pending_number <= chain_info.best_number {
if *pending_number > chain_info.finalized_number
&& *pending_number <= chain_info.best_number
{
out.push((pending_hash.clone(), *pending_number));
}
}
@@ -216,9 +227,9 @@ impl LightAuthoritySet {
}
}
struct GrandpaFinalityProofRequestBuilder<B: BlockT<Hash=H256>>(Arc<RwLock<LightImportData<B>>>);
struct GrandpaFinalityProofRequestBuilder<B: BlockT>(Arc<RwLock<LightImportData<B>>>);
impl<B: BlockT<Hash=H256>> FinalityProofRequestBuilder<B> for GrandpaFinalityProofRequestBuilder<B> {
impl<B: BlockT> FinalityProofRequestBuilder<B> for GrandpaFinalityProofRequestBuilder<B> {
fn build_request_data(&mut self, _hash: &B::Hash) -> Vec<u8> {
let data = self.0.read();
make_finality_proof_request(
@@ -229,19 +240,19 @@ impl<B: BlockT<Hash=H256>> FinalityProofRequestBuilder<B> for GrandpaFinalityPro
}
/// Try to import new block.
fn do_import_block<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_block<B, C, Block: BlockT, J>(
mut client: C,
data: &mut LightImportData<Block>,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, TransactionFor<B, Block>>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ BlockImport<Block>
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
J: ProvableJustification<Block::Header>,
@@ -288,7 +299,7 @@ fn do_import_block<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Try to import finality proof.
fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_finality_proof<B, C, Block: BlockT, J>(
client: C,
backend: Arc<B>,
authority_set_provider: &dyn AuthoritySetForFinalityChecker<Block>,
@@ -301,10 +312,10 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ BlockImport<Block>
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
DigestFor<Block>: Encode,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
@@ -322,15 +333,27 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
// try to import all new headers
let block_origin = BlockOrigin::NetworkBroadcast;
for header_to_import in finality_effects.headers_to_import {
let (block_to_import, new_authorities) = verifier.verify(block_origin, header_to_import, None, None)
.map_err(|e| ConsensusError::ClientImport(e))?;
assert!(block_to_import.justification.is_none(), "We have passed None as justification to verifier.verify");
let (block_to_import, new_authorities) = verifier.verify(
block_origin,
header_to_import,
None,
None,
).map_err(|e| ConsensusError::ClientImport(e))?;
assert!(
block_to_import.justification.is_none(),
"We have passed None as justification to verifier.verify",
);
let mut cache = HashMap::new();
if let Some(authorities) = new_authorities {
cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode());
}
do_import_block::<_, _, _, J>(client.clone(), data, block_to_import, cache)?;
do_import_block::<_, _, _, J>(
client.clone(),
data,
block_to_import.convert_transaction(),
cache,
)?;
}
// try to import latest justification
@@ -356,7 +379,7 @@ fn do_import_finality_proof<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Try to import justification.
fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
fn do_import_justification<B, C, Block: BlockT, J>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
@@ -366,9 +389,9 @@ fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
{
@@ -427,7 +450,7 @@ fn do_import_justification<B, C, Block: BlockT<Hash=H256>, J>(
}
/// Finalize the block.
fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
fn do_finalize_block<B, C, Block: BlockT>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
@@ -437,9 +460,9 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, Blake2Hasher, B>
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block, Blake2Hasher> + 'static,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
{
// finalize the block
@@ -450,7 +473,10 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
// forget obsoleted consensus changes
let consensus_finalization_res = data.consensus_changes
.finalize((number, hash), |at_height| canonical_at_height(client.clone(), (hash, number), true, at_height));
.finalize(
(number, hash),
|at_height| canonical_at_height(&client, (hash, number), true, at_height)
);
match consensus_finalization_res {
Ok((true, _)) => require_insert_aux(
&client,
@@ -470,13 +496,14 @@ fn do_finalize_block<B, C, Block: BlockT<Hash=H256>>(
}
/// Load light import aux data from the store.
fn load_aux_import_data<B, Block: BlockT<Hash=H256>>(
fn load_aux_import_data<B, Block>(
last_finalized: Block::Hash,
aux_store: &B,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
) -> Result<LightImportData<Block>, ClientError>
where
B: AuxStore,
Block: BlockT,
{
let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? {
Some(authority_set) => authority_set,
@@ -548,15 +575,15 @@ pub mod tests {
use crate::tests::TestApi;
use crate::finality_proof::tests::TestJustification;
pub struct NoJustificationsImport<B, E, Block: BlockT<Hash=H256>, RA>(
pub struct NoJustificationsImport<B, E, Block: BlockT, RA>(
pub GrandpaLightBlockImport<B, E, Block, RA>
);
impl<B, E, Block: BlockT<Hash=H256>, RA> Clone
impl<B, E, Block: BlockT, RA> Clone
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
DigestFor<Block>: Encode,
RA: Send + Sync,
{
@@ -565,19 +592,24 @@ pub mod tests {
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockImport<Block>
impl<B, E, Block: BlockT, RA> BlockImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<B, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
block.justification.take();
@@ -592,13 +624,17 @@ pub mod tests {
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA> FinalityProofImport<Block>
impl<B, E, Block: BlockT, RA> FinalityProofImport<Block>
for NoJustificationsImport<B, E, Block, RA> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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>
+ AuxStore,
{
type Error = ConsensusError;
@@ -618,16 +654,19 @@ 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<Hash=H256>, RA>(
pub fn light_block_import_without_justifications<B, E, Block: BlockT, RA>(
client: Arc<Client<B, E, Block, RA>>,
backend: Arc<B>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<NoJustificationsImport<B, E, Block, RA>, ClientError>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
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,
{
light_block_import(client, backend, genesis_authorities_provider, authority_set_provider)
.map(NoJustificationsImport)
@@ -655,6 +694,7 @@ pub mod tests {
justification,
post_digests: Vec::new(),
body: None,
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -25,10 +25,9 @@ use finality_grandpa::{
use log::{debug, info, warn};
use sp_consensus::SelectChain;
use sc_client_api::{CallExecutor, backend::Backend};
use sc_client_api::{CallExecutor, backend::{Backend, AuxStore}};
use sc_client::Client;
use sp_runtime::traits::{NumberFor, Block as BlockT};
use sp_core::{H256, Blake2Hasher};
use crate::{
global_communication, CommandOrError, CommunicationIn, Config, environment,
@@ -41,10 +40,10 @@ use sp_finality_grandpa::AuthorityId;
struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client<B, E, Block, RA>);
impl<'a, Block: BlockT<Hash=H256>, B, E, RA> finality_grandpa::Chain<Block::Hash, NumberFor<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, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
B: Backend<Block>,
E: CallExecutor<Block>,
NumberFor<Block>: BlockNumberOps,
{
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
@@ -57,7 +56,7 @@ impl<'a, Block: BlockT<Hash=H256>, B, E, RA> finality_grandpa::Chain<Block::Hash
}
}
fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
fn grandpa_observer<B, E, Block: BlockT, RA, S, F>(
client: &Arc<Client<B, E, Block, RA>>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
@@ -65,10 +64,10 @@ fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
last_finalized_number: NumberFor<Block>,
commits: S,
note_round: F,
) -> impl Future<Item=(), Error=CommandOrError<H256, NumberFor<Block>>> where
) -> impl Future<Item=(), Error=CommandOrError<Block::Hash, NumberFor<Block>>> where
NumberFor<Block>: BlockNumberOps,
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
S: Stream<
Item = CommunicationIn<Block>,
@@ -151,20 +150,21 @@ fn grandpa_observer<B, E, Block: BlockT<Hash=H256>, RA, S, F>(
/// listening for and validating GRANDPA commits instead of following the full
/// protocol. Provide configuration and a link to a block import worker that has
/// already been instantiated with `block_import`.
pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA, SC, Sp>(
pub fn run_grandpa_observer<B, E, Block: BlockT, N, RA, SC, Sp>(
config: Config,
link: LinkHalf<B, E, Block, RA, SC>,
network: N,
on_exit: impl futures03::Future<Output=()> + Clone + Send + Unpin + 'static,
executor: Sp,
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
) -> sp_blockchain::Result<impl Future<Item=(), Error=()> + Send + 'static> where
B: Backend<Block> + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
N: NetworkT<Block> + Send + Clone + 'static,
SC: SelectChain<Block> + 'static,
NumberFor<Block>: BlockNumberOps,
RA: Send + Sync + 'static,
Sp: futures03::task::Spawn + 'static,
Client<B, E, Block, RA>: AuxStore,
{
let LinkHalf {
client,
@@ -202,7 +202,7 @@ pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA, SC, Sp>(
/// Future that powers the observer.
#[must_use]
struct ObserverWork<B: BlockT<Hash=H256>, N: NetworkT<B>, E, Backend, RA> {
struct ObserverWork<B: BlockT, N: NetworkT<B>, E, Backend, RA> {
observer: Box<dyn Future<Item = (), Error = CommandOrError<B::Hash, NumberFor<B>>> + Send>,
client: Arc<Client<Backend, E, B, RA>>,
network: NetworkBridge<B, N>,
@@ -213,12 +213,13 @@ struct ObserverWork<B: BlockT<Hash=H256>, N: NetworkT<B>, E, Backend, RA> {
impl<B, N, E, Bk, RA> ObserverWork<B, N, E, Bk, RA>
where
B: BlockT<Hash=H256>,
B: BlockT,
N: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B, Blake2Hasher> + Send + Sync + 'static,
Bk: Backend<B, Blake2Hasher> + 'static,
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>>,
@@ -328,12 +329,13 @@ where
impl<B, N, E, Bk, RA> Future for ObserverWork<B, N, E, Bk, RA>
where
B: BlockT<Hash=H256>,
B: BlockT,
N: NetworkT<B>,
NumberFor<B>: BlockNumberOps,
RA: 'static + Send + Sync,
E: CallExecutor<B, Blake2Hasher> + Send + Sync + 'static,
Bk: Backend<B, Blake2Hasher> + 'static,
E: CallExecutor<B> + Send + Sync + 'static,
Bk: Backend<B> + 'static,
Client<Bk, E, B, RA>: AuxStore,
{
type Item = ();
type Error = Error;
+93 -38
View File
@@ -18,8 +18,10 @@
use super::*;
use environment::HasVoted;
use sc_network_test::{Block, DummySpecialization, Hash, TestNetFactory, Peer, PeersClient};
use sc_network_test::{PassThroughVerifier};
use sc_network_test::{
Block, DummySpecialization, Hash, TestNetFactory, BlockImportAdapter, Peer,
PeersClient, PassThroughVerifier,
};
use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder};
use parking_lot::Mutex;
use futures_timer::Delay;
@@ -27,23 +29,28 @@ use futures03::{StreamExt as _, TryStreamExt as _};
use tokio::runtime::current_thread;
use sp_keyring::Ed25519Keyring;
use sc_client::LongestChain;
use sc_client_api::backend::TransactionFor;
use sp_blockchain::Result;
use sp_api::{Core, RuntimeVersion, ApiExt, StorageProof};
use substrate_test_runtime_client::{self, runtime::BlockNumber};
use sp_consensus::{BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult};
use sp_consensus::import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport};
use sp_api::{ApiRef, ApiErrorExt, Core, RuntimeVersion, ApiExt, StorageProof, ProvideRuntimeApi};
use substrate_test_runtime_client::runtime::BlockNumber;
use sp_consensus::{
BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport,
import_queue::{BoxJustificationImport, BoxFinalityProofImport},
};
use std::collections::{HashMap, HashSet};
use std::result;
use parity_scale_codec::Decode;
use sp_runtime::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT};
use sp_runtime::traits::{Header as HeaderT, HasherFor};
use sp_runtime::generic::{BlockId, DigestItem};
use sp_core::{NativeOrEncoded, ExecutionContext, crypto::Public};
use sp_core::{H256, NativeOrEncoded, ExecutionContext, crypto::Public};
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi};
use sp_state_machine::{backend::InMemory, prove_read, read_proof_check};
use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check};
use std::{pin::Pin, task};
use authorities::AuthoritySet;
use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker};
use finality_proof::{
FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker,
};
use consensus_changes::ConsensusChanges;
type PeerData =
@@ -108,9 +115,9 @@ impl TestNetFactory for GrandpaTestNet {
PassThroughVerifier(false) // use non-instant finality.
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -125,8 +132,13 @@ impl TestNetFactory for GrandpaTestNet {
LongestChain::new(backend.clone()),
).expect("Could not create block import for fresh peer.");
let justification_import = Box::new(import.clone());
let block_import = Box::new(import);
(block_import, Some(justification_import), None, None, Mutex::new(Some(link)))
(
BlockImportAdapter::new_full(import),
Some(justification_import),
None,
None,
Mutex::new(Some(link)),
)
},
PeersClient::Light(ref client, ref backend) => {
use crate::light_import::tests::light_block_import_without_justifications;
@@ -142,8 +154,13 @@ impl TestNetFactory for GrandpaTestNet {
).expect("Could not create block import for fresh peer.");
let finality_proof_req_builder = import.0.create_finality_proof_request_builder();
let proof_import = Box::new(import.clone());
let block_import = Box::new(import);
(block_import, None, Some(proof_import), Some(finality_proof_req_builder), Mutex::new(None))
(
BlockImportAdapter::new_light(import),
None,
Some(proof_import),
Some(finality_proof_req_builder),
Mutex::new(None),
)
},
}
}
@@ -202,7 +219,7 @@ pub(crate) struct RuntimeApi {
inner: TestApi,
}
impl ProvideRuntimeApi for TestApi {
impl ProvideRuntimeApi<Block> for TestApi {
type Api = RuntimeApi;
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
@@ -242,8 +259,14 @@ impl Core<Block> for RuntimeApi {
}
}
impl ApiExt<Block> for RuntimeApi {
impl ApiErrorExt for RuntimeApi {
type Error = sp_blockchain::Error;
}
impl ApiExt<Block> for RuntimeApi {
type StateBackend = <
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
>::State;
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
&self,
@@ -263,6 +286,19 @@ impl ApiExt<Block> for RuntimeApi {
fn extract_proof(&mut self) -> Option<StorageProof> {
unimplemented!("Not required for testing!")
}
fn into_storage_changes<
T: sp_api::ChangesTrieStorage<sp_api::HasherFor<Block>, sp_api::NumberFor<Block>>
>(
&self,
_: &Self::StateBackend,
_: Option<&T>,
_: <Block as sp_api::BlockT>::Hash,
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
where Self: Sized
{
unimplemented!("Not required for testing!")
}
}
impl GrandpaApi<Block> for RuntimeApi {
@@ -290,7 +326,7 @@ impl AuthoritySetForFinalityProver<Block> for TestApi {
fn prove_authorities(&self, block: &BlockId<Block>) -> Result<StorageProof> {
let authorities = self.authorities(block)?;
let backend = <InMemory<Blake2Hasher>>::from(vec![
let backend = <InMemoryBackend<HasherFor<Block>>>::from(vec![
(None, vec![(b"authorities".to_vec(), Some(authorities.encode()))])
]);
let proof = prove_read(backend, vec![b"authorities"])
@@ -306,7 +342,7 @@ impl AuthoritySetForFinalityChecker<Block> for TestApi {
header: <Block as BlockT>::Header,
proof: StorageProof,
) -> Result<AuthorityList> {
let results = read_proof_check::<Blake2Hasher, _>(
let results = read_proof_check::<HasherFor<Block>, _>(
*header.state_root(), proof, vec![b"authorities"]
)
.expect("failure checking read proof for authorities");
@@ -629,7 +665,7 @@ fn transition_3_voters_twice_1_full_observer() {
14 => {
// generate transition at block 15, applied at 20.
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 4,
@@ -643,7 +679,7 @@ fn transition_3_voters_twice_1_full_observer() {
// at block 21 we do another transition, but this time instant.
// add more until we have 30.
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(&peers_c),
delay: 0,
@@ -808,7 +844,7 @@ fn sync_justifications_on_change_blocks() {
// at block 21 we do add a transition which is instant
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -870,7 +906,7 @@ fn finalizes_multiple_pending_changes_in_order() {
// at block 21 we do add a transition which is instant
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -883,7 +919,7 @@ fn finalizes_multiple_pending_changes_in_order() {
// at block 26 we add another which is enacted at block 30
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_c),
delay: 4,
@@ -927,7 +963,7 @@ fn force_change_to_new_set() {
let net = Arc::new(Mutex::new(net));
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
// add a forced transition at block 12.
add_forced_change(&mut block, 0, ScheduledChange {
@@ -973,11 +1009,15 @@ fn allows_reimporting_change_blocks() {
let mut net = GrandpaTestNet::new(api.clone(), 3);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(
client.clone(),
);
let full_client = client.as_full().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let mut block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 0,
@@ -991,6 +1031,7 @@ fn allows_reimporting_change_blocks() {
justification: None,
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -1026,11 +1067,15 @@ fn test_bad_justification() {
let mut net = GrandpaTestNet::new(api.clone(), 3);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(
client.clone(),
);
let full_client = client.as_full().expect("only full clients are used in test");
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let mut block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let mut block = builder.build().unwrap().block;
add_scheduled_change(&mut block, ScheduledChange {
next_authorities: make_ids(peers_b),
@@ -1045,6 +1090,7 @@ fn test_bad_justification() {
justification: Some(Vec::new()),
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -1136,7 +1182,10 @@ fn voter_persists_its_votes() {
Ok(Async::NotReady) => {}
Ok(Async::Ready(Some(()))) => {
let (_block_import, _, _, _, link) =
self.net.lock().make_block_import(self.client.clone());
self.net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(self.client.clone());
let link = link.lock().take().unwrap();
let grandpa_params = GrandpaParams {
@@ -1209,7 +1258,10 @@ fn voter_persists_its_votes() {
};
let set_state = {
let (_, _, _, _, link) = net.lock().make_block_import(client);
let (_, _, _, _, link) = net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(client);
let LinkHalf { persistent_data, .. } = link.lock().take().unwrap();
let PersistentData { set_state, .. } = persistent_data;
set_state
@@ -1439,7 +1491,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
// best is #1
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
// add a forced transition at block 5.
let mut block = builder.bake().unwrap();
let mut block = builder.build().unwrap().block;
if FORCE_CHANGE {
add_forced_change(&mut block, 0, ScheduledChange {
next_authorities: voters.clone(),
@@ -1728,11 +1780,13 @@ fn imports_justification_for_regular_blocks_on_import() {
let mut net = GrandpaTestNet::new(api.clone(), 1);
let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone());
let (mut block_import, ..) = net.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(client.clone());
let full_client = client.as_full().expect("only full clients are used in test");
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();
let block = builder.bake().unwrap();
let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap();
let block = builder.build().unwrap().block;
let block_hash = block.hash();
@@ -1776,6 +1830,7 @@ fn imports_justification_for_regular_blocks_on_import() {
justification: Some(justification.encode()),
post_digests: Vec::new(),
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,