Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

babe, aura, pow: only call check_inherents if authoring version is compatible #6862

Merged
10 commits merged into from
Aug 17, 2020
6 changes: 4 additions & 2 deletions bin/node-template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
grandpa_block_import.clone(), client.clone(),
);

let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>(
let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
sc_consensus_aura::slot_duration(&*client)?,
aura_block_import,
Some(Box::new(grandpa_block_import.clone())),
Expand All @@ -63,6 +63,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
inherent_data_providers.clone(),
&task_manager.spawn_handle(),
config.prometheus_registry(),
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
)?;

Ok(sc_service::PartialComponents {
Expand Down Expand Up @@ -240,7 +241,7 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
let finality_proof_request_builder =
finality_proof_import.create_finality_proof_request_builder();

let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>(
let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
sc_consensus_aura::slot_duration(&*client)?,
grandpa_block_import,
None,
Expand All @@ -249,6 +250,7 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
InherentDataProviders::new(),
&task_manager.spawn_handle(),
config.prometheus_registry(),
sp_consensus::NeverCanAuthor,
)?;

let finality_proof_provider =
Expand Down
2 changes: 2 additions & 0 deletions bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
inherent_data_providers.clone(),
&task_manager.spawn_handle(),
config.prometheus_registry(),
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
)?;

let import_setup = (block_import, grandpa_link, babe_link);
Expand Down Expand Up @@ -385,6 +386,7 @@ pub fn new_light_base(config: Configuration) -> Result<(
inherent_data_providers.clone(),
&task_manager.spawn_handle(),
config.prometheus_registry(),
sp_consensus::NeverCanAuthor,
)?;

let finality_proof_provider =
Expand Down
36 changes: 27 additions & 9 deletions client/consensus/aura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,26 +492,39 @@ fn check_header<C, B: BlockT, P: Pair>(
}

/// A verifier for Aura blocks.
pub struct AuraVerifier<C, P> {
pub struct AuraVerifier<C, P, CAW> {
client: Arc<C>,
phantom: PhantomData<P>,
inherent_data_providers: sp_inherents::InherentDataProviders,
can_author_with: CAW,
}

impl<C, P> AuraVerifier<C, P>
where P: Send + Sync + 'static
impl<C, P, CAW> AuraVerifier<C, P, CAW> where
P: Send + Sync + 'static,
CAW: Send + Sync + 'static,
{
fn check_inherents<B: BlockT>(
&self,
block: B,
block_id: BlockId<B>,
inherent_data: InherentData,
timestamp_now: u64,
) -> Result<(), Error<B>>
where C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
) -> Result<(), Error<B>> where
C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
CAW: CanAuthorWith<B>,
{
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;

if let Err(e) = self.can_author_with.can_author_with(&block_id) {
debug!(
target: "aura",
"Skipping `check_inherents` as authoring version is not compatible: {}",
e,
);

return Ok(())
}

let inherent_res = self.client.runtime_api().check_inherents(
&block_id,
block,
Expand Down Expand Up @@ -553,7 +566,7 @@ impl<C, P> AuraVerifier<C, P>
}

#[forbid(deprecated)]
impl<B: BlockT, C, P> Verifier<B> for AuraVerifier<C, P> where
impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
C: ProvideRuntimeApi<B> +
Send +
Sync +
Expand All @@ -565,6 +578,7 @@ impl<B: BlockT, C, P> Verifier<B> for AuraVerifier<C, P> where
P: Pair + Send + Sync + 'static,
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static,
P::Signature: Encode + Decode,
CAW: CanAuthorWith<B> + Send + Sync + 'static,
{
fn verify(
&mut self,
Expand Down Expand Up @@ -812,7 +826,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
}

/// Start an import queue for the Aura consensus algorithm.
pub fn import_queue<B, I, C, P, S>(
pub fn import_queue<B, I, C, P, S, CAW>(
slot_duration: SlotDuration,
block_import: I,
justification_import: Option<BoxJustificationImport<B>>,
Expand All @@ -821,6 +835,7 @@ pub fn import_queue<B, I, C, P, S>(
inherent_data_providers: InherentDataProviders,
spawner: &S,
registry: Option<&Registry>,
can_author_with: CAW,
) -> Result<DefaultImportQueue<B, C>, sp_consensus::Error> where
B: BlockT,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
Expand All @@ -831,6 +846,7 @@ pub fn import_queue<B, I, C, P, S>(
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
P::Signature: Encode + Decode,
S: sp_core::traits::SpawnNamed,
CAW: CanAuthorWith<B> + Send + Sync + 'static,
{
register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?;
initialize_authorities_cache(&*client)?;
Expand All @@ -839,6 +855,7 @@ pub fn import_queue<B, I, C, P, S>(
client,
inherent_data_providers,
phantom: PhantomData,
can_author_with,
};

Ok(BasicQueue::new(
Expand All @@ -854,7 +871,7 @@ pub fn import_queue<B, I, C, P, S>(
#[cfg(test)]
mod tests {
use super::*;
use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof};
use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor};
use sc_network_test::{Block as TestBlock, *};
use sp_runtime::traits::{Block as BlockT, DigestFor};
use sc_network::config::ProtocolConfig;
Expand Down Expand Up @@ -924,7 +941,7 @@ mod tests {
}

impl TestNetFactory for AuraTestNet {
type Verifier = AuraVerifier<PeersFullClient, AuthorityPair>;
type Verifier = AuraVerifier<PeersFullClient, AuthorityPair, AlwaysCanAuthor>;
type PeerData = ();

/// Create new test network with peers and given config.
Expand All @@ -951,6 +968,7 @@ mod tests {
client,
inherent_data_providers,
phantom: Default::default(),
can_author_with: AlwaysCanAuthor,
}
},
PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"),
Expand Down
25 changes: 21 additions & 4 deletions client/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,29 +787,41 @@ impl<Block: BlockT> BabeLink<Block> {
}

/// A verifier for Babe blocks.
pub struct BabeVerifier<Block: BlockT, Client, SelectChain> {
pub struct BabeVerifier<Block: BlockT, Client, SelectChain, CAW> {
client: Arc<Client>,
select_chain: SelectChain,
inherent_data_providers: sp_inherents::InherentDataProviders,
config: Config,
epoch_changes: SharedEpochChanges<Block, Epoch>,
time_source: TimeSource,
can_author_with: CAW,
}

impl<Block, Client, SelectChain> BabeVerifier<Block, Client, SelectChain>
impl<Block, Client, SelectChain, CAW> BabeVerifier<Block, Client, SelectChain, CAW>
where
Block: BlockT,
Client: AuxStore + HeaderBackend<Block> + HeaderMetadata<Block> + ProvideRuntimeApi<Block>,
Client::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
+ BabeApi<Block, Error = sp_blockchain::Error>,
SelectChain: sp_consensus::SelectChain<Block>,
CAW: CanAuthorWith<Block>,
{
fn check_inherents(
&self,
block: Block,
block_id: BlockId<Block>,
inherent_data: InherentData,
) -> Result<(), Error<Block>> {
if let Err(e) = self.can_author_with.can_author_with(&block_id) {
debug!(
target: "babe",
"Skipping `check_inherents` as authoring version is not compatible: {}",
e,
);

return Ok(())
}

let inherent_res = self.client.runtime_api().check_inherents(
&block_id,
block,
Expand Down Expand Up @@ -908,13 +920,15 @@ where
}
}

impl<Block, Client, SelectChain> Verifier<Block> for BabeVerifier<Block, Client, SelectChain>
impl<Block, Client, SelectChain, CAW> Verifier<Block>
for BabeVerifier<Block, Client, SelectChain, CAW>
where
Block: BlockT,
Client: HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + AuxStore + ProvideCache<Block>,
Client::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error> + BabeApi<Block, Error = sp_blockchain::Error>,
SelectChain: sp_consensus::SelectChain<Block>,
CAW: CanAuthorWith<Block> + Send + Sync,
{
fn verify(
&mut self,
Expand Down Expand Up @@ -1422,7 +1436,7 @@ pub fn block_import<Client, Block: BlockT, I>(
///
/// The block import object provided must be the `BabeBlockImport` or a wrapper
/// of it, otherwise crucial import logic will be omitted.
pub fn import_queue<Block: BlockT, Client, SelectChain, Inner>(
pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
babe_link: BabeLink<Block>,
block_import: Inner,
justification_import: Option<BoxJustificationImport<Block>>,
Expand All @@ -1432,13 +1446,15 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner>(
inherent_data_providers: InherentDataProviders,
spawner: &impl sp_core::traits::SpawnNamed,
registry: Option<&Registry>,
can_author_with: CAW,
) -> ClientResult<DefaultImportQueue<Block, Client>> where
Inner: BlockImport<Block, Error = ConsensusError, Transaction = sp_api::TransactionFor<Client, Block>>
+ Send + Sync + 'static,
Client: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
Client: HeaderBackend<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error>,
Client::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>,
SelectChain: sp_consensus::SelectChain<Block> + 'static,
CAW: CanAuthorWith<Block> + Send + Sync + 'static,
{
register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?;

Expand All @@ -1449,6 +1465,7 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner>(
config: babe_link.config,
epoch_changes: babe_link.epoch_changes,
time_source: babe_link.time_source,
can_author_with,
};

Ok(BasicQueue::new(
Expand Down
5 changes: 3 additions & 2 deletions client/consensus/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use sp_consensus_babe::{
};
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, RecordProof,
NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor,
import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport},
};
use sc_network_test::*;
Expand Down Expand Up @@ -220,7 +220,7 @@ type TestSelectChain = substrate_test_runtime_client::LongestChain<
>;

pub struct TestVerifier {
inner: BabeVerifier<TestBlock, PeersFullClient, TestSelectChain>,
inner: BabeVerifier<TestBlock, PeersFullClient, TestSelectChain, AlwaysCanAuthor>,
mutator: Mutator,
}

Expand Down Expand Up @@ -320,6 +320,7 @@ impl TestNetFactory for BabeTestNet {
config: data.link.config.clone(),
epoch_changes: data.link.epoch_changes.clone(),
time_source: data.link.time_source.clone(),
can_author_with: AlwaysCanAuthor,
},
mutator: MUTATOR.with(|m| m.borrow().clone()),
}
Expand Down
38 changes: 31 additions & 7 deletions client/consensus/pow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,19 @@ pub trait PowAlgorithm<B: BlockT> {
}

/// A block importer for PoW.
pub struct PowBlockImport<B: BlockT, I, C, S, Algorithm> {
pub struct PowBlockImport<B: BlockT, I, C, S, Algorithm, CAW> {
algorithm: Algorithm,
inner: I,
select_chain: Option<S>,
client: Arc<C>,
inherent_data_providers: sp_inherents::InherentDataProviders,
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
can_author_with: CAW,
}

impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone> Clone for PowBlockImport<B, I, C, S, Algorithm> {
impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone, CAW: Clone> Clone
for PowBlockImport<B, I, C, S, Algorithm, CAW>
{
fn clone(&self) -> Self {
Self {
algorithm: self.algorithm.clone(),
Expand All @@ -204,17 +207,19 @@ impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone> Clone for PowBlockImpor
client: self.client.clone(),
inherent_data_providers: self.inherent_data_providers.clone(),
check_inherents_after: self.check_inherents_after.clone(),
can_author_with: self.can_author_with.clone(),
}
}
}

impl<B, I, C, S, Algorithm> PowBlockImport<B, I, C, S, Algorithm> where
impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> where
B: BlockT,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
I::Error: Into<ConsensusError>,
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
Algorithm: PowAlgorithm<B>,
CAW: CanAuthorWith<B>,
{
/// Create a new block import suitable to be used in PoW
pub fn new(
Expand All @@ -224,9 +229,17 @@ impl<B, I, C, S, Algorithm> PowBlockImport<B, I, C, S, Algorithm> where
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
select_chain: Option<S>,
inherent_data_providers: sp_inherents::InherentDataProviders,
can_author_with: CAW,
) -> Self {
Self { inner, client, algorithm, check_inherents_after,
select_chain, inherent_data_providers }
Self {
inner,
client,
algorithm,
check_inherents_after,
select_chain,
inherent_data_providers,
can_author_with,
}
}

fn check_inherents(
Expand All @@ -242,6 +255,16 @@ impl<B, I, C, S, Algorithm> PowBlockImport<B, I, C, S, Algorithm> where
return Ok(())
}

if let Err(e) = self.can_author_with.can_author_with(&block_id) {
debug!(
target: "pow",
"Skipping `check_inherents` as authoring version is not compatible: {}",
e,
);

return Ok(())
}

let inherent_res = self.client.runtime_api().check_inherents(
&block_id,
block,
Expand Down Expand Up @@ -270,7 +293,7 @@ impl<B, I, C, S, Algorithm> PowBlockImport<B, I, C, S, Algorithm> where
}
}

impl<B, I, C, S, Algorithm> BlockImport<B> for PowBlockImport<B, I, C, S, Algorithm> where
impl<B, I, C, S, Algorithm, CAW> BlockImport<B> for PowBlockImport<B, I, C, S, Algorithm, CAW> where
B: BlockT,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
I::Error: Into<ConsensusError>,
Expand All @@ -279,6 +302,7 @@ impl<B, I, C, S, Algorithm> BlockImport<B> for PowBlockImport<B, I, C, S, Algori
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
Algorithm: PowAlgorithm<B>,
Algorithm::Difficulty: 'static,
CAW: CanAuthorWith<B>,
{
type Error = ConsensusError;
type Transaction = sp_api::TransactionFor<C, B>;
Expand Down Expand Up @@ -649,7 +673,7 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
};

log::info!("✅ Successfully mined block: {}", best_hash);

let (hash, seal) = {
let seal = DigestItem::Seal(POW_ENGINE_ID, seal);
let mut header = header.clone();
Expand Down
Loading