diff --git a/substrate/client/consensus/pow/src/lib.rs b/substrate/client/consensus/pow/src/lib.rs index 87f51be216..d656f71a15 100644 --- a/substrate/client/consensus/pow/src/lib.rs +++ b/substrate/client/consensus/pow/src/lib.rs @@ -63,8 +63,8 @@ pub enum Error { HeaderUnsealed(B::Hash), #[display(fmt = "PoW validation error: invalid seal")] InvalidSeal, - #[display(fmt = "PoW validation error: invalid difficulty")] - InvalidDifficulty, + #[display(fmt = "PoW validation error: preliminary verification failed")] + FailedPreliminaryVerify, #[display(fmt = "Rejecting block too far in future")] TooFarInFuture, #[display(fmt = "Fetching best header failed using select chain: {:?}", _0)] @@ -154,18 +154,23 @@ pub trait PowAlgorithm { /// This function will be called twice during the import process, so the implementation /// should be properly cached. fn difficulty(&self, parent: &BlockId) -> Result>; - /// Verify that the seal is valid against given pre hash. - fn verify_seal( + /// Verify that the seal is valid against given pre hash when parent block is not yet imported. + /// + /// None means that preliminary verify is not available for this algorithm. + fn preliminary_verify( &self, + _pre_hash: &B::Hash, + _seal: &Seal, + ) -> Result, Error> { + Ok(None) + } + /// Verify that the difficulty is valid against given seal. + fn verify( + &self, + parent: &BlockId, pre_hash: &B::Hash, seal: &Seal, - ) -> Result>; - /// Verify that the difficulty is valid against given seal. - fn verify_difficulty( - &self, difficulty: Self::Difficulty, - parent: &BlockId, - seal: &Seal, ) -> Result>; /// Mine a seal that satisfies the given difficulty. fn mine( @@ -187,6 +192,19 @@ pub struct PowBlockImport { check_inherents_after: <::Header as HeaderT>::Number, } +impl Clone for PowBlockImport { + fn clone(&self) -> Self { + Self { + algorithm: self.algorithm.clone(), + inner: self.inner.clone(), + select_chain: self.select_chain.clone(), + client: self.client.clone(), + inherent_data_providers: self.inherent_data_providers.clone(), + check_inherents_after: self.check_inherents_after.clone(), + } + } +} + impl PowBlockImport where B: BlockT, I: BlockImport> + Send + Sync, @@ -322,12 +340,14 @@ impl BlockImport for PowBlockImport self.algorithm.difficulty(&BlockId::hash(parent_hash))?, }; - if !self.algorithm.verify_difficulty( - difficulty, + let pre_hash = block.header.hash(); + if !self.algorithm.verify( &BlockId::hash(parent_hash), + &pre_hash, &inner_seal, + difficulty, )? { - return Err(Error::::InvalidDifficulty.into()) + return Err(Error::::InvalidSeal.into()) } aux.difficulty = difficulty; @@ -379,11 +399,8 @@ impl PowVerifier { let pre_hash = header.hash(); - if !self.algorithm.verify_seal( - &pre_hash, - &inner_seal, - )? { - return Err(Error::InvalidSeal); + if !self.algorithm.preliminary_verify(&pre_hash, &inner_seal)?.unwrap_or(true) { + return Err(Error::FailedPreliminaryVerify); } Ok((header, seal)) @@ -450,20 +467,17 @@ pub fn register_pow_inherent_data_provider( pub type PowImportQueue = BasicQueue; /// Import queue for PoW engine. -pub fn import_queue( - block_import: BoxBlockImport>, +pub fn import_queue( + block_import: BoxBlockImport, algorithm: Algorithm, inherent_data_providers: InherentDataProviders, ) -> Result< - PowImportQueue>, + PowImportQueue, sp_consensus::Error > where B: BlockT, - C: ProvideRuntimeApi + HeaderBackend + BlockOf + ProvideCache + AuxStore, - C: Send + Sync + AuxStore + 'static, - C::Api: BlockBuilderApi, + Transaction: Send + Sync + 'static, Algorithm: PowAlgorithm + Clone + Send + Sync + 'static, - S: SelectChain + 'static, { register_pow_inherent_data_provider(&inherent_data_providers)?;