// 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::Duration, }; use sp_blockchain::HeaderBackend; use block_builder::{BlockBuilderApi, BlockBuilderProvider}; use consensus::{Proposal, RecordProof}; use polkadot_primitives::v0::{NEW_HEADS_IDENTIFIER, Block, Header, AttestedCandidate}; use runtime_primitives::traits::{DigestFor, HashFor}; use txpool_api::TransactionPool; use futures::prelude::*; use inherents::InherentData; use sp_api::{ApiExt, ProvideRuntimeApi}; use prometheus_endpoint::Registry as PrometheusRegistry; use crate::Error; // Polkadot proposer factory. pub struct ProposerFactory { factory: sc_basic_authorship::ProposerFactory, } impl ProposerFactory { /// Create a new proposer factory. pub fn new( client: Arc, transaction_pool: Arc, prometheus: Option<&PrometheusRegistry>, ) -> Self { let factory = sc_basic_authorship::ProposerFactory::new( client, transaction_pool, prometheus, ); ProposerFactory { factory, } } } impl consensus::Environment for ProposerFactory where TxPool: TransactionPool + 'static, Client: BlockBuilderProvider + ProvideRuntimeApi + HeaderBackend + Send + Sync + 'static, Client::Api: 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 proposer = self.factory.init(parent_header) .into_inner() .map_err(Into::into) .map(|proposer| Proposer { proposer }); Box::pin(future::ready(proposer)) } } /// The Polkadot proposer logic. pub struct Proposer, Backend> { proposer: sc_basic_authorship::Proposer, } impl consensus::Proposer for Proposer where TxPool: TransactionPool + 'static, Client: BlockBuilderProvider + ProvideRuntimeApi + HeaderBackend + Send + Sync + 'static, Client::Api: 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>, Self::Error, >> + Send > >; fn propose( self, inherent_data: InherentData, inherent_digests: DigestFor, max_duration: Duration, record_proof: RecordProof, ) -> Self::Proposal { async move { let mut inherent_data = inherent_data; inherent_data.put_data(NEW_HEADS_IDENTIFIER, &Vec::::new()) .map_err(Error::InherentError)?; self.proposer.propose( inherent_data, inherent_digests.clone(), max_duration, record_proof ).await.map_err(Into::into) }.boxed() } }