polkadot_node_core_parachains_inherent/
lib.rs1#![deny(unused_crate_dependencies, unused_results)]
27
28use futures::{select, FutureExt};
29use polkadot_node_subsystem::{
30 errors::SubsystemError, messages::ProvisionerMessage, overseer::Handle,
31};
32use polkadot_primitives::{Block, Hash, InherentData as ParachainsInherentData};
33use std::{sync::Arc, time};
34
35pub(crate) const LOG_TARGET: &str = "parachain::parachains-inherent";
36
37const PROVISIONER_TIMEOUT: time::Duration = core::time::Duration::from_millis(2500);
39
40pub struct ParachainsInherentDataProvider<C: sp_blockchain::HeaderBackend<Block>> {
42 pub client: Arc<C>,
43 pub overseer: polkadot_overseer::Handle,
44 pub parent: Hash,
45}
46
47impl<C: sp_blockchain::HeaderBackend<Block>> ParachainsInherentDataProvider<C> {
48 pub fn new(client: Arc<C>, overseer: polkadot_overseer::Handle, parent: Hash) -> Self {
50 ParachainsInherentDataProvider { client, overseer, parent }
51 }
52
53 pub async fn create(
55 client: Arc<C>,
56 mut overseer: Handle,
57 parent: Hash,
58 ) -> Result<ParachainsInherentData, Error> {
59 let pid = async {
60 let (sender, receiver) = futures::channel::oneshot::channel();
61 gum::trace!(
62 target: LOG_TARGET,
63 relay_parent = ?parent,
64 "Inherent data requested by Babe"
65 );
66 overseer.wait_for_activation(parent, sender).await;
67 receiver
68 .await
69 .map_err(|_| Error::ClosedChannelAwaitingActivation)?
70 .map_err(|e| Error::Subsystem(e))?;
71
72 let (sender, receiver) = futures::channel::oneshot::channel();
73 gum::trace!(
74 target: LOG_TARGET,
75 relay_parent = ?parent,
76 "Requesting inherent data (after having waited for activation)"
77 );
78 overseer
79 .send_msg(
80 ProvisionerMessage::RequestInherentData(parent, sender),
81 std::any::type_name::<Self>(),
82 )
83 .await;
84
85 receiver.await.map_err(|_| Error::ClosedChannelAwaitingInherentData)
86 };
87
88 let mut timeout = futures_timer::Delay::new(PROVISIONER_TIMEOUT).fuse();
89
90 let parent_header = match client.header(parent) {
91 Ok(Some(h)) => h,
92 Ok(None) => return Err(Error::ParentHeaderNotFound(parent)),
93 Err(err) => return Err(Error::Blockchain(err)),
94 };
95
96 let res = select! {
97 pid = pid.fuse() => pid,
98 _ = timeout => Err(Error::Timeout),
99 };
100
101 let inherent_data = match res {
102 Ok(pd) => ParachainsInherentData {
103 bitfields: pd.bitfields.into_iter().map(Into::into).collect(),
104 backed_candidates: pd.backed_candidates,
105 disputes: pd.disputes,
106 parent_header,
107 },
108 Err(err) => {
109 gum::debug!(
110 target: LOG_TARGET,
111 %err,
112 "Could not get provisioner inherent data; injecting default data",
113 );
114 ParachainsInherentData {
115 bitfields: Vec::new(),
116 backed_candidates: Vec::new(),
117 disputes: Vec::new(),
118 parent_header,
119 }
120 },
121 };
122
123 Ok(inherent_data)
124 }
125}
126
127#[async_trait::async_trait]
128impl<C: sp_blockchain::HeaderBackend<Block>> sp_inherents::InherentDataProvider
129 for ParachainsInherentDataProvider<C>
130{
131 async fn provide_inherent_data(
132 &self,
133 dst_inherent_data: &mut sp_inherents::InherentData,
134 ) -> Result<(), sp_inherents::Error> {
135 let inherent_data = ParachainsInherentDataProvider::create(
136 self.client.clone(),
137 self.overseer.clone(),
138 self.parent,
139 )
140 .await
141 .map_err(|e| sp_inherents::Error::Application(Box::new(e)))?;
142
143 dst_inherent_data
144 .put_data(polkadot_primitives::PARACHAINS_INHERENT_IDENTIFIER, &inherent_data)
145 }
146
147 async fn try_handle_error(
148 &self,
149 _identifier: &sp_inherents::InherentIdentifier,
150 _error: &[u8],
151 ) -> Option<Result<(), sp_inherents::Error>> {
152 None
154 }
155}
156
157#[derive(thiserror::Error, Debug)]
158pub enum Error {
159 #[error("Blockchain error")]
160 Blockchain(#[from] sp_blockchain::Error),
161 #[error("Timeout: provisioner did not return inherent data after {:?}", PROVISIONER_TIMEOUT)]
162 Timeout,
163 #[error("Could not find the parent header in the blockchain: {:?}", _0)]
164 ParentHeaderNotFound(Hash),
165 #[error("Closed channel from overseer when awaiting activation")]
166 ClosedChannelAwaitingActivation,
167 #[error("Closed channel from provisioner when awaiting inherent data")]
168 ClosedChannelAwaitingInherentData,
169 #[error("Subsystem failed")]
170 Subsystem(#[from] SubsystemError),
171}