sc_consensus_manual_seal/
seal_block.rs1use crate::{rpc, ConsensusDataProvider, CreatedBlock, Error};
22use futures::prelude::*;
23use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction};
24use sc_transaction_pool_api::TransactionPool;
25use sp_api::ProvideRuntimeApi;
26use sp_blockchain::HeaderBackend;
27use sp_consensus::{self, BlockOrigin, Environment, Proposer, SelectChain};
28use sp_inherents::{CreateInherentDataProviders, InherentDataProvider};
29use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
30use std::{sync::Arc, time::Duration};
31
32pub const MAX_PROPOSAL_DURATION: u64 = 10;
34
35pub struct SealBlockParams<'a, B: BlockT, BI, SC, C: ProvideRuntimeApi<B>, E, TP, CIDP, P> {
37 pub create_empty: bool,
40 pub finalize: bool,
42 pub parent_hash: Option<<B as BlockT>::Hash>,
44 pub sender: rpc::Sender<CreatedBlock<<B as BlockT>::Hash>>,
46 pub pool: Arc<TP>,
48 pub client: Arc<C>,
50 pub env: &'a mut E,
52 pub select_chain: &'a SC,
54 pub consensus_data_provider: Option<&'a dyn ConsensusDataProvider<B, Proof = P>>,
56 pub block_import: &'a mut BI,
58 pub create_inherent_data_providers: &'a CIDP,
60}
61
62pub async fn seal_block<B, BI, SC, C, E, TP, CIDP, P>(
64 SealBlockParams {
65 create_empty,
66 finalize,
67 pool,
68 parent_hash,
69 client,
70 select_chain,
71 block_import,
72 env,
73 create_inherent_data_providers,
74 consensus_data_provider: digest_provider,
75 mut sender,
76 }: SealBlockParams<'_, B, BI, SC, C, E, TP, CIDP, P>,
77) where
78 B: BlockT,
79 BI: BlockImport<B, Error = sp_consensus::Error> + Send + Sync + 'static,
80 C: HeaderBackend<B> + ProvideRuntimeApi<B>,
81 E: Environment<B>,
82 E::Proposer: Proposer<B, Proof = P>,
83 TP: TransactionPool<Block = B>,
84 SC: SelectChain<B>,
85 CIDP: CreateInherentDataProviders<B, ()>,
86 P: codec::Encode + Send + Sync + 'static,
87{
88 let future = async {
89 if pool.status().ready == 0 && !create_empty {
90 return Err(Error::EmptyTransactionPool)
91 }
92
93 let parent = match parent_hash {
97 Some(hash) =>
98 client.header(hash)?.ok_or_else(|| Error::BlockNotFound(format!("{}", hash)))?,
99 None => select_chain.best_chain().await?,
100 };
101
102 let inherent_data_providers = create_inherent_data_providers
103 .create_inherent_data_providers(parent.hash(), ())
104 .await
105 .map_err(|e| Error::Other(e))?;
106
107 let inherent_data = inherent_data_providers.create_inherent_data().await?;
108
109 let proposer = env.init(&parent).map_err(|err| Error::StringError(err.to_string())).await?;
110 let inherents_len = inherent_data.len();
111
112 let digest = if let Some(digest_provider) = digest_provider {
113 digest_provider.create_digest(&parent, &inherent_data)?
114 } else {
115 Default::default()
116 };
117
118 let proposal = proposer
119 .propose(
120 inherent_data.clone(),
121 digest,
122 Duration::from_secs(MAX_PROPOSAL_DURATION),
123 None,
124 )
125 .map_err(|err| Error::StringError(err.to_string()))
126 .await?;
127
128 if proposal.block.extrinsics().len() == inherents_len && !create_empty {
129 return Err(Error::EmptyTransactionPool)
130 }
131
132 let (header, body) = proposal.block.deconstruct();
133 let proof = proposal.proof;
134 let proof_size = proof.encoded_size();
135 let mut params = BlockImportParams::new(BlockOrigin::Own, header.clone());
136 params.body = Some(body);
137 params.finalized = finalize;
138 params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
139 params.state_action = StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(
140 proposal.storage_changes,
141 ));
142
143 if let Some(digest_provider) = digest_provider {
144 digest_provider.append_block_import(&parent, &mut params, &inherent_data, proof)?;
145 }
146
147 let mut post_header = header.clone();
150 post_header.digest_mut().logs.extend(params.post_digests.iter().cloned());
151
152 match block_import.import_block(params).await? {
153 ImportResult::Imported(aux) => Ok(CreatedBlock {
154 hash: <B as BlockT>::Header::hash(&post_header),
155 aux,
156 proof_size,
157 }),
158 other => Err(other.into()),
159 }
160 };
161
162 rpc::send_result(&mut sender, future.await)
163}