mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 14:11:09 +00:00
consensus: handle justification sync for blocks authored locally (#8698)
* consensus: add trait to control justification sync process * network: implement JustificationSyncLink for NetworkService * slots: handle justification sync in slot worker * babe: fix slot worker instantiation * aura: fix slot worker instantiation * pow: handle justification sync in miner * babe: fix tests * aura: fix tests * node: fix compilation * node-template: fix compilation * consensus: rename justification sync link parameter * aura: fix test compilation * consensus: slots: move JustificationSyncLink out of on_slot
This commit is contained in:
@@ -220,7 +220,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
|
||||
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
|
||||
let raw_slot_duration = slot_duration.slot_duration();
|
||||
|
||||
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _>(
|
||||
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>(
|
||||
StartAuraParams {
|
||||
slot_duration,
|
||||
client: client.clone(),
|
||||
@@ -243,6 +243,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
|
||||
keystore: keystore_container.sync_keystore(),
|
||||
can_author_with,
|
||||
sync_oracle: network.clone(),
|
||||
justification_sync_link: network.clone(),
|
||||
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
},
|
||||
|
||||
@@ -308,6 +308,7 @@ pub fn new_full_base(
|
||||
env: proposer,
|
||||
block_import,
|
||||
sync_oracle: network.clone(),
|
||||
justification_sync_link: network.clone(),
|
||||
create_inherent_data_providers: move |parent, ()| {
|
||||
let client_clone = client_clone.clone();
|
||||
async move {
|
||||
|
||||
@@ -109,7 +109,7 @@ fn slot_author<P: Pair>(slot: Slot, authorities: &[AuthorityId<P>]) -> Option<&A
|
||||
}
|
||||
|
||||
/// Parameters of [`start_aura`].
|
||||
pub struct StartAuraParams<C, SC, I, PF, SO, BS, CAW, IDP> {
|
||||
pub struct StartAuraParams<C, SC, I, PF, SO, L, CIDP, BS, CAW> {
|
||||
/// The duration of a slot.
|
||||
pub slot_duration: SlotDuration,
|
||||
/// The client to interact with the chain.
|
||||
@@ -122,8 +122,10 @@ pub struct StartAuraParams<C, SC, I, PF, SO, BS, CAW, IDP> {
|
||||
pub proposer_factory: PF,
|
||||
/// The sync oracle that can give us the current sync status.
|
||||
pub sync_oracle: SO,
|
||||
/// Hook into the sync module to control the justification sync process.
|
||||
pub justification_sync_link: L,
|
||||
/// Something that can create the inherent data providers.
|
||||
pub create_inherent_data_providers: IDP,
|
||||
pub create_inherent_data_providers: CIDP,
|
||||
/// Should we force the authoring of blocks?
|
||||
pub force_authoring: bool,
|
||||
/// The backoff strategy when we miss slots.
|
||||
@@ -143,7 +145,7 @@ pub struct StartAuraParams<C, SC, I, PF, SO, BS, CAW, IDP> {
|
||||
}
|
||||
|
||||
/// Start the aura worker. The returned future should be run in a futures executor.
|
||||
pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error, IDP>(
|
||||
pub fn start_aura<P, B, C, SC, I, PF, SO, L, CIDP, BS, CAW, Error>(
|
||||
StartAuraParams {
|
||||
slot_duration,
|
||||
client,
|
||||
@@ -151,6 +153,7 @@ pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error, IDP>(
|
||||
block_import,
|
||||
proposer_factory,
|
||||
sync_oracle,
|
||||
justification_sync_link,
|
||||
create_inherent_data_providers,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
@@ -158,31 +161,33 @@ pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error, IDP>(
|
||||
can_author_with,
|
||||
block_proposal_slot_portion,
|
||||
telemetry,
|
||||
}: StartAuraParams<C, SC, I, PF, SO, BS, CAW, IDP>,
|
||||
}: StartAuraParams<C, SC, I, PF, SO, L, CIDP, BS, CAW>,
|
||||
) -> Result<impl Future<Output = ()>, sp_consensus::Error> where
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
B: BlockT,
|
||||
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + AuxStore + HeaderBackend<B> + Send + Sync,
|
||||
C::Api: AuraApi<B, AuthorityId<P>>,
|
||||
SC: SelectChain<B>,
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
|
||||
PF: Environment<B, Error = Error> + Send + Sync + 'static,
|
||||
PF::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone,
|
||||
CAW: CanAuthorWith<B> + Send,
|
||||
L: sp_consensus::JustificationSyncLink<B>,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + Send,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
|
||||
IDP: CreateInherentDataProviders<B, ()> + Send,
|
||||
IDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
CAW: CanAuthorWith<B> + Send,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
{
|
||||
let worker = build_aura_worker::<P, _, _, _, _, _, _, _>(BuildAuraWorkerParams {
|
||||
let worker = build_aura_worker::<P, _, _, _, _, _, _, _, _>(BuildAuraWorkerParams {
|
||||
client: client.clone(),
|
||||
block_import,
|
||||
proposer_factory,
|
||||
keystore,
|
||||
sync_oracle: sync_oracle.clone(),
|
||||
justification_sync_link,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
telemetry,
|
||||
@@ -200,7 +205,7 @@ pub fn start_aura<P, B, C, SC, PF, I, SO, CAW, BS, Error, IDP>(
|
||||
}
|
||||
|
||||
/// Parameters of [`build_aura_worker`].
|
||||
pub struct BuildAuraWorkerParams<C, I, PF, SO, BS> {
|
||||
pub struct BuildAuraWorkerParams<C, I, PF, SO, L, BS> {
|
||||
/// The client to interact with the chain.
|
||||
pub client: Arc<C>,
|
||||
/// The block import.
|
||||
@@ -209,6 +214,8 @@ pub struct BuildAuraWorkerParams<C, I, PF, SO, BS> {
|
||||
pub proposer_factory: PF,
|
||||
/// The sync oracle that can give us the current sync status.
|
||||
pub sync_oracle: SO,
|
||||
/// Hook into the sync module to control the justification sync process.
|
||||
pub justification_sync_link: L,
|
||||
/// Should we force the authoring of blocks?
|
||||
pub force_authoring: bool,
|
||||
/// The backoff strategy when we miss slots.
|
||||
@@ -228,18 +235,19 @@ pub struct BuildAuraWorkerParams<C, I, PF, SO, BS> {
|
||||
/// Build the aura worker.
|
||||
///
|
||||
/// The caller is responsible for running this worker, otherwise it will do nothing.
|
||||
pub fn build_aura_worker<P, B, C, PF, I, SO, BS, Error>(
|
||||
pub fn build_aura_worker<P, B, C, PF, I, SO, L, BS, Error>(
|
||||
BuildAuraWorkerParams {
|
||||
client,
|
||||
block_import,
|
||||
proposer_factory,
|
||||
sync_oracle,
|
||||
justification_sync_link,
|
||||
backoff_authoring_blocks,
|
||||
keystore,
|
||||
block_proposal_slot_portion,
|
||||
telemetry,
|
||||
force_authoring,
|
||||
}: BuildAuraWorkerParams<C, I, PF, SO, BS>,
|
||||
}: BuildAuraWorkerParams<C, I, PF, SO, L, BS>,
|
||||
) -> impl sc_consensus_slots::SlotWorker<B, <PF::Proposer as Proposer<B>>::Proof> where
|
||||
B: BlockT,
|
||||
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + AuxStore + HeaderBackend<B> + Send + Sync,
|
||||
@@ -252,6 +260,7 @@ pub fn build_aura_worker<P, B, C, PF, I, SO, BS, Error>(
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone,
|
||||
L: sp_consensus::JustificationSyncLink<B>,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
|
||||
{
|
||||
AuraWorker {
|
||||
@@ -260,6 +269,7 @@ pub fn build_aura_worker<P, B, C, PF, I, SO, BS, Error>(
|
||||
env: proposer_factory,
|
||||
keystore,
|
||||
sync_oracle,
|
||||
justification_sync_link,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
telemetry,
|
||||
@@ -268,12 +278,13 @@ pub fn build_aura_worker<P, B, C, PF, I, SO, BS, Error>(
|
||||
}
|
||||
}
|
||||
|
||||
struct AuraWorker<C, E, I, P, SO, BS> {
|
||||
struct AuraWorker<C, E, I, P, SO, L, BS> {
|
||||
client: Arc<C>,
|
||||
block_import: I,
|
||||
env: E,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
sync_oracle: SO,
|
||||
justification_sync_link: L,
|
||||
force_authoring: bool,
|
||||
backoff_authoring_blocks: Option<BS>,
|
||||
block_proposal_slot_portion: SlotProportion,
|
||||
@@ -281,8 +292,8 @@ struct AuraWorker<C, E, I, P, SO, BS> {
|
||||
_key_type: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<B, C, E, I, P, Error, SO, BS> sc_consensus_slots::SimpleSlotWorker<B>
|
||||
for AuraWorker<C, E, I, P, SO, BS>
|
||||
impl<B, C, E, I, P, Error, SO, L, BS> sc_consensus_slots::SimpleSlotWorker<B>
|
||||
for AuraWorker<C, E, I, P, SO, L, BS>
|
||||
where
|
||||
B: BlockT,
|
||||
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + HeaderBackend<B> + Sync,
|
||||
@@ -294,11 +305,13 @@ where
|
||||
P::Public: AppPublic + Public + Member + Encode + Decode + Hash,
|
||||
P::Signature: TryFrom<Vec<u8>> + Member + Encode + Decode + Hash + Debug,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
L: sp_consensus::JustificationSyncLink<B>,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
{
|
||||
type BlockImport = I;
|
||||
type SyncOracle = SO;
|
||||
type JustificationSyncLink = L;
|
||||
type CreateProposer = Pin<Box<
|
||||
dyn Future<Output = Result<E::Proposer, sp_consensus::Error>> + Send + 'static
|
||||
>>;
|
||||
@@ -425,6 +438,10 @@ where
|
||||
&mut self.sync_oracle
|
||||
}
|
||||
|
||||
fn justification_sync_link(&mut self) -> &mut Self::JustificationSyncLink {
|
||||
&mut self.justification_sync_link
|
||||
}
|
||||
|
||||
fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer {
|
||||
Box::pin(self.env.init(block).map_err(|e| {
|
||||
sp_consensus::Error::ClientImport(format!("{:?}", e)).into()
|
||||
@@ -725,13 +742,14 @@ mod tests {
|
||||
|
||||
let slot_duration = slot_duration(&*client).expect("slot duration available");
|
||||
|
||||
aura_futures.push(start_aura::<AuthorityPair, _, _, _, _, _, _, _, _, _, _>(StartAuraParams {
|
||||
aura_futures.push(start_aura::<AuthorityPair, _, _, _, _, _, _, _, _, _, _, _>(StartAuraParams {
|
||||
slot_duration,
|
||||
block_import: client.clone(),
|
||||
select_chain,
|
||||
client,
|
||||
proposer_factory: environ,
|
||||
sync_oracle: DummyOracle,
|
||||
justification_sync_link: (),
|
||||
create_inherent_data_providers: |_, _| async {
|
||||
let timestamp = TimestampInherentDataProvider::from_system_time();
|
||||
let slot = InherentDataProvider::from_timestamp_and_duration(
|
||||
@@ -804,6 +822,7 @@ mod tests {
|
||||
env: environ,
|
||||
keystore: keystore.into(),
|
||||
sync_oracle: DummyOracle.clone(),
|
||||
justification_sync_link: (),
|
||||
force_authoring: false,
|
||||
backoff_authoring_blocks: Some(BackoffAuthoringOnFinalizedHeadLagging::default()),
|
||||
telemetry: None,
|
||||
@@ -853,6 +872,7 @@ mod tests {
|
||||
env: environ,
|
||||
keystore: keystore.into(),
|
||||
sync_oracle: DummyOracle.clone(),
|
||||
justification_sync_link: (),
|
||||
force_authoring: false,
|
||||
backoff_authoring_blocks: Option::<()>::None,
|
||||
telemetry: None,
|
||||
@@ -871,7 +891,7 @@ mod tests {
|
||||
duration: Duration::from_millis(1000),
|
||||
chain_head: head,
|
||||
block_size_limit: None,
|
||||
},
|
||||
}
|
||||
)).unwrap();
|
||||
|
||||
// The returned block should be imported and we should be able to get its header by now.
|
||||
|
||||
@@ -363,7 +363,7 @@ impl std::ops::Deref for Config {
|
||||
}
|
||||
|
||||
/// Parameters for BABE.
|
||||
pub struct BabeParams<B: BlockT, C, E, I, SO, SC, CAW, BS, IDP> {
|
||||
pub struct BabeParams<B: BlockT, C, SC, E, I, SO, L, CIDP, BS, CAW> {
|
||||
/// The keystore that manages the keys of the node.
|
||||
pub keystore: SyncCryptoStorePtr,
|
||||
|
||||
@@ -384,8 +384,11 @@ pub struct BabeParams<B: BlockT, C, E, I, SO, SC, CAW, BS, IDP> {
|
||||
/// A sync oracle
|
||||
pub sync_oracle: SO,
|
||||
|
||||
/// Hook into the sync module to control the justification sync process.
|
||||
pub justification_sync_link: L,
|
||||
|
||||
/// Something that can create the inherent data providers.
|
||||
pub create_inherent_data_providers: IDP,
|
||||
pub create_inherent_data_providers: CIDP,
|
||||
|
||||
/// Force authoring of blocks even if we are offline
|
||||
pub force_authoring: bool,
|
||||
@@ -411,13 +414,14 @@ pub struct BabeParams<B: BlockT, C, E, I, SO, SC, CAW, BS, IDP> {
|
||||
}
|
||||
|
||||
/// Start the babe worker.
|
||||
pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error, IDP>(BabeParams {
|
||||
pub fn start_babe<B, C, SC, E, I, SO, CIDP, BS, CAW, L, Error>(BabeParams {
|
||||
keystore,
|
||||
client,
|
||||
select_chain,
|
||||
env,
|
||||
block_import,
|
||||
sync_oracle,
|
||||
justification_sync_link,
|
||||
create_inherent_data_providers,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
@@ -425,26 +429,35 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error, IDP>(BabeParams {
|
||||
can_author_with,
|
||||
block_proposal_slot_portion,
|
||||
telemetry,
|
||||
}: BabeParams<B, C, E, I, SO, SC, CAW, BS, IDP>) -> Result<
|
||||
}: BabeParams<B, C, SC, E, I, SO, L, CIDP, BS, CAW>) -> Result<
|
||||
BabeWorker<B>,
|
||||
sp_consensus::Error,
|
||||
> where
|
||||
B: BlockT,
|
||||
C: ProvideRuntimeApi<B> + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
|
||||
+ HeaderBackend<B> + HeaderMetadata<B, Error = ClientError>
|
||||
+ Send + Sync + 'static,
|
||||
C: ProvideRuntimeApi<B>
|
||||
+ ProvideCache<B>
|
||||
+ ProvideUncles<B>
|
||||
+ BlockchainEvents<B>
|
||||
+ HeaderBackend<B>
|
||||
+ HeaderMetadata<B, Error = ClientError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
C::Api: BabeApi<B>,
|
||||
SC: SelectChain<B> + 'static,
|
||||
E: Environment<B, Error = Error> + Send + Sync + 'static,
|
||||
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
|
||||
I: BlockImport<B, Error = ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send
|
||||
+ Sync + 'static,
|
||||
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
|
||||
I: BlockImport<B, Error = ConsensusError, Transaction = sp_api::TransactionFor<C, B>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone + 'static,
|
||||
CAW: CanAuthorWith<B> + Send + Sync + 'static,
|
||||
L: sp_consensus::JustificationSyncLink<B> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + Send + Sync + 'static,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
|
||||
IDP: CreateInherentDataProviders<B, ()> + Send + Sync + 'static,
|
||||
IDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
CAW: CanAuthorWith<B> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
|
||||
{
|
||||
const HANDLE_BUFFER_SIZE: usize = 1024;
|
||||
|
||||
@@ -456,6 +469,7 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error, IDP>(BabeParams {
|
||||
block_import,
|
||||
env,
|
||||
sync_oracle: sync_oracle.clone(),
|
||||
justification_sync_link,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
keystore,
|
||||
@@ -600,11 +614,12 @@ type SlotNotificationSinks<B> = Arc<
|
||||
Mutex<Vec<Sender<(Slot, ViableEpochDescriptor<<B as BlockT>::Hash, NumberFor<B>, Epoch>)>>>
|
||||
>;
|
||||
|
||||
struct BabeSlotWorker<B: BlockT, C, E, I, SO, BS> {
|
||||
struct BabeSlotWorker<B: BlockT, C, E, I, SO, L, BS> {
|
||||
client: Arc<C>,
|
||||
block_import: I,
|
||||
env: E,
|
||||
sync_oracle: SO,
|
||||
justification_sync_link: L,
|
||||
force_authoring: bool,
|
||||
backoff_authoring_blocks: Option<BS>,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
@@ -615,8 +630,8 @@ struct BabeSlotWorker<B: BlockT, C, E, I, SO, BS> {
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
}
|
||||
|
||||
impl<B, C, E, I, Error, SO, BS> sc_consensus_slots::SimpleSlotWorker<B>
|
||||
for BabeSlotWorker<B, C, E, I, SO, BS>
|
||||
impl<B, C, E, I, Error, SO, L, BS> sc_consensus_slots::SimpleSlotWorker<B>
|
||||
for BabeSlotWorker<B, C, E, I, SO, L, BS>
|
||||
where
|
||||
B: BlockT,
|
||||
C: ProvideRuntimeApi<B> +
|
||||
@@ -628,12 +643,14 @@ where
|
||||
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
|
||||
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
L: sp_consensus::JustificationSyncLink<B>,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>>,
|
||||
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
|
||||
{
|
||||
type EpochData = ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>;
|
||||
type Claim = (PreDigest, AuthorityId);
|
||||
type SyncOracle = SO;
|
||||
type JustificationSyncLink = L;
|
||||
type CreateProposer = Pin<Box<
|
||||
dyn Future<Output = Result<E::Proposer, sp_consensus::Error>> + Send + 'static
|
||||
>>;
|
||||
@@ -798,6 +815,10 @@ where
|
||||
&mut self.sync_oracle
|
||||
}
|
||||
|
||||
fn justification_sync_link(&mut self) -> &mut Self::JustificationSyncLink {
|
||||
&mut self.justification_sync_link
|
||||
}
|
||||
|
||||
fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer {
|
||||
Box::pin(self.env.init(block).map_err(|e| {
|
||||
sp_consensus::Error::ClientImport(format!("{:?}", e))
|
||||
|
||||
@@ -390,9 +390,7 @@ fn rejects_empty_block() {
|
||||
})
|
||||
}
|
||||
|
||||
fn run_one_test(
|
||||
mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static,
|
||||
) {
|
||||
fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static) {
|
||||
sp_tracing::try_init_simple();
|
||||
let mutator = Arc::new(mutator) as Mutator;
|
||||
|
||||
@@ -473,6 +471,7 @@ fn run_one_test(
|
||||
babe_link: data.link.clone(),
|
||||
keystore,
|
||||
can_author_with: sp_consensus::AlwaysCanAuthor,
|
||||
justification_sync_link: (),
|
||||
block_proposal_slot_portion: SlotProportion::new(0.5),
|
||||
telemetry: None,
|
||||
}).expect("Starts babe"));
|
||||
|
||||
@@ -527,20 +527,21 @@ 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, CIDP>(
|
||||
pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, L, CIDP, CAW>(
|
||||
block_import: BoxBlockImport<Block, sp_api::TransactionFor<C, Block>>,
|
||||
client: Arc<C>,
|
||||
select_chain: S,
|
||||
algorithm: Algorithm,
|
||||
mut env: E,
|
||||
mut sync_oracle: SO,
|
||||
justification_sync_link: L,
|
||||
pre_runtime: Option<Vec<u8>>,
|
||||
create_inherent_data_providers: CIDP,
|
||||
timeout: Duration,
|
||||
build_time: Duration,
|
||||
can_author_with: CAW,
|
||||
) -> (
|
||||
Arc<Mutex<MiningWorker<Block, Algorithm, C, <E::Proposer as Proposer<Block>>::Proof>>>,
|
||||
Arc<Mutex<MiningWorker<Block, Algorithm, C, L, <E::Proposer as Proposer<Block>>::Proof>>>,
|
||||
impl Future<Output = ()>,
|
||||
) where
|
||||
Block: BlockT,
|
||||
@@ -552,14 +553,16 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW, CIDP>(
|
||||
E::Error: std::fmt::Debug,
|
||||
E::Proposer: Proposer<Block, Transaction = sp_api::TransactionFor<C, Block>>,
|
||||
SO: SyncOracle + Clone + Send + Sync + 'static,
|
||||
CAW: CanAuthorWith<Block> + Clone + Send + 'static,
|
||||
L: sp_consensus::JustificationSyncLink<Block>,
|
||||
CIDP: CreateInherentDataProviders<Block, ()>,
|
||||
CAW: CanAuthorWith<Block> + Clone + Send + 'static,
|
||||
{
|
||||
let mut timer = UntilImportedOrTimeout::new(client.import_notification_stream(), timeout);
|
||||
let worker = Arc::new(Mutex::new(MiningWorker::<Block, Algorithm, C, _> {
|
||||
let worker = Arc::new(Mutex::new(MiningWorker {
|
||||
build: None,
|
||||
algorithm: algorithm.clone(),
|
||||
block_import,
|
||||
justification_sync_link,
|
||||
}));
|
||||
let worker_ret = worker.clone();
|
||||
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
|
||||
use std::{pin::Pin, time::Duration, collections::HashMap, borrow::Cow};
|
||||
use sc_client_api::ImportNotifications;
|
||||
use sp_runtime::{DigestItem, traits::Block as BlockT, generic::BlockId};
|
||||
use sp_consensus::{Proposal, BlockOrigin, BlockImportParams, import_queue::BoxBlockImport};
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, Header as HeaderT},
|
||||
DigestItem,
|
||||
};
|
||||
use futures::{prelude::*, task::{Context, Poll}};
|
||||
use futures_timer::Delay;
|
||||
use log::*;
|
||||
@@ -57,18 +61,22 @@ pub struct MiningWorker<
|
||||
Block: BlockT,
|
||||
Algorithm: PowAlgorithm<Block>,
|
||||
C: sp_api::ProvideRuntimeApi<Block>,
|
||||
Proof
|
||||
L: sp_consensus::JustificationSyncLink<Block>,
|
||||
Proof,
|
||||
> {
|
||||
pub(crate) build: Option<MiningBuild<Block, Algorithm, C, Proof>>,
|
||||
pub(crate) algorithm: Algorithm,
|
||||
pub(crate) block_import: BoxBlockImport<Block, sp_api::TransactionFor<C, Block>>,
|
||||
pub(crate) justification_sync_link: L,
|
||||
}
|
||||
|
||||
impl<Block, Algorithm, C, Proof> MiningWorker<Block, Algorithm, C, Proof> where
|
||||
impl<Block, Algorithm, C, L, Proof> MiningWorker<Block, Algorithm, C, L, Proof>
|
||||
where
|
||||
Block: BlockT,
|
||||
C: sp_api::ProvideRuntimeApi<Block>,
|
||||
Algorithm: PowAlgorithm<Block>,
|
||||
Algorithm::Difficulty: 'static + Send,
|
||||
L: sp_consensus::JustificationSyncLink<Block>,
|
||||
sp_api::TransactionFor<C, Block>: Send + 'static,
|
||||
{
|
||||
/// Get the current best hash. `None` if the worker has just started or the client is doing
|
||||
@@ -139,8 +147,11 @@ impl<Block, Algorithm, C, Proof> MiningWorker<Block, Algorithm, C, Proof> where
|
||||
Box::new(intermediate) as Box<_>,
|
||||
);
|
||||
|
||||
let header = import_block.post_header();
|
||||
match self.block_import.import_block(import_block, HashMap::default()).await {
|
||||
Ok(_) => {
|
||||
Ok(res) => {
|
||||
res.handle_justification(&header.hash(), *header.number(), &mut self.justification_sync_link);
|
||||
|
||||
info!(
|
||||
target: "pow",
|
||||
"✅ Successfully mined block on top of: {}",
|
||||
|
||||
@@ -39,7 +39,9 @@ use futures_timer::Delay;
|
||||
use log::{debug, error, info, warn};
|
||||
use sp_api::{ProvideRuntimeApi, ApiRef};
|
||||
use sp_arithmetic::traits::BaseArithmetic;
|
||||
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData};
|
||||
use sp_consensus::{
|
||||
BlockImport, CanAuthorWith, JustificationSyncLink, Proposer, SelectChain, SlotData, SyncOracle,
|
||||
};
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_inherents::CreateInherentDataProviders;
|
||||
use sp_runtime::{
|
||||
@@ -92,6 +94,10 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
/// A handle to a `SyncOracle`.
|
||||
type SyncOracle: SyncOracle;
|
||||
|
||||
/// A handle to a `JustificationSyncLink`, allows hooking into the sync module to control the
|
||||
/// justification sync process.
|
||||
type JustificationSyncLink: JustificationSyncLink<B>;
|
||||
|
||||
/// The type of future resolving to the proposer.
|
||||
type CreateProposer: Future<Output = Result<Self::Proposer, sp_consensus::Error>>
|
||||
+ Send + Unpin + 'static;
|
||||
@@ -178,6 +184,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
/// Returns a handle to a `SyncOracle`.
|
||||
fn sync_oracle(&mut self) -> &mut Self::SyncOracle;
|
||||
|
||||
/// Returns a handle to a `JustificationSyncLink`.
|
||||
fn justification_sync_link(&mut self) -> &mut Self::JustificationSyncLink;
|
||||
|
||||
/// Returns a `Proposer` to author on top of the given block.
|
||||
fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer;
|
||||
|
||||
@@ -392,27 +401,37 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
);
|
||||
|
||||
let header = block_import_params.post_header();
|
||||
if let Err(err) = block_import
|
||||
match block_import
|
||||
.import_block(block_import_params, Default::default())
|
||||
.await
|
||||
{
|
||||
warn!(
|
||||
target: logging_target,
|
||||
"Error with block built on {:?}: {:?}",
|
||||
parent_hash,
|
||||
err,
|
||||
);
|
||||
Ok(res) => {
|
||||
res.handle_justification(
|
||||
&header.hash(),
|
||||
*header.number(),
|
||||
self.justification_sync_link(),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: logging_target,
|
||||
"Error with block built on {:?}: {:?}", parent_hash, err,
|
||||
);
|
||||
|
||||
telemetry!(
|
||||
telemetry;
|
||||
CONSENSUS_WARN;
|
||||
"slots.err_with_block_built_on";
|
||||
"hash" => ?parent_hash,
|
||||
"err" => ?err,
|
||||
);
|
||||
telemetry!(
|
||||
telemetry;
|
||||
CONSENSUS_WARN;
|
||||
"slots.err_with_block_built_on";
|
||||
"hash" => ?parent_hash,
|
||||
"err" => ?err,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Some(SlotResult { block: B::new(header, body), storage_proof })
|
||||
Some(SlotResult {
|
||||
block: B::new(header, body),
|
||||
storage_proof,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +500,7 @@ where
|
||||
///
|
||||
/// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is
|
||||
/// polled until completion, unless we are major syncing.
|
||||
pub async fn start_slot_worker<B, C, W, T, SO, CAW, CIDP, Proof>(
|
||||
pub async fn start_slot_worker<B, C, W, T, SO, CIDP, CAW, Proof>(
|
||||
slot_duration: SlotDuration<T>,
|
||||
client: C,
|
||||
mut worker: W,
|
||||
@@ -495,9 +514,9 @@ where
|
||||
W: SlotWorker<B, Proof>,
|
||||
SO: SyncOracle + Send,
|
||||
T: SlotData + Clone,
|
||||
CAW: CanAuthorWith<B> + Send,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + Send,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
CAW: CanAuthorWith<B> + Send,
|
||||
{
|
||||
let SlotDuration(slot_duration) = slot_duration;
|
||||
|
||||
|
||||
@@ -966,6 +966,11 @@ impl<B: BlockT> Protocol<B> {
|
||||
self.sync.request_justification(&hash, number)
|
||||
}
|
||||
|
||||
/// Clear all pending justification requests.
|
||||
pub fn clear_justification_requests(&mut self) {
|
||||
self.sync.clear_justification_requests();
|
||||
}
|
||||
|
||||
/// Request syncing for the given block from given set of peers.
|
||||
/// Uses `protocol` to queue a new block download request and tries to dispatch all pending
|
||||
/// requests.
|
||||
|
||||
@@ -632,6 +632,11 @@ impl<B: BlockT> ChainSync<B> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Clear all pending justification requests.
|
||||
pub fn clear_justification_requests(&mut self) {
|
||||
self.extra_justifications.reset();
|
||||
}
|
||||
|
||||
/// Request syncing for the given block from given set of peers.
|
||||
// The implementation is similar to on_block_announce with unknown parent hash.
|
||||
pub fn set_sync_fork_request(
|
||||
@@ -1117,7 +1122,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
number,
|
||||
hash
|
||||
);
|
||||
self.extra_justifications.reset()
|
||||
self.clear_justification_requests();
|
||||
}
|
||||
|
||||
if aux.needs_justification {
|
||||
|
||||
@@ -976,6 +976,13 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkService<B, H> {
|
||||
.unbounded_send(ServiceToWorkerMsg::RequestJustification(*hash, number));
|
||||
}
|
||||
|
||||
/// Clear all pending justification requests.
|
||||
pub fn clear_justification_requests(&self) {
|
||||
let _ = self
|
||||
.to_worker
|
||||
.unbounded_send(ServiceToWorkerMsg::ClearJustificationRequests);
|
||||
}
|
||||
|
||||
/// Are we in the process of downloading the chain?
|
||||
pub fn is_major_syncing(&self) -> bool {
|
||||
self.is_major_syncing.load(Ordering::Relaxed)
|
||||
@@ -1219,6 +1226,16 @@ impl<'a, B: BlockT + 'static, H: ExHashT> sp_consensus::SyncOracle
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, H: ExHashT> sp_consensus::JustificationSyncLink<B> for NetworkService<B, H> {
|
||||
fn request_justification(&self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
NetworkService::request_justification(self, hash, number);
|
||||
}
|
||||
|
||||
fn clear_justification_requests(&self) {
|
||||
NetworkService::clear_justification_requests(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, H> NetworkStateInfo for NetworkService<B, H>
|
||||
where
|
||||
B: sp_runtime::traits::Block,
|
||||
@@ -1323,6 +1340,7 @@ enum ServiceToWorkerMsg<B: BlockT, H: ExHashT> {
|
||||
PropagateTransaction(H),
|
||||
PropagateTransactions,
|
||||
RequestJustification(B::Hash, NumberFor<B>),
|
||||
ClearJustificationRequests,
|
||||
AnnounceBlock(B::Hash, Option<Vec<u8>>),
|
||||
GetValue(record::Key),
|
||||
PutValue(record::Key, Vec<u8>),
|
||||
@@ -1444,6 +1462,8 @@ impl<B: BlockT + 'static, H: ExHashT> Future for NetworkWorker<B, H> {
|
||||
this.network_service.behaviour_mut().user_protocol_mut().announce_block(hash, data),
|
||||
ServiceToWorkerMsg::RequestJustification(hash, number) =>
|
||||
this.network_service.behaviour_mut().user_protocol_mut().request_justification(&hash, number),
|
||||
ServiceToWorkerMsg::ClearJustificationRequests =>
|
||||
this.network_service.behaviour_mut().user_protocol_mut().clear_justification_requests(),
|
||||
ServiceToWorkerMsg::PropagateTransaction(hash) =>
|
||||
this.tx_handler_controller.propagate_transaction(hash),
|
||||
ServiceToWorkerMsg::PropagateTransactions =>
|
||||
|
||||
@@ -68,6 +68,30 @@ impl ImportResult {
|
||||
|
||||
ImportResult::Imported(aux)
|
||||
}
|
||||
|
||||
/// Handles any necessary request for justifications (or clearing of pending requests) based on
|
||||
/// the outcome of this block import.
|
||||
pub fn handle_justification<B>(
|
||||
&self,
|
||||
hash: &B::Hash,
|
||||
number: NumberFor<B>,
|
||||
justification_sync_link: &mut dyn JustificationSyncLink<B>,
|
||||
) where
|
||||
B: BlockT,
|
||||
{
|
||||
match self {
|
||||
ImportResult::Imported(aux) => {
|
||||
if aux.clear_justification_requests {
|
||||
justification_sync_link.clear_justification_requests();
|
||||
}
|
||||
|
||||
if aux.needs_justification {
|
||||
justification_sync_link.request_justification(hash, number);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Block data origin.
|
||||
@@ -354,3 +378,32 @@ pub trait JustificationImport<B: BlockT> {
|
||||
justification: Justification,
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
/// Control the synchronization process of block justifications.
|
||||
///
|
||||
/// When importing blocks different consensus engines might require that
|
||||
/// additional finality data is provided (i.e. a justification for the block).
|
||||
/// This trait abstracts the required methods to issue those requests
|
||||
pub trait JustificationSyncLink<B: BlockT>: Send + Sync {
|
||||
/// Request a justification for the given block.
|
||||
fn request_justification(&self, hash: &B::Hash, number: NumberFor<B>);
|
||||
|
||||
/// Clear all pending justification requests.
|
||||
fn clear_justification_requests(&self);
|
||||
}
|
||||
|
||||
impl<B: BlockT> JustificationSyncLink<B> for () {
|
||||
fn request_justification(&self, _hash: &B::Hash, _number: NumberFor<B>) {}
|
||||
|
||||
fn clear_justification_requests(&self) {}
|
||||
}
|
||||
|
||||
impl<B: BlockT, L: JustificationSyncLink<B>> JustificationSyncLink<B> for Arc<L> {
|
||||
fn request_justification(&self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
L::request_justification(&*self, hash, number);
|
||||
}
|
||||
|
||||
fn clear_justification_requests(&self) {
|
||||
L::clear_justification_requests(&*self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ mod metrics;
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use block_import::{
|
||||
BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams,
|
||||
ImportResult, JustificationImport,
|
||||
BlockCheckParams, BlockImport, BlockImportParams, BlockOrigin, ForkChoiceStrategy,
|
||||
ImportResult, ImportedAux, JustificationImport, JustificationSyncLink,
|
||||
};
|
||||
pub use select_chain::SelectChain;
|
||||
pub use sp_state_machine::Backend as StateBackend;
|
||||
|
||||
Reference in New Issue
Block a user