diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index babfef8dc1..1869eba5dd 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -286,7 +286,6 @@ enum CheckedHeader { Checked(H, u64, ed25519::Signature), } - /// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. /// if it's successful, returns the pre-header, the slot number, and the signat. // @@ -328,15 +327,37 @@ fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, a } } -/// A verifier for Aura blocks. -pub struct AuraVerifier { - config: Config, - client: Arc, +/// Extra verification for Aura blocks. +pub trait ExtraVerification: Send + Sync { + /// Future that resolves when the block is verified or fails with error if not. + type Verified: IntoFuture; + + /// Do additional verification for this block. + fn verify(&self, header: &B::Header, body: Option<&[B::Extrinsic]>) -> Self::Verified; } -impl Verifier for AuraVerifier where +/// No-op extra verification. +#[derive(Debug, Clone, Copy)] +pub struct NothingExtra; + +impl ExtraVerification for NothingExtra { + type Verified = Result<(), String>; + + fn verify(&self, _: &B::Header, _: Option<&[B::Extrinsic]>) -> Self::Verified { + Ok(()) + } +} +/// A verifier for Aura blocks. +pub struct AuraVerifier { + config: Config, + client: Arc, + extra: E, +} + +impl Verifier for AuraVerifier where C: Authorities + BlockImport + Send + Sync, DigestItemFor: CompatibleDigestItem, + E: ExtraVerification, { fn verify( &self, @@ -352,6 +373,8 @@ impl Verifier for AuraVerifier where let authorities = self.client.authorities(&BlockId::Hash(parent_hash)) .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; + let extra_verification = self.extra.verify(&header, body.as_ref().map(|x| &x[..])); + // we add one to allow for some small drift. // FIXME: in the future, alter this queue to allow deferring of headers // https://github.com/paritytech/substrate/issues/1019 @@ -362,6 +385,7 @@ impl Verifier for AuraVerifier where debug!(target: "aura", "Checked {:?}; importing.", pre_header); + extra_verification.into_future().wait()?; let import_block = ImportBlock { origin, header: pre_header, @@ -384,20 +408,19 @@ impl Verifier for AuraVerifier where } /// The Aura import queue type. -pub type AuraImportQueue = BasicQueue>; +pub type AuraImportQueue = BasicQueue>; /// Start an import queue for the Aura consensus algorithm. -pub fn import_queue(config: Config, client: Arc) -> AuraImportQueue where +pub fn import_queue(config: Config, client: Arc, extra: E) -> AuraImportQueue where B: Block, C: Authorities + BlockImport + Send + Sync, DigestItemFor: CompatibleDigestItem, + E: ExtraVerification, { - let verifier = Arc::new(AuraVerifier { config, client: client.clone() }); + let verifier = Arc::new(AuraVerifier { config, client: client.clone(), extra, }); BasicQueue::new(verifier, client) } - - #[cfg(test)] mod tests { use super::*; @@ -443,12 +466,12 @@ mod tests { const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); pub struct AuraTestNet { - peers: Vec, ()>>>, + peers: Vec, ()>>>, started: bool } impl TestNetFactory for AuraTestNet { - type Verifier = AuraVerifier; + type Verifier = AuraVerifier; type PeerData = (); /// Create new test network with peers and given config. @@ -463,7 +486,7 @@ mod tests { -> Arc { let config = Config { local_key: None, slot_duration: SLOT_DURATION }; - Arc::new(AuraVerifier { client, config }) + Arc::new(AuraVerifier { client, config, extra: NothingExtra }) } fn peer(&self, i: usize) -> &Peer { diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs index 5a5edb89b0..b232beb538 100644 --- a/substrate/node/cli/src/service.rs +++ b/substrate/node/cli/src/service.rs @@ -28,7 +28,7 @@ use substrate_service::{ Roles, TaskExecutor, }; use node_executor; -use consensus::{import_queue, start_aura, Config as AuraConfig, AuraImportQueue}; +use consensus::{import_queue, start_aura, Config as AuraConfig, AuraImportQueue, NothingExtra}; use client; const AURA_SLOT_DURATION: u64 = 6; @@ -79,17 +79,25 @@ construct_service_factory! { }, LightService = LightComponents { |config, executor| >::new(config, executor) }, - FullImportQueue = AuraImportQueue> - { |config, client| Ok(import_queue(AuraConfig { - local_key: None, - slot_duration: 5 - }, client)) }, - LightImportQueue = AuraImportQueue> - { |config, client| Ok( - import_queue(AuraConfig { + FullImportQueue = AuraImportQueue, NothingExtra> + { |config, client| Ok(import_queue( + AuraConfig { local_key: None, slot_duration: 5 - }, client)) + }, + client, + NothingExtra, + )) + }, + LightImportQueue = AuraImportQueue, NothingExtra> + { |config, client| Ok(import_queue( + AuraConfig { + local_key: None, + slot_duration: 5 + }, + client, + NothingExtra, + )) }, } }