mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -19,26 +19,30 @@
|
||||
//! Extensions for manual seal to produce blocks valid for any runtime.
|
||||
use super::Error;
|
||||
|
||||
use sp_runtime::traits::{Block as BlockT, DigestFor};
|
||||
use sp_inherents::InherentData;
|
||||
use sp_consensus::BlockImportParams;
|
||||
use sp_inherents::InherentData;
|
||||
use sp_runtime::traits::{Block as BlockT, DigestFor};
|
||||
|
||||
pub mod babe;
|
||||
|
||||
/// Consensus data provider, manual seal uses this trait object for authoring blocks valid
|
||||
/// Consensus data provider, manual seal uses this trait object for authoring blocks valid
|
||||
/// for any runtime.
|
||||
pub trait ConsensusDataProvider<B: BlockT>: Send + Sync {
|
||||
/// Block import transaction type
|
||||
type Transaction;
|
||||
|
||||
/// Attempt to create a consensus digest.
|
||||
fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result<DigestFor<B>, Error>;
|
||||
fn create_digest(
|
||||
&self,
|
||||
parent: &B::Header,
|
||||
inherents: &InherentData,
|
||||
) -> Result<DigestFor<B>, Error>;
|
||||
|
||||
/// set up the neccessary import params.
|
||||
fn append_block_import(
|
||||
&self,
|
||||
parent: &B::Header,
|
||||
params: &mut BlockImportParams<B, Self::Transaction>,
|
||||
inherents: &InherentData
|
||||
inherents: &InherentData,
|
||||
) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
@@ -21,30 +21,40 @@
|
||||
use super::ConsensusDataProvider;
|
||||
use crate::Error;
|
||||
use codec::Encode;
|
||||
use std::{borrow::Cow, sync::{Arc, atomic}, time::SystemTime};
|
||||
use sc_client_api::{AuxStore, UsageProvider};
|
||||
use sc_consensus_babe::{
|
||||
Config, Epoch, authorship, CompatibleDigestItem, BabeIntermediate, INTERMEDIATE_KEY,
|
||||
find_pre_digest,
|
||||
authorship, find_pre_digest, BabeIntermediate, CompatibleDigestItem, Config, Epoch,
|
||||
INTERMEDIATE_KEY,
|
||||
};
|
||||
use sc_consensus_epochs::{
|
||||
descendent_query, EpochHeader, SharedEpochChanges, ViableEpochDescriptor,
|
||||
};
|
||||
use sc_consensus_epochs::{SharedEpochChanges, descendent_query, ViableEpochDescriptor, EpochHeader};
|
||||
use sp_keystore::SyncCryptoStorePtr;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
sync::{atomic, Arc},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata};
|
||||
use sp_consensus::{BlockImportParams, BlockOrigin, ForkChoiceStrategy};
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_consensus_babe::{
|
||||
BabeApi, inherents::BabeInherentData, ConsensusLog, BABE_ENGINE_ID, AuthorityId,
|
||||
digests::{PreDigest, SecondaryPlainPreDigest, NextEpochDescriptor}, BabeAuthorityWeight,
|
||||
use sp_consensus::{
|
||||
import_queue::{CacheKeyId, Verifier},
|
||||
BlockImportParams, BlockOrigin, ForkChoiceStrategy,
|
||||
};
|
||||
use sp_consensus_babe::{
|
||||
digests::{NextEpochDescriptor, PreDigest, SecondaryPlainPreDigest},
|
||||
inherents::BabeInherentData,
|
||||
AuthorityId, BabeApi, BabeAuthorityWeight, ConsensusLog, BABE_ENGINE_ID,
|
||||
};
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier};
|
||||
use sp_runtime::{
|
||||
traits::{DigestItemFor, DigestFor, Block as BlockT, Zero, Header},
|
||||
generic::{Digest, BlockId}, Justifications,
|
||||
generic::{BlockId, Digest},
|
||||
traits::{Block as BlockT, DigestFor, DigestItemFor, Header, Zero},
|
||||
Justifications,
|
||||
};
|
||||
use sp_timestamp::{InherentType, INHERENT_IDENTIFIER, TimestampInherentData};
|
||||
use sp_consensus::import_queue::{Verifier, CacheKeyId};
|
||||
use sp_timestamp::{InherentType, TimestampInherentData, INHERENT_IDENTIFIER};
|
||||
|
||||
/// Provides BABE-compatible predigests and BlockImportParams.
|
||||
/// Intended for use with BABE runtimes.
|
||||
@@ -77,19 +87,16 @@ pub struct BabeVerifier<B: BlockT, C> {
|
||||
impl<B: BlockT, C> BabeVerifier<B, C> {
|
||||
/// create a nrew verifier
|
||||
pub fn new(epoch_changes: SharedEpochChanges<B, Epoch>, client: Arc<C>) -> BabeVerifier<B, C> {
|
||||
BabeVerifier {
|
||||
epoch_changes,
|
||||
client,
|
||||
}
|
||||
BabeVerifier { epoch_changes, client }
|
||||
}
|
||||
}
|
||||
|
||||
/// The verifier for the manual seal engine; instantly finalizes.
|
||||
#[async_trait::async_trait]
|
||||
impl<B, C> Verifier<B> for BabeVerifier<B, C>
|
||||
where
|
||||
B: BlockT,
|
||||
C: HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error>
|
||||
where
|
||||
B: BlockT,
|
||||
C: HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error>,
|
||||
{
|
||||
async fn verify(
|
||||
&mut self,
|
||||
@@ -107,7 +114,9 @@ impl<B, C> Verifier<B> for BabeVerifier<B, C>
|
||||
let pre_digest = find_pre_digest::<B>(&header)?;
|
||||
|
||||
let parent_hash = header.parent_hash();
|
||||
let parent = self.client.header(BlockId::Hash(*parent_hash))
|
||||
let parent = self
|
||||
.client
|
||||
.header(BlockId::Hash(*parent_hash))
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or_else(|| format!("header for block {} not found", parent_hash))?;
|
||||
@@ -134,14 +143,14 @@ impl<B, C> Verifier<B> for BabeVerifier<B, C>
|
||||
}
|
||||
|
||||
impl<B, C> BabeConsensusDataProvider<B, C>
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore
|
||||
+ HeaderBackend<B>
|
||||
+ ProvideRuntimeApi<B>
|
||||
+ HeaderMetadata<B, Error = sp_blockchain::Error>
|
||||
+ UsageProvider<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore
|
||||
+ HeaderBackend<B>
|
||||
+ ProvideRuntimeApi<B>
|
||||
+ HeaderMetadata<B, Error = sp_blockchain::Error>
|
||||
+ UsageProvider<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
{
|
||||
pub fn new(
|
||||
client: Arc<C>,
|
||||
@@ -155,13 +164,7 @@ impl<B, C> BabeConsensusDataProvider<B, C>
|
||||
|
||||
let config = Config::get_or_compute(&*client)?;
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
client,
|
||||
keystore,
|
||||
epoch_changes,
|
||||
authorities,
|
||||
})
|
||||
Ok(Self { config, client, keystore, epoch_changes, authorities })
|
||||
}
|
||||
|
||||
fn epoch(&self, parent: &B::Header, slot: Slot) -> Result<Epoch, Error> {
|
||||
@@ -177,10 +180,7 @@ impl<B, C> BabeConsensusDataProvider<B, C>
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
|
||||
let epoch = epoch_changes
|
||||
.viable_epoch(
|
||||
&epoch_descriptor,
|
||||
|slot| Epoch::genesis(&self.config, slot),
|
||||
)
|
||||
.viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot))
|
||||
.ok_or_else(|| {
|
||||
log::info!(target: "babe", "create_digest: no viable_epoch :(");
|
||||
sp_consensus::Error::InvalidAuthoritiesSet
|
||||
@@ -191,38 +191,37 @@ impl<B, C> BabeConsensusDataProvider<B, C>
|
||||
}
|
||||
|
||||
impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore
|
||||
+ HeaderBackend<B>
|
||||
+ HeaderMetadata<B, Error = sp_blockchain::Error>
|
||||
+ UsageProvider<B>
|
||||
+ ProvideRuntimeApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore
|
||||
+ HeaderBackend<B>
|
||||
+ HeaderMetadata<B, Error = sp_blockchain::Error>
|
||||
+ UsageProvider<B>
|
||||
+ ProvideRuntimeApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
{
|
||||
type Transaction = TransactionFor<C, B>;
|
||||
|
||||
fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result<DigestFor<B>, Error> {
|
||||
let slot = inherents.babe_inherent_data()?
|
||||
fn create_digest(
|
||||
&self,
|
||||
parent: &B::Header,
|
||||
inherents: &InherentData,
|
||||
) -> Result<DigestFor<B>, Error> {
|
||||
let slot = inherents
|
||||
.babe_inherent_data()?
|
||||
.ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
|
||||
let epoch = self.epoch(parent, slot)?;
|
||||
|
||||
// this is a dev node environment, we should always be able to claim a slot.
|
||||
let logs = if let Some((predigest, _)) = authorship::claim_slot(
|
||||
slot,
|
||||
&epoch,
|
||||
&self.keystore,
|
||||
) {
|
||||
vec![
|
||||
<DigestItemFor<B> as CompatibleDigestItem>::babe_pre_digest(predigest),
|
||||
]
|
||||
let logs = if let Some((predigest, _)) =
|
||||
authorship::claim_slot(slot, &epoch, &self.keystore)
|
||||
{
|
||||
vec![<DigestItemFor<B> as CompatibleDigestItem>::babe_pre_digest(predigest)]
|
||||
} else {
|
||||
// well we couldn't claim a slot because this is an existing chain and we're not in the authorities.
|
||||
// we need to tell BabeBlockImport that the epoch has changed, and we put ourselves in the authorities.
|
||||
let predigest = PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
|
||||
slot,
|
||||
authority_index: 0_u32,
|
||||
});
|
||||
let predigest =
|
||||
PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot, authority_index: 0_u32 });
|
||||
|
||||
let mut epoch_changes = self.epoch_changes.shared_data();
|
||||
let epoch_descriptor = epoch_changes
|
||||
@@ -232,12 +231,15 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
parent.number().clone(),
|
||||
slot,
|
||||
)
|
||||
.map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
|
||||
.map_err(|e| {
|
||||
Error::StringError(format!("failed to fetch epoch_descriptor: {}", e))
|
||||
})?
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
|
||||
match epoch_descriptor {
|
||||
ViableEpochDescriptor::Signaled(identifier, _epoch_header) => {
|
||||
let epoch_mut = epoch_changes.epoch_mut(&identifier)
|
||||
let epoch_mut = epoch_changes
|
||||
.epoch_mut(&identifier)
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
|
||||
// mutate the current epoch
|
||||
@@ -251,15 +253,13 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
|
||||
vec![
|
||||
DigestItemFor::<B>::PreRuntime(BABE_ENGINE_ID, predigest.encode()),
|
||||
DigestItemFor::<B>::Consensus(BABE_ENGINE_ID, next_epoch.encode())
|
||||
DigestItemFor::<B>::Consensus(BABE_ENGINE_ID, next_epoch.encode()),
|
||||
]
|
||||
},
|
||||
ViableEpochDescriptor::UnimportedGenesis(_) => {
|
||||
// since this is the genesis, secondary predigest works for now.
|
||||
vec![
|
||||
DigestItemFor::<B>::PreRuntime(BABE_ENGINE_ID, predigest.encode()),
|
||||
]
|
||||
}
|
||||
vec![DigestItemFor::<B>::PreRuntime(BABE_ENGINE_ID, predigest.encode())]
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -270,9 +270,10 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
&self,
|
||||
parent: &B::Header,
|
||||
params: &mut BlockImportParams<B, Self::Transaction>,
|
||||
inherents: &InherentData
|
||||
inherents: &InherentData,
|
||||
) -> Result<(), Error> {
|
||||
let slot = inherents.babe_inherent_data()?
|
||||
let slot = inherents
|
||||
.babe_inherent_data()?
|
||||
.ok_or_else(|| Error::StringError("No babe inherent data".into()))?;
|
||||
let epoch_changes = self.epoch_changes.shared_data();
|
||||
let mut epoch_descriptor = epoch_changes
|
||||
@@ -289,27 +290,27 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
// a quick check to see if we're in the authorities
|
||||
let epoch = self.epoch(parent, slot)?;
|
||||
let (authority, _) = self.authorities.first().expect("authorities is non-emptyp; qed");
|
||||
let has_authority = epoch.authorities.iter()
|
||||
.find(|(id, _)| *id == *authority)
|
||||
.is_some();
|
||||
let has_authority = epoch.authorities.iter().find(|(id, _)| *id == *authority).is_some();
|
||||
|
||||
if !has_authority {
|
||||
log::info!(target: "manual-seal", "authority not found");
|
||||
let timestamp = inherents.timestamp_inherent_data()?
|
||||
let timestamp = inherents
|
||||
.timestamp_inherent_data()?
|
||||
.ok_or_else(|| Error::StringError("No timestamp inherent data".into()))?;
|
||||
let slot = *timestamp / self.config.slot_duration;
|
||||
// manually hard code epoch descriptor
|
||||
epoch_descriptor = match epoch_descriptor {
|
||||
ViableEpochDescriptor::Signaled(identifier, _header) => {
|
||||
ViableEpochDescriptor::Signaled(identifier, _header) =>
|
||||
ViableEpochDescriptor::Signaled(
|
||||
identifier,
|
||||
EpochHeader {
|
||||
start_slot: slot.into(),
|
||||
end_slot: (slot * self.config.epoch_length).into(),
|
||||
},
|
||||
)
|
||||
},
|
||||
_ => unreachable!("we're not in the authorities, so this isn't the genesis epoch; qed")
|
||||
),
|
||||
_ => unreachable!(
|
||||
"we're not in the authorities, so this isn't the genesis epoch; qed"
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -326,16 +327,16 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
/// Mocks the timestamp inherent to always produce the timestamp for the next babe slot.
|
||||
pub struct SlotTimestampProvider {
|
||||
time: atomic::AtomicU64,
|
||||
slot_duration: u64
|
||||
slot_duration: u64,
|
||||
}
|
||||
|
||||
impl SlotTimestampProvider {
|
||||
/// Create a new mocked time stamp provider.
|
||||
pub fn new<B, C>(client: Arc<C>) -> Result<Self, Error>
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B> + UsageProvider<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
where
|
||||
B: BlockT,
|
||||
C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B> + UsageProvider<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
{
|
||||
let slot_duration = Config::get_or_compute(&*client)?.slot_duration;
|
||||
let info = client.info();
|
||||
@@ -355,10 +356,7 @@ impl SlotTimestampProvider {
|
||||
.as_millis() as u64
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
time: atomic::AtomicU64::new(time),
|
||||
slot_duration,
|
||||
})
|
||||
Ok(Self { time: atomic::AtomicU64::new(time), slot_duration })
|
||||
}
|
||||
|
||||
/// Get the current slot number
|
||||
@@ -369,12 +367,13 @@ impl SlotTimestampProvider {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl InherentDataProvider for SlotTimestampProvider {
|
||||
fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), sp_inherents::Error> {
|
||||
fn provide_inherent_data(
|
||||
&self,
|
||||
inherent_data: &mut InherentData,
|
||||
) -> Result<(), sp_inherents::Error> {
|
||||
// we update the time here.
|
||||
let duration: InherentType = self.time.fetch_add(
|
||||
self.slot_duration,
|
||||
atomic::Ordering::SeqCst,
|
||||
).into();
|
||||
let duration: InherentType =
|
||||
self.time.fetch_add(self.slot_duration, atomic::Ordering::SeqCst).into();
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &duration)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
//! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks.
|
||||
//! This is suitable for a testing environment.
|
||||
|
||||
use sp_consensus::{Error as ConsensusError, ImportResult};
|
||||
use futures::channel::{mpsc::SendError, oneshot};
|
||||
use sp_blockchain::Error as BlockchainError;
|
||||
use sp_consensus::{Error as ConsensusError, ImportResult};
|
||||
use sp_inherents::Error as InherentsError;
|
||||
use futures::channel::{oneshot, mpsc::SendError};
|
||||
|
||||
/// Error code for rpc
|
||||
mod codes {
|
||||
@@ -63,14 +63,14 @@ pub enum Error {
|
||||
#[display(fmt = "{}", _0)]
|
||||
#[from(ignore)]
|
||||
StringError(String),
|
||||
///send error
|
||||
/// send error
|
||||
#[display(fmt = "Consensus process is terminating")]
|
||||
Canceled(oneshot::Canceled),
|
||||
///send error
|
||||
/// send error
|
||||
#[display(fmt = "Consensus process is terminating")]
|
||||
SendError(SendError),
|
||||
/// Some other error.
|
||||
#[display(fmt="Other error: {}", _0)]
|
||||
#[display(fmt = "Other error: {}", _0)]
|
||||
Other(Box<dyn std::error::Error + Send>),
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ impl Error {
|
||||
InherentError(_) => codes::INHERENTS_ERROR,
|
||||
BlockchainError(_) => codes::BLOCKCHAIN_ERROR,
|
||||
SendError(_) | Canceled(_) => codes::SERVER_SHUTTING_DOWN,
|
||||
_ => codes::UNKNOWN_ERROR
|
||||
_ => codes::UNKNOWN_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ impl std::convert::From<Error> for jsonrpc_core::Error {
|
||||
jsonrpc_core::Error {
|
||||
code: jsonrpc_core::ErrorCode::ServerError(error.to_code()),
|
||||
message: format!("{}", error),
|
||||
data: None
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,14 +19,9 @@
|
||||
//! Block finalization utilities
|
||||
|
||||
use crate::rpc;
|
||||
use sp_runtime::{
|
||||
Justification,
|
||||
traits::Block as BlockT,
|
||||
generic::BlockId,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use sc_client_api::backend::{Backend as ClientBackend, Finalizer};
|
||||
use std::marker::PhantomData;
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT, Justification};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
/// params for block finalization.
|
||||
pub struct FinalizeBlockParams<B: BlockT, F, CB> {
|
||||
@@ -42,30 +37,23 @@ pub struct FinalizeBlockParams<B: BlockT, F, CB> {
|
||||
pub _phantom: PhantomData<CB>,
|
||||
}
|
||||
|
||||
|
||||
/// finalizes a block in the backend with the given params.
|
||||
pub async fn finalize_block<B, F, CB>(params: FinalizeBlockParams<B, F, CB>)
|
||||
where
|
||||
B: BlockT,
|
||||
F: Finalizer<B, CB>,
|
||||
CB: ClientBackend<B>,
|
||||
where
|
||||
B: BlockT,
|
||||
F: Finalizer<B, CB>,
|
||||
CB: ClientBackend<B>,
|
||||
{
|
||||
let FinalizeBlockParams {
|
||||
hash,
|
||||
mut sender,
|
||||
justification,
|
||||
finalizer,
|
||||
..
|
||||
} = params;
|
||||
let FinalizeBlockParams { hash, mut sender, justification, finalizer, .. } = params;
|
||||
|
||||
match finalizer.finalize_block(BlockId::Hash(hash), justification, true) {
|
||||
Err(e) => {
|
||||
log::warn!("Failed to finalize block {:?}", e);
|
||||
rpc::send_result(&mut sender, Err(e.into()))
|
||||
}
|
||||
},
|
||||
Ok(()) => {
|
||||
log::info!("✅ Successfully finalized block: {}", hash);
|
||||
rpc::send_result(&mut sender, Ok(()))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
//! This is suitable for a testing environment.
|
||||
|
||||
use futures::prelude::*;
|
||||
use sp_consensus::{
|
||||
Environment, Proposer, SelectChain, BlockImport,
|
||||
ForkChoiceStrategy, BlockImportParams, BlockOrigin,
|
||||
import_queue::{Verifier, BasicQueue, CacheKeyId, BoxBlockImport},
|
||||
};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_inherents::CreateInherentDataProviders;
|
||||
use sp_runtime::{traits::Block as BlockT, Justifications, ConsensusEngineId};
|
||||
use sc_client_api::backend::{Backend as ClientBackend, Finalizer};
|
||||
use std::{sync::Arc, marker::PhantomData};
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_client_api::backend::{Backend as ClientBackend, Finalizer};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_consensus::{
|
||||
import_queue::{BasicQueue, BoxBlockImport, CacheKeyId, Verifier},
|
||||
BlockImport, BlockImportParams, BlockOrigin, Environment, ForkChoiceStrategy, Proposer,
|
||||
SelectChain,
|
||||
};
|
||||
use sp_inherents::CreateInherentDataProviders;
|
||||
use sp_runtime::{traits::Block as BlockT, ConsensusEngineId, Justifications};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
mod error;
|
||||
mod finalize_block;
|
||||
@@ -40,14 +40,14 @@ pub mod consensus;
|
||||
pub mod rpc;
|
||||
|
||||
pub use self::{
|
||||
error::Error,
|
||||
consensus::ConsensusDataProvider,
|
||||
error::Error,
|
||||
finalize_block::{finalize_block, FinalizeBlockParams},
|
||||
seal_block::{SealBlockParams, seal_block, MAX_PROPOSAL_DURATION},
|
||||
rpc::{EngineCommand, CreatedBlock},
|
||||
rpc::{CreatedBlock, EngineCommand},
|
||||
seal_block::{seal_block, SealBlockParams, MAX_PROPOSAL_DURATION},
|
||||
};
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
use sc_transaction_pool_api::TransactionPool;
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
|
||||
/// The `ConsensusEngineId` of Manual Seal.
|
||||
pub const MANUAL_SEAL_ENGINE_ID: ConsensusEngineId = [b'm', b'a', b'n', b'l'];
|
||||
@@ -80,17 +80,11 @@ pub fn import_queue<Block, Transaction>(
|
||||
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
||||
registry: Option<&Registry>,
|
||||
) -> BasicQueue<Block, Transaction>
|
||||
where
|
||||
Block: BlockT,
|
||||
Transaction: Send + Sync + 'static,
|
||||
where
|
||||
Block: BlockT,
|
||||
Transaction: Send + Sync + 'static,
|
||||
{
|
||||
BasicQueue::new(
|
||||
ManualSealVerifier,
|
||||
block_import,
|
||||
None,
|
||||
spawner,
|
||||
registry,
|
||||
)
|
||||
BasicQueue::new(ManualSealVerifier, block_import, None, spawner, registry)
|
||||
}
|
||||
|
||||
/// Params required to start the instant sealing authorship task.
|
||||
@@ -115,7 +109,8 @@ pub struct ManualSealParams<B: BlockT, BI, E, C: ProvideRuntimeApi<B>, TP, SC, C
|
||||
pub select_chain: SC,
|
||||
|
||||
/// Digest provider for inclusion in blocks.
|
||||
pub consensus_data_provider: Option<Box<dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>>,
|
||||
pub consensus_data_provider:
|
||||
Option<Box<dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>>,
|
||||
|
||||
/// Something that can create the inherent data providers.
|
||||
pub create_inherent_data_providers: CIDP,
|
||||
@@ -139,7 +134,8 @@ pub struct InstantSealParams<B: BlockT, BI, E, C: ProvideRuntimeApi<B>, TP, SC,
|
||||
pub select_chain: SC,
|
||||
|
||||
/// Digest provider for inclusion in blocks.
|
||||
pub consensus_data_provider: Option<Box<dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>>,
|
||||
pub consensus_data_provider:
|
||||
Option<Box<dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>>,
|
||||
|
||||
/// Something that can create the inherent data providers.
|
||||
pub create_inherent_data_providers: CIDP,
|
||||
@@ -156,58 +152,52 @@ pub async fn run_manual_seal<B, BI, CB, E, C, TP, SC, CS, CIDP>(
|
||||
select_chain,
|
||||
consensus_data_provider,
|
||||
create_inherent_data_providers,
|
||||
}: ManualSealParams<B, BI, E, C, TP, SC, CS, CIDP>
|
||||
)
|
||||
where
|
||||
B: BlockT + 'static,
|
||||
BI: BlockImport<B, Error = sp_consensus::Error, Transaction = sp_api::TransactionFor<C, B>>
|
||||
+ Send + Sync + 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + ProvideRuntimeApi<B> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Proposer: Proposer<B, Transaction = TransactionFor<C, B>>,
|
||||
CS: Stream<Item=EngineCommand<<B as BlockT>::Hash>> + Unpin + 'static,
|
||||
SC: SelectChain<B> + 'static,
|
||||
TransactionFor<C, B>: 'static,
|
||||
TP: TransactionPool<Block = B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
}: ManualSealParams<B, BI, E, C, TP, SC, CS, CIDP>,
|
||||
) where
|
||||
B: BlockT + 'static,
|
||||
BI: BlockImport<B, Error = sp_consensus::Error, Transaction = sp_api::TransactionFor<C, B>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + ProvideRuntimeApi<B> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Proposer: Proposer<B, Transaction = TransactionFor<C, B>>,
|
||||
CS: Stream<Item = EngineCommand<<B as BlockT>::Hash>> + Unpin + 'static,
|
||||
SC: SelectChain<B> + 'static,
|
||||
TransactionFor<C, B>: 'static,
|
||||
TP: TransactionPool<Block = B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
{
|
||||
while let Some(command) = commands_stream.next().await {
|
||||
match command {
|
||||
EngineCommand::SealNewBlock {
|
||||
create_empty,
|
||||
finalize,
|
||||
parent_hash,
|
||||
sender,
|
||||
} => {
|
||||
seal_block(
|
||||
SealBlockParams {
|
||||
sender,
|
||||
parent_hash,
|
||||
finalize,
|
||||
create_empty,
|
||||
env: &mut env,
|
||||
select_chain: &select_chain,
|
||||
block_import: &mut block_import,
|
||||
consensus_data_provider: consensus_data_provider.as_ref().map(|p| &**p),
|
||||
pool: pool.clone(),
|
||||
client: client.clone(),
|
||||
create_inherent_data_providers: &create_inherent_data_providers,
|
||||
}
|
||||
).await;
|
||||
}
|
||||
EngineCommand::SealNewBlock { create_empty, finalize, parent_hash, sender } => {
|
||||
seal_block(SealBlockParams {
|
||||
sender,
|
||||
parent_hash,
|
||||
finalize,
|
||||
create_empty,
|
||||
env: &mut env,
|
||||
select_chain: &select_chain,
|
||||
block_import: &mut block_import,
|
||||
consensus_data_provider: consensus_data_provider.as_ref().map(|p| &**p),
|
||||
pool: pool.clone(),
|
||||
client: client.clone(),
|
||||
create_inherent_data_providers: &create_inherent_data_providers,
|
||||
})
|
||||
.await;
|
||||
},
|
||||
EngineCommand::FinalizeBlock { hash, sender, justification } => {
|
||||
let justification = justification.map(|j| (MANUAL_SEAL_ENGINE_ID, j));
|
||||
finalize_block(
|
||||
FinalizeBlockParams {
|
||||
hash,
|
||||
sender,
|
||||
justification,
|
||||
finalizer: client.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
).await
|
||||
}
|
||||
finalize_block(FinalizeBlockParams {
|
||||
hash,
|
||||
sender,
|
||||
justification,
|
||||
finalizer: client.clone(),
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
.await
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,63 +214,57 @@ pub async fn run_instant_seal<B, BI, CB, E, C, TP, SC, CIDP>(
|
||||
select_chain,
|
||||
consensus_data_provider,
|
||||
create_inherent_data_providers,
|
||||
}: InstantSealParams<B, BI, E, C, TP, SC, CIDP>
|
||||
)
|
||||
where
|
||||
B: BlockT + 'static,
|
||||
BI: BlockImport<B, Error = sp_consensus::Error, Transaction = sp_api::TransactionFor<C, B>>
|
||||
+ Send + Sync + 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + ProvideRuntimeApi<B> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Proposer: Proposer<B, Transaction = TransactionFor<C, B>>,
|
||||
SC: SelectChain<B> + 'static,
|
||||
TransactionFor<C, B>: 'static,
|
||||
TP: TransactionPool<Block = B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
}: InstantSealParams<B, BI, E, C, TP, SC, CIDP>,
|
||||
) where
|
||||
B: BlockT + 'static,
|
||||
BI: BlockImport<B, Error = sp_consensus::Error, Transaction = sp_api::TransactionFor<C, B>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + ProvideRuntimeApi<B> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Proposer: Proposer<B, Transaction = TransactionFor<C, B>>,
|
||||
SC: SelectChain<B> + 'static,
|
||||
TransactionFor<C, B>: 'static,
|
||||
TP: TransactionPool<Block = B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
{
|
||||
// instant-seal creates blocks as soon as transactions are imported
|
||||
// into the transaction pool.
|
||||
let commands_stream = pool.import_notification_stream()
|
||||
.map(|_| {
|
||||
EngineCommand::SealNewBlock {
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
parent_hash: None,
|
||||
sender: None,
|
||||
}
|
||||
});
|
||||
let commands_stream = pool.import_notification_stream().map(|_| EngineCommand::SealNewBlock {
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
parent_hash: None,
|
||||
sender: None,
|
||||
});
|
||||
|
||||
run_manual_seal(
|
||||
ManualSealParams {
|
||||
block_import,
|
||||
env,
|
||||
client,
|
||||
pool,
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider,
|
||||
create_inherent_data_providers,
|
||||
}
|
||||
).await
|
||||
run_manual_seal(ManualSealParams {
|
||||
block_import,
|
||||
env,
|
||||
client,
|
||||
pool,
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider,
|
||||
create_inherent_data_providers,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_test_runtime_client::{
|
||||
DefaultTestClientBuilderExt,
|
||||
TestClientBuilderExt,
|
||||
AccountKeyring::*,
|
||||
TestClientBuilder,
|
||||
};
|
||||
use sc_transaction_pool::{BasicPool, RevalidationType, Options};
|
||||
use substrate_test_runtime_transaction_pool::{TestApi, uxt};
|
||||
use sc_transaction_pool_api::{TransactionPool, MaintainedTransactionPool, TransactionSource};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_consensus::ImportedAux;
|
||||
use sc_basic_authorship::ProposerFactory;
|
||||
use sc_client_api::BlockBackend;
|
||||
use sc_transaction_pool::{BasicPool, Options, RevalidationType};
|
||||
use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool, TransactionSource};
|
||||
use sp_consensus::ImportedAux;
|
||||
use sp_runtime::generic::BlockId;
|
||||
use substrate_test_runtime_client::{
|
||||
AccountKeyring::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
|
||||
};
|
||||
use substrate_test_runtime_transaction_pool::{uxt, TestApi};
|
||||
|
||||
fn api() -> Arc<TestApi> {
|
||||
Arc::new(TestApi::empty())
|
||||
@@ -303,40 +287,32 @@ mod tests {
|
||||
spawner.clone(),
|
||||
0,
|
||||
));
|
||||
let env = ProposerFactory::new(
|
||||
spawner.clone(),
|
||||
client.clone(),
|
||||
pool.clone(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None);
|
||||
// this test checks that blocks are created as soon as transactions are imported into the pool.
|
||||
let (sender, receiver) = futures::channel::oneshot::channel();
|
||||
let mut sender = Arc::new(Some(sender));
|
||||
let commands_stream = pool.pool().validated_pool().import_notification_stream()
|
||||
.map(move |_| {
|
||||
let commands_stream =
|
||||
pool.pool().validated_pool().import_notification_stream().map(move |_| {
|
||||
// we're only going to submit one tx so this fn will only be called once.
|
||||
let mut_sender = Arc::get_mut(&mut sender).unwrap();
|
||||
let mut_sender = Arc::get_mut(&mut sender).unwrap();
|
||||
let sender = std::mem::take(mut_sender);
|
||||
EngineCommand::SealNewBlock {
|
||||
create_empty: false,
|
||||
finalize: true,
|
||||
parent_hash: None,
|
||||
sender
|
||||
sender,
|
||||
}
|
||||
});
|
||||
let future = run_manual_seal(
|
||||
ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
consensus_data_provider: None,
|
||||
}
|
||||
);
|
||||
let future = run_manual_seal(ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
consensus_data_provider: None,
|
||||
});
|
||||
std::thread::spawn(|| {
|
||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
// spawn the background authorship task
|
||||
@@ -380,27 +356,19 @@ mod tests {
|
||||
spawner.clone(),
|
||||
0,
|
||||
));
|
||||
let env = ProposerFactory::new(
|
||||
spawner.clone(),
|
||||
client.clone(),
|
||||
pool.clone(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None);
|
||||
// this test checks that blocks are created as soon as an engine command is sent over the stream.
|
||||
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
|
||||
let future = run_manual_seal(
|
||||
ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider: None,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
}
|
||||
);
|
||||
let future = run_manual_seal(ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider: None,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
});
|
||||
std::thread::spawn(|| {
|
||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
// spawn the background authorship task
|
||||
@@ -416,7 +384,9 @@ mod tests {
|
||||
sender: Some(tx),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
}).await.unwrap();
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let created_block = rx.await.unwrap().unwrap();
|
||||
|
||||
// assert that the background task returns ok
|
||||
@@ -439,8 +409,10 @@ mod tests {
|
||||
sink.send(EngineCommand::FinalizeBlock {
|
||||
sender: Some(tx),
|
||||
hash: header.hash(),
|
||||
justification: None
|
||||
}).await.unwrap();
|
||||
justification: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
// assert that the background task returns ok
|
||||
assert_eq!(rx.await.unwrap().unwrap(), ());
|
||||
}
|
||||
@@ -461,27 +433,19 @@ mod tests {
|
||||
spawner.clone(),
|
||||
0,
|
||||
));
|
||||
let env = ProposerFactory::new(
|
||||
spawner.clone(),
|
||||
client.clone(),
|
||||
pool.clone(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None);
|
||||
// this test checks that blocks are created as soon as an engine command is sent over the stream.
|
||||
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
|
||||
let future = run_manual_seal(
|
||||
ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider: None,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
}
|
||||
);
|
||||
let future = run_manual_seal(ManualSealParams {
|
||||
block_import: client.clone(),
|
||||
env,
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
commands_stream,
|
||||
select_chain,
|
||||
consensus_data_provider: None,
|
||||
create_inherent_data_providers: |_, _| async { Ok(()) },
|
||||
});
|
||||
std::thread::spawn(|| {
|
||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
// spawn the background authorship task
|
||||
@@ -498,7 +462,9 @@ mod tests {
|
||||
sender: Some(tx),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
}).await.unwrap();
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let created_block = rx.await.unwrap().unwrap();
|
||||
pool_api.increment_nonce(Alice.into());
|
||||
|
||||
@@ -524,31 +490,35 @@ mod tests {
|
||||
pool.maintain(sc_transaction_pool_api::ChainEvent::NewBestBlock {
|
||||
hash: header.hash(),
|
||||
tree_route: None,
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
|
||||
let (tx1, rx1) = futures::channel::oneshot::channel();
|
||||
assert!(sink.send(EngineCommand::SealNewBlock {
|
||||
parent_hash: Some(created_block.hash),
|
||||
sender: Some(tx1),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
}).await.is_ok());
|
||||
assert_matches::assert_matches!(
|
||||
rx1.await.expect("should be no error receiving"),
|
||||
Ok(_)
|
||||
);
|
||||
assert!(sink
|
||||
.send(EngineCommand::SealNewBlock {
|
||||
parent_hash: Some(created_block.hash),
|
||||
sender: Some(tx1),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
})
|
||||
.await
|
||||
.is_ok());
|
||||
assert_matches::assert_matches!(rx1.await.expect("should be no error receiving"), Ok(_));
|
||||
let block = client.block(&BlockId::Number(2)).unwrap().unwrap().block;
|
||||
pool_api.add_block(block, true);
|
||||
pool_api.increment_nonce(Alice.into());
|
||||
|
||||
assert!(pool.submit_one(&BlockId::Number(1), SOURCE, uxt(Bob, 0)).await.is_ok());
|
||||
let (tx2, rx2) = futures::channel::oneshot::channel();
|
||||
assert!(sink.send(EngineCommand::SealNewBlock {
|
||||
parent_hash: Some(created_block.hash),
|
||||
sender: Some(tx2),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
}).await.is_ok());
|
||||
assert!(sink
|
||||
.send(EngineCommand::SealNewBlock {
|
||||
parent_hash: Some(created_block.hash),
|
||||
sender: Some(tx2),
|
||||
create_empty: false,
|
||||
finalize: false,
|
||||
})
|
||||
.await
|
||||
.is_ok());
|
||||
let imported = rx2.await.unwrap().unwrap();
|
||||
// assert that fork block is in the db
|
||||
assert!(client.header(&BlockId::Hash(imported.hash)).unwrap().is_some())
|
||||
|
||||
@@ -18,18 +18,16 @@
|
||||
|
||||
//! RPC interface for the `ManualSeal` Engine.
|
||||
|
||||
use sp_consensus::ImportedAux;
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_derive::rpc;
|
||||
pub use self::gen_client::Client as ManualSealClient;
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
TryFutureExt,
|
||||
FutureExt,
|
||||
SinkExt
|
||||
FutureExt, SinkExt, TryFutureExt,
|
||||
};
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_derive::rpc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_consensus::ImportedAux;
|
||||
use sp_runtime::EncodedJustification;
|
||||
pub use self::gen_client::Client as ManualSealClient;
|
||||
|
||||
/// Future's type for jsonrpc
|
||||
type FutureResult<T> = Box<dyn jsonrpc_core::futures::Future<Item = T, Error = Error> + Send>;
|
||||
@@ -63,7 +61,7 @@ pub enum EngineCommand<Hash> {
|
||||
sender: Sender<()>,
|
||||
/// finalization justification
|
||||
justification: Option<EncodedJustification>,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/// RPC trait that provides methods for interacting with the manual-seal authorship task over rpc.
|
||||
@@ -75,7 +73,7 @@ pub trait ManualSealApi<Hash> {
|
||||
&self,
|
||||
create_empty: bool,
|
||||
finalize: bool,
|
||||
parent_hash: Option<Hash>
|
||||
parent_hash: Option<Hash>,
|
||||
) -> FutureResult<CreatedBlock<Hash>>;
|
||||
|
||||
/// Instructs the manual-seal authorship task to finalize a block
|
||||
@@ -83,7 +81,7 @@ pub trait ManualSealApi<Hash> {
|
||||
fn finalize_block(
|
||||
&self,
|
||||
hash: Hash,
|
||||
justification: Option<EncodedJustification>
|
||||
justification: Option<EncodedJustification>,
|
||||
) -> FutureResult<bool>;
|
||||
}
|
||||
|
||||
@@ -98,7 +96,7 @@ pub struct CreatedBlock<Hash> {
|
||||
/// hash of the created block.
|
||||
pub hash: Hash,
|
||||
/// some extra details about the import operation
|
||||
pub aux: ImportedAux
|
||||
pub aux: ImportedAux,
|
||||
}
|
||||
|
||||
impl<Hash> ManualSeal<Hash> {
|
||||
@@ -113,7 +111,7 @@ impl<Hash: Send + 'static> ManualSealApi<Hash> for ManualSeal<Hash> {
|
||||
&self,
|
||||
create_empty: bool,
|
||||
finalize: bool,
|
||||
parent_hash: Option<Hash>
|
||||
parent_hash: Option<Hash>,
|
||||
) -> FutureResult<CreatedBlock<Hash>> {
|
||||
let mut sink = self.import_block_channel.clone();
|
||||
let future = async move {
|
||||
@@ -126,18 +124,22 @@ impl<Hash: Send + 'static> ManualSealApi<Hash> for ManualSeal<Hash> {
|
||||
};
|
||||
sink.send(command).await?;
|
||||
receiver.await?
|
||||
}.boxed();
|
||||
}
|
||||
.boxed();
|
||||
|
||||
Box::new(future.map_err(Error::from).compat())
|
||||
}
|
||||
|
||||
fn finalize_block(&self, hash: Hash, justification: Option<EncodedJustification>) -> FutureResult<bool> {
|
||||
fn finalize_block(
|
||||
&self,
|
||||
hash: Hash,
|
||||
justification: Option<EncodedJustification>,
|
||||
) -> FutureResult<bool> {
|
||||
let mut sink = self.import_block_channel.clone();
|
||||
let future = async move {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
sink.send(
|
||||
EngineCommand::FinalizeBlock { hash, sender: Some(sender), justification }
|
||||
).await?;
|
||||
sink.send(EngineCommand::FinalizeBlock { hash, sender: Some(sender), justification })
|
||||
.await?;
|
||||
|
||||
receiver.await?.map(|_| true)
|
||||
};
|
||||
@@ -150,7 +152,7 @@ impl<Hash: Send + 'static> ManualSealApi<Hash> for ManualSeal<Hash> {
|
||||
/// to the rpc
|
||||
pub fn send_result<T: std::fmt::Debug>(
|
||||
sender: &mut Sender<T>,
|
||||
result: std::result::Result<T, crate::Error>
|
||||
result: std::result::Result<T, crate::Error>,
|
||||
) {
|
||||
if let Some(sender) = sender.take() {
|
||||
if let Err(err) = sender.send(result) {
|
||||
@@ -160,7 +162,7 @@ pub fn send_result<T: std::fmt::Debug>(
|
||||
// instant seal doesn't report errors over rpc, simply log them.
|
||||
match result {
|
||||
Ok(r) => log::info!("Instant Seal success: {:?}", r),
|
||||
Err(e) => log::error!("Instant Seal encountered an error: {}", e)
|
||||
Err(e) => log::error!("Instant Seal encountered an error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,21 @@
|
||||
|
||||
//! Block sealing utilities
|
||||
|
||||
use crate::{Error, rpc, CreatedBlock, ConsensusDataProvider};
|
||||
use std::sync::Arc;
|
||||
use sp_runtime::{
|
||||
traits::{Block as BlockT, Header as HeaderT},
|
||||
generic::BlockId,
|
||||
};
|
||||
use crate::{rpc, ConsensusDataProvider, CreatedBlock, Error};
|
||||
use futures::prelude::*;
|
||||
use sp_consensus::{
|
||||
self, BlockImport, Environment, Proposer, ForkChoiceStrategy,
|
||||
BlockImportParams, BlockOrigin, ImportResult, SelectChain, StateAction,
|
||||
};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use sp_inherents::{CreateInherentDataProviders, InherentDataProvider};
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
use sc_transaction_pool_api::TransactionPool;
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_consensus::{
|
||||
self, BlockImport, BlockImportParams, BlockOrigin, Environment, ForkChoiceStrategy,
|
||||
ImportResult, Proposer, SelectChain, StateAction,
|
||||
};
|
||||
use sp_inherents::{CreateInherentDataProviders, InherentDataProvider};
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, Header as HeaderT},
|
||||
};
|
||||
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||
|
||||
/// max duration for creating a proposal in secs
|
||||
pub const MAX_PROPOSAL_DURATION: u64 = 10;
|
||||
@@ -59,7 +57,8 @@ pub struct SealBlockParams<'a, B: BlockT, BI, SC, C: ProvideRuntimeApi<B>, E, TP
|
||||
/// SelectChain object
|
||||
pub select_chain: &'a SC,
|
||||
/// Digest provider for inclusion in blocks.
|
||||
pub consensus_data_provider: Option<&'a dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>,
|
||||
pub consensus_data_provider:
|
||||
Option<&'a dyn ConsensusDataProvider<B, Transaction = TransactionFor<C, B>>>,
|
||||
/// block import object
|
||||
pub block_import: &'a mut BI,
|
||||
/// Something that can create the inherent data providers.
|
||||
@@ -97,7 +96,7 @@ pub async fn seal_block<B, BI, SC, C, E, TP, CIDP>(
|
||||
{
|
||||
let future = async {
|
||||
if pool.status().ready == 0 && !create_empty {
|
||||
return Err(Error::EmptyTransactionPool);
|
||||
return Err(Error::EmptyTransactionPool)
|
||||
}
|
||||
|
||||
// get the header to build this new block on.
|
||||
@@ -129,12 +128,15 @@ pub async fn seal_block<B, BI, SC, C, E, TP, CIDP>(
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let proposal = proposer.propose(
|
||||
inherent_data.clone(),
|
||||
digest,
|
||||
Duration::from_secs(MAX_PROPOSAL_DURATION),
|
||||
None,
|
||||
).map_err(|err| Error::StringError(format!("{:?}", err))).await?;
|
||||
let proposal = proposer
|
||||
.propose(
|
||||
inherent_data.clone(),
|
||||
digest,
|
||||
Duration::from_secs(MAX_PROPOSAL_DURATION),
|
||||
None,
|
||||
)
|
||||
.map_err(|err| Error::StringError(format!("{:?}", err)))
|
||||
.await?;
|
||||
|
||||
if proposal.block.extrinsics().len() == inherents_len && !create_empty {
|
||||
return Err(Error::EmptyTransactionPool)
|
||||
@@ -145,18 +147,17 @@ pub async fn seal_block<B, BI, SC, C, E, TP, CIDP>(
|
||||
params.body = Some(body);
|
||||
params.finalized = finalize;
|
||||
params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
|
||||
params.state_action = StateAction::ApplyChanges(
|
||||
sp_consensus::StorageChanges::Changes(proposal.storage_changes)
|
||||
);
|
||||
params.state_action = StateAction::ApplyChanges(sp_consensus::StorageChanges::Changes(
|
||||
proposal.storage_changes,
|
||||
));
|
||||
|
||||
if let Some(digest_provider) = digest_provider {
|
||||
digest_provider.append_block_import(&parent, &mut params, &inherent_data)?;
|
||||
}
|
||||
|
||||
match block_import.import_block(params, HashMap::new()).await? {
|
||||
ImportResult::Imported(aux) => {
|
||||
Ok(CreatedBlock { hash: <B as BlockT>::Header::hash(&header), aux })
|
||||
},
|
||||
ImportResult::Imported(aux) =>
|
||||
Ok(CreatedBlock { hash: <B as BlockT>::Header::hash(&header), aux }),
|
||||
other => Err(other.into()),
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user