// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
//! The block production pipeline of Polkadot.
//!
//! The `ProposerFactory` exported by this module will be wrapped by some
//! consensus engine, and triggered when it is time to create a block.
use std::{
pin::Pin,
sync::Arc,
time::{self, Duration, Instant},
};
use sp_blockchain::HeaderBackend;
use block_builder::{BlockBuilderApi, BlockBuilderProvider};
use consensus::{Proposal, RecordProof};
use polkadot_primitives::{Block, Header};
use polkadot_primitives::parachain::{
ParachainHost, NEW_HEADS_IDENTIFIER,
};
use runtime_primitives::traits::{DigestFor, HashFor};
use futures_timer::Delay;
use txpool_api::TransactionPool;
use futures::prelude::*;
use inherents::InherentData;
use sp_timestamp::TimestampInherentData;
use sp_api::{ApiExt, ProvideRuntimeApi};
use prometheus_endpoint::Registry as PrometheusRegistry;
use crate::{
Error,
dynamic_inclusion::DynamicInclusion,
validation_service::ServiceHandle,
};
// Polkadot proposer factory.
pub struct ProposerFactory {
service_handle: ServiceHandle,
babe_slot_duration: u64,
factory: sc_basic_authorship::ProposerFactory,
}
impl ProposerFactory {
/// Create a new proposer factory.
pub fn new(
client: Arc,
transaction_pool: Arc,
service_handle: ServiceHandle,
babe_slot_duration: u64,
prometheus: Option<&PrometheusRegistry>,
) -> Self {
let factory = sc_basic_authorship::ProposerFactory::new(
client,
transaction_pool,
prometheus,
);
ProposerFactory {
service_handle,
babe_slot_duration,
factory,
}
}
}
impl consensus::Environment
for ProposerFactory
where
TxPool: TransactionPool + 'static,
Client: BlockBuilderProvider + ProvideRuntimeApi + HeaderBackend + Send + Sync + 'static,
Client::Api: ParachainHost + BlockBuilderApi
+ ApiExt,
Backend: sc_client_api::Backend<
Block,
State = sp_api::StateBackendFor
> + 'static,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor: sp_api::StateBackend> + Send,
{
type CreateProposer = Pin> + Send + 'static
>>;
type Proposer = Proposer;
type Error = Error;
fn init(
&mut self,
parent_header: &Header,
) -> Self::CreateProposer {
let parent_hash = parent_header.hash();
let slot_duration = self.babe_slot_duration.clone();
let proposer = self.factory.init(parent_header).into_inner();
let maybe_proposer = self.service_handle
.clone()
.get_validation_instance(parent_hash)
.and_then(move |tracker| future::ready(proposer
.map_err(Into::into)
.map(|proposer| Proposer {
tracker,
slot_duration,
proposer,
})
));
Box::pin(maybe_proposer)
}
}
/// The Polkadot proposer logic.
pub struct Proposer, Backend> {
tracker: crate::validation_service::ValidationInstanceHandle,
slot_duration: u64,
proposer: sc_basic_authorship::Proposer,
}
impl consensus::Proposer for Proposer where
TxPool: TransactionPool + 'static,
Client: BlockBuilderProvider + ProvideRuntimeApi + HeaderBackend + Send + Sync + 'static,
Client::Api: ParachainHost + BlockBuilderApi + ApiExt,
Backend: sc_client_api::Backend> + 'static,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor: sp_api::StateBackend> + Send,
{
type Error = Error;
type Transaction = sp_api::TransactionFor;
type Proposal = Pin<
Box<
dyn Future