mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 15:41:02 +00:00
Rework inherent data client side (#8526)
* Lol * Yeah * Moare * adaasda * Convert AURA to new pallet macro * AURA: Switch to `CurrentSlot` instead of `LastTimestamp` This switches AURA to use `CurrentSlot` instead of `LastTimestamp`. * Add missing file * Update frame/aura/src/migrations.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Remove the runtime side provide inherent code * Use correct weight * Add TODO * Remove the Inherent from AURA * 🤦 * Remove unused stuff * Update primitives authorship * Fix babe inherent data provider * Fix consensus-uncles * Fix BABE * Do some further changes to authorship primitives... :D * More work * Make it compile the happy path * Make it async! * Take hash * More stuff * Hacks * Revert "Hacks" This reverts commit cfffad88668cfdebf632a59c4fbfada001ef8251. * Fix * Make `execute_block` return the final block header * Move Aura digest stuff * Make it possible to disable equivocation checking * Fix fix fix * Some refactorings * Comment * Fixes fixes fixes * More cleanups * Some love * Better love * Make slot duration being exposed as `Duration` to the outside * Some slot info love * Add `build_aura_worker` utility function * Copy copy copy * Some stuff * Start fixing pow * Fix pow * Remove some bounds * More work * Make grandpa work * Make slots use `async_trait` * Introduce `SharedData` * Add test and fix bugs * Switch to `SharedData` * Make grandpa tests working * More Babe work * Make grandpa work * Introduce `SharedData` * Add test and fix bugs * Switch to `SharedData` * Make grandpa tests working * More Babe work * Make it async * Fix fix * Use `async_trait` in sc-consensus-slots This makes the code a little bit easier to read and also expresses that there can always only be one call at a time to `on_slot`. * Make grandpa tests compile * More Babe tests work * Fix network test * Start fixing service test * Finish service-test * Fix sc-consensus-aura * Fix fix fix * More fixes * Make everything compile *yeah* * Make manual-seal compile * More fixes * Start fixing Aura * Fix Aura tests * Fix Babe tests * Make everything compile * Move code around and switch to async_trait * Fix Babe * Docs docs docs * Move to FRAME * Fix fix fix * Make everything compile * Last cleanups * Fix integration test * Change slot usage of the timestamp * We really need to switch to `impl-trait-for-tuples` * Update primitives/inherents/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update primitives/inherents/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update primitives/inherents/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Some extra logging * Remove dbg! * Update primitives/consensus/common/src/import_queue/basic_queue.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
@@ -39,7 +39,7 @@ use std::{
|
||||
sync::Arc, borrow::Cow, collections::HashMap, marker::PhantomData,
|
||||
cmp::Ordering, time::Duration,
|
||||
};
|
||||
use futures::{prelude::*, future::Either};
|
||||
use futures::{Future, StreamExt};
|
||||
use parking_lot::Mutex;
|
||||
use sc_client_api::{BlockOf, backend::AuxStore, BlockchainEvents};
|
||||
use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as CacheKeyId};
|
||||
@@ -49,7 +49,7 @@ use sp_runtime::generic::{BlockId, Digest, DigestItem};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_consensus_pow::{Seal, TotalDifficulty, POW_ENGINE_ID};
|
||||
use sp_inherents::{InherentDataProviders, InherentData};
|
||||
use sp_inherents::{CreateInherentDataProviders, InherentDataProvider};
|
||||
use sp_consensus::{
|
||||
BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer,
|
||||
SelectChain, Error as ConsensusError, CanAuthorWith, BlockImport, BlockCheckParams, ImportResult,
|
||||
@@ -61,7 +61,6 @@ use codec::{Encode, Decode};
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_client_api;
|
||||
use log::*;
|
||||
use sp_timestamp::{InherentError as TIError, TimestampInherentData};
|
||||
|
||||
use crate::worker::UntilImportedOrTimeout;
|
||||
|
||||
@@ -92,7 +91,12 @@ pub enum Error<B: BlockT> {
|
||||
#[display(fmt = "Creating inherents failed: {}", _0)]
|
||||
CreateInherents(sp_inherents::Error),
|
||||
#[display(fmt = "Checking inherents failed: {}", _0)]
|
||||
CheckInherents(String),
|
||||
CheckInherents(sp_inherents::Error),
|
||||
#[display(
|
||||
fmt = "Checking inherents unknown error for identifier: {:?}",
|
||||
"String::from_utf8_lossy(_0)",
|
||||
)]
|
||||
CheckInherentsUnknownError(sp_inherents::InherentIdentifier),
|
||||
#[display(fmt = "Multiple pre-runtime digests")]
|
||||
MultiplePreRuntimeDigests,
|
||||
Client(sp_blockchain::Error),
|
||||
@@ -200,18 +204,18 @@ pub trait PowAlgorithm<B: BlockT> {
|
||||
}
|
||||
|
||||
/// A block importer for PoW.
|
||||
pub struct PowBlockImport<B: BlockT, I, C, S, Algorithm, CAW> {
|
||||
pub struct PowBlockImport<B: BlockT, I, C, S, Algorithm, CAW, CIDP> {
|
||||
algorithm: Algorithm,
|
||||
inner: I,
|
||||
select_chain: S,
|
||||
client: Arc<C>,
|
||||
inherent_data_providers: sp_inherents::InherentDataProviders,
|
||||
create_inherent_data_providers: Arc<CIDP>,
|
||||
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
|
||||
can_author_with: CAW,
|
||||
}
|
||||
|
||||
impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone, CAW: Clone> Clone
|
||||
for PowBlockImport<B, I, C, S, Algorithm, CAW>
|
||||
impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone, CAW: Clone, CIDP> Clone
|
||||
for PowBlockImport<B, I, C, S, Algorithm, CAW, CIDP>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
@@ -219,14 +223,14 @@ impl<B: BlockT, I: Clone, C, S: Clone, Algorithm: Clone, CAW: Clone> Clone
|
||||
inner: self.inner.clone(),
|
||||
select_chain: self.select_chain.clone(),
|
||||
client: self.client.clone(),
|
||||
inherent_data_providers: self.inherent_data_providers.clone(),
|
||||
create_inherent_data_providers: self.create_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, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> where
|
||||
impl<B, I, C, S, Algorithm, CAW, CIDP> PowBlockImport<B, I, C, S, Algorithm, CAW, CIDP> where
|
||||
B: BlockT,
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
|
||||
I::Error: Into<ConsensusError>,
|
||||
@@ -234,6 +238,7 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
Algorithm: PowAlgorithm<B>,
|
||||
CAW: CanAuthorWith<B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
{
|
||||
/// Create a new block import suitable to be used in PoW
|
||||
pub fn new(
|
||||
@@ -242,7 +247,7 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
|
||||
algorithm: Algorithm,
|
||||
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
|
||||
select_chain: S,
|
||||
inherent_data_providers: sp_inherents::InherentDataProviders,
|
||||
create_inherent_data_providers: CIDP,
|
||||
can_author_with: CAW,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -251,20 +256,17 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
|
||||
algorithm,
|
||||
check_inherents_after,
|
||||
select_chain,
|
||||
inherent_data_providers,
|
||||
create_inherent_data_providers: Arc::new(create_inherent_data_providers),
|
||||
can_author_with,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_inherents(
|
||||
async fn check_inherents(
|
||||
&self,
|
||||
block: B,
|
||||
block_id: BlockId<B>,
|
||||
inherent_data: InherentData,
|
||||
timestamp_now: u64,
|
||||
inherent_data_providers: CIDP::InherentDataProviders,
|
||||
) -> Result<(), Error<B>> {
|
||||
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
|
||||
|
||||
if *block.header().number() < self.check_inherents_after {
|
||||
return Ok(())
|
||||
}
|
||||
@@ -279,6 +281,9 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let inherent_data = inherent_data_providers.create_inherent_data()
|
||||
.map_err(|e| Error::CreateInherents(e))?;
|
||||
|
||||
let inherent_res = self.client.runtime_api().check_inherents(
|
||||
&block_id,
|
||||
block,
|
||||
@@ -286,38 +291,32 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
|
||||
).map_err(|e| Error::Client(e.into()))?;
|
||||
|
||||
if !inherent_res.ok() {
|
||||
inherent_res
|
||||
.into_errors()
|
||||
.try_for_each(|(i, e)| match TIError::try_from(&i, &e) {
|
||||
Some(TIError::ValidAtTimestamp(timestamp)) => {
|
||||
if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS {
|
||||
return Err(Error::TooFarInFuture);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
Some(TIError::Other(e)) => Err(Error::Runtime(e)),
|
||||
None => Err(Error::CheckInherents(
|
||||
self.inherent_data_providers.error_to_string(&i, &e)
|
||||
)),
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
for (identifier, error) in inherent_res.into_errors() {
|
||||
match inherent_data_providers.try_handle_error(&identifier, &error).await {
|
||||
Some(res) => res.map_err(Error::CheckInherents)?,
|
||||
None => return Err(Error::CheckInherentsUnknownError(identifier)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<B, I, C, S, Algorithm, CAW> BlockImport<B> for PowBlockImport<B, I, C, S, Algorithm, CAW> where
|
||||
impl<B, I, C, S, Algorithm, CAW, CIDP> BlockImport<B>
|
||||
for PowBlockImport<B, I, C, S, Algorithm, CAW, CIDP>
|
||||
where
|
||||
B: BlockT,
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
|
||||
I::Error: Into<ConsensusError>,
|
||||
S: SelectChain<B>,
|
||||
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
Algorithm: PowAlgorithm<B> + Send,
|
||||
Algorithm: PowAlgorithm<B> + Send + Sync,
|
||||
Algorithm::Difficulty: 'static + Send,
|
||||
CAW: CanAuthorWith<B> + Send,
|
||||
CAW: CanAuthorWith<B> + Send + Sync,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + Send + Sync,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
type Transaction = sp_api::TransactionFor<C, B>;
|
||||
@@ -343,18 +342,16 @@ impl<B, I, C, S, Algorithm, CAW> BlockImport<B> for PowBlockImport<B, I, C, S, A
|
||||
let mut aux = PowAux::read::<_, B>(self.client.as_ref(), &parent_hash)?;
|
||||
|
||||
if let Some(inner_body) = block.body.take() {
|
||||
let inherent_data = self.inherent_data_providers
|
||||
.create_inherent_data().map_err(|e| e.into_string())?;
|
||||
let timestamp_now = inherent_data.timestamp_inherent_data().map_err(|e| e.into_string())?;
|
||||
|
||||
let check_block = B::new(block.header.clone(), inner_body);
|
||||
|
||||
self.check_inherents(
|
||||
check_block.clone(),
|
||||
BlockId::Hash(parent_hash),
|
||||
inherent_data,
|
||||
*timestamp_now,
|
||||
)?;
|
||||
self.create_inherent_data_providers.create_inherent_data_providers(
|
||||
parent_hash,
|
||||
(),
|
||||
).await?,
|
||||
).await?;
|
||||
|
||||
block.body = Some(check_block.deconstruct().1);
|
||||
}
|
||||
@@ -475,7 +472,7 @@ impl<B: BlockT, Algorithm> Verifier<B> for PowVerifier<B, Algorithm> where
|
||||
import_block.justifications = justifications;
|
||||
import_block.intermediates.insert(
|
||||
Cow::from(INTERMEDIATE_KEY),
|
||||
Box::new(intermediate) as Box<_>,
|
||||
Box::new(intermediate) as Box<_>
|
||||
);
|
||||
import_block.post_hash = Some(hash);
|
||||
|
||||
@@ -483,20 +480,6 @@ impl<B: BlockT, Algorithm> Verifier<B> for PowVerifier<B, Algorithm> where
|
||||
}
|
||||
}
|
||||
|
||||
/// Register the PoW inherent data provider, if not registered already.
|
||||
pub fn register_pow_inherent_data_provider(
|
||||
inherent_data_providers: &InherentDataProviders,
|
||||
) -> Result<(), sp_consensus::Error> {
|
||||
if !inherent_data_providers.has_provider(&sp_timestamp::INHERENT_IDENTIFIER) {
|
||||
inherent_data_providers
|
||||
.register_provider(sp_timestamp::InherentDataProvider)
|
||||
.map_err(Into::into)
|
||||
.map_err(sp_consensus::Error::InherentData)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The PoW import queue type.
|
||||
pub type PowImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
|
||||
|
||||
@@ -505,7 +488,6 @@ pub fn import_queue<B, Transaction, Algorithm>(
|
||||
block_import: BoxBlockImport<B, Transaction>,
|
||||
justification_import: Option<BoxJustificationImport<B>>,
|
||||
algorithm: Algorithm,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
||||
registry: Option<&Registry>,
|
||||
) -> Result<
|
||||
@@ -517,8 +499,6 @@ pub fn import_queue<B, Transaction, Algorithm>(
|
||||
Algorithm: PowAlgorithm<B> + Clone + Send + Sync + 'static,
|
||||
Algorithm::Difficulty: Send,
|
||||
{
|
||||
register_pow_inherent_data_provider(&inherent_data_providers)?;
|
||||
|
||||
let verifier = PowVerifier::new(algorithm);
|
||||
|
||||
Ok(BasicQueue::new(
|
||||
@@ -539,7 +519,7 @@ pub fn import_queue<B, Transaction, Algorithm>(
|
||||
///
|
||||
/// `pre_runtime` is a parameter that allows a custom additional pre-runtime digest to be inserted
|
||||
/// for blocks being built. This can encode authorship information, or just be a graffiti.
|
||||
pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW, CIDP>(
|
||||
block_import: BoxBlockImport<Block, sp_api::TransactionFor<C, Block>>,
|
||||
client: Arc<C>,
|
||||
select_chain: S,
|
||||
@@ -547,7 +527,7 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
mut env: E,
|
||||
mut sync_oracle: SO,
|
||||
pre_runtime: Option<Vec<u8>>,
|
||||
inherent_data_providers: sp_inherents::InherentDataProviders,
|
||||
create_inherent_data_providers: CIDP,
|
||||
timeout: Duration,
|
||||
build_time: Duration,
|
||||
can_author_with: CAW,
|
||||
@@ -565,12 +545,9 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
E::Proposer: Proposer<Block, Transaction = sp_api::TransactionFor<C, Block>>,
|
||||
SO: SyncOracle + Clone + Send + Sync + 'static,
|
||||
CAW: CanAuthorWith<Block> + Clone + Send + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, ()>,
|
||||
{
|
||||
if let Err(_) = register_pow_inherent_data_provider(&inherent_data_providers) {
|
||||
warn!("Registering inherent data provider for timestamp failed");
|
||||
}
|
||||
|
||||
let timer = UntilImportedOrTimeout::new(client.import_notification_stream(), timeout);
|
||||
let mut timer = UntilImportedOrTimeout::new(client.import_notification_stream(), timeout);
|
||||
let worker = Arc::new(Mutex::new(MiningWorker::<Block, Algorithm, C, _> {
|
||||
build: None,
|
||||
algorithm: algorithm.clone(),
|
||||
@@ -578,81 +555,97 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
}));
|
||||
let worker_ret = worker.clone();
|
||||
|
||||
let task = timer.for_each(move |()| {
|
||||
let worker = worker.clone();
|
||||
let task = async move {
|
||||
loop {
|
||||
if timer.next().await.is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
if sync_oracle.is_major_syncing() {
|
||||
debug!(target: "pow", "Skipping proposal due to sync.");
|
||||
worker.lock().on_major_syncing();
|
||||
return Either::Left(future::ready(()))
|
||||
}
|
||||
if sync_oracle.is_major_syncing() {
|
||||
debug!(target: "pow", "Skipping proposal due to sync.");
|
||||
worker.lock().on_major_syncing();
|
||||
return;
|
||||
}
|
||||
|
||||
let best_header = match select_chain.best_chain() {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
let best_header = match select_chain.best_chain() {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to pull new block for authoring. \
|
||||
Select best chain error: {:?}",
|
||||
err
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let best_hash = best_header.hash();
|
||||
|
||||
if let Err(err) = can_author_with.can_author_with(&BlockId::Hash(best_hash)) {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to pull new block for authoring. \
|
||||
Select best chain error: {:?}",
|
||||
err
|
||||
);
|
||||
return Either::Left(future::ready(()))
|
||||
},
|
||||
};
|
||||
let best_hash = best_header.hash();
|
||||
|
||||
if let Err(err) = can_author_with.can_author_with(&BlockId::Hash(best_hash)) {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Skipping proposal `can_author_with` returned: {} \
|
||||
Probably a node update is required!",
|
||||
err,
|
||||
);
|
||||
return Either::Left(future::ready(()))
|
||||
}
|
||||
|
||||
if worker.lock().best_hash() == Some(best_hash) {
|
||||
return Either::Left(future::ready(()))
|
||||
}
|
||||
|
||||
// The worker is locked for the duration of the whole proposing period. Within this period,
|
||||
// the mining target is outdated and useless anyway.
|
||||
|
||||
let difficulty = match algorithm.difficulty(best_hash) {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to propose new block for authoring. \
|
||||
Fetch difficulty failed: {:?}",
|
||||
"Skipping proposal `can_author_with` returned: {} \
|
||||
Probably a node update is required!",
|
||||
err,
|
||||
);
|
||||
return Either::Left(future::ready(()))
|
||||
},
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
let awaiting_proposer = env.init(&best_header);
|
||||
let inherent_data = match inherent_data_providers.create_inherent_data() {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to propose new block for authoring. \
|
||||
Creating inherent data failed: {:?}",
|
||||
err,
|
||||
);
|
||||
return Either::Left(future::ready(()))
|
||||
},
|
||||
};
|
||||
let mut inherent_digest = Digest::<Block::Hash>::default();
|
||||
if let Some(pre_runtime) = &pre_runtime {
|
||||
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, pre_runtime.to_vec()));
|
||||
}
|
||||
if worker.lock().best_hash() == Some(best_hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pre_runtime = pre_runtime.clone();
|
||||
// The worker is locked for the duration of the whole proposing period. Within this period,
|
||||
// the mining target is outdated and useless anyway.
|
||||
|
||||
Either::Right(async move {
|
||||
let proposer = match awaiting_proposer.await {
|
||||
let difficulty = match algorithm.difficulty(best_hash) {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to propose new block for authoring. \
|
||||
Fetch difficulty failed: {:?}",
|
||||
err,
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let inherent_data_providers =
|
||||
match create_inherent_data_providers.create_inherent_data_providers(best_hash, ()).await {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to propose new block for authoring. \
|
||||
Creating inherent data providers failed: {:?}",
|
||||
err,
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let inherent_data = match inherent_data_providers.create_inherent_data() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
warn!(
|
||||
target: "pow",
|
||||
"Unable to propose new block for authoring. \
|
||||
Creating inherent data failed: {:?}",
|
||||
e,
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let mut inherent_digest = Digest::<Block::Hash>::default();
|
||||
if let Some(pre_runtime) = &pre_runtime {
|
||||
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, pre_runtime.to_vec()));
|
||||
}
|
||||
|
||||
let pre_runtime = pre_runtime.clone();
|
||||
|
||||
let proposer = match env.init(&best_header).await {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
@@ -694,8 +687,8 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
};
|
||||
|
||||
worker.lock().on_build(build);
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
(worker_ret, task)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user