domain_block_preprocessor/
inherents.rs1use sp_api::ProvideRuntimeApi;
17use sp_blockchain::HeaderBackend;
18use sp_domains::{DomainId, DomainsApi};
19use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider};
20use sp_messenger::MessengerApi;
21use sp_runtime::traits::{Block as BlockT, NumberFor};
22use sp_timestamp::InherentType;
23use std::error::Error;
24use std::sync::Arc;
25
26pub async fn get_inherent_data<CClient, CBlock, Block>(
27 consensus_client: Arc<CClient>,
28 consensus_block_hash: CBlock::Hash,
29 parent_hash: Block::Hash,
30 domain_id: DomainId,
31) -> Result<InherentData, sp_blockchain::Error>
32where
33 CBlock: BlockT,
34 Block: BlockT,
35 CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
36 CClient::Api:
37 DomainsApi<CBlock, Block::Header> + MessengerApi<CBlock, NumberFor<CBlock>, CBlock::Hash>,
38{
39 let create_inherent_data_providers =
40 CreateInherentDataProvider::new(consensus_client, Some(consensus_block_hash), domain_id);
41 let inherent_data_providers = <CreateInherentDataProvider<_, _> as CreateInherentDataProviders<
42 Block,
43 (),
44 >>::create_inherent_data_providers(
45 &create_inherent_data_providers, parent_hash, ()
46 )
47 .await?;
48 let mut inherent_data = InherentData::new();
49 inherent_data_providers
50 .provide_inherent_data(&mut inherent_data)
51 .await
52 .map_err(|err| {
53 sp_blockchain::Error::Application(Box::from(format!(
54 "failed to provide inherent data: {err:?}"
55 )))
56 })?;
57
58 Ok(inherent_data)
59}
60
61pub(crate) fn is_runtime_upgraded<CClient, CBlock, Block>(
62 consensus_client: &Arc<CClient>,
63 consensus_block_hash: CBlock::Hash,
64 domain_id: DomainId,
65) -> Result<bool, sp_blockchain::Error>
66where
67 CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
68 CClient::Api: DomainsApi<CBlock, Block::Header>,
69 CBlock: BlockT,
70 Block: BlockT,
71{
72 let runtime_api = consensus_client.runtime_api();
73
74 let runtime_id = runtime_api
75 .runtime_id(consensus_block_hash, domain_id)?
76 .ok_or(sp_blockchain::Error::Application(Box::from(format!(
77 "No RuntimeId found for {domain_id:?}"
78 ))))?;
79
80 let runtime_upgrades = runtime_api.runtime_upgrades(consensus_block_hash)?;
81
82 Ok(runtime_upgrades.contains(&runtime_id))
83}
84
85pub fn extract_domain_runtime_upgrade_code<CClient, CBlock, Block>(
87 consensus_client: &Arc<CClient>,
88 consensus_block_hash: CBlock::Hash,
89 domain_id: DomainId,
90) -> Result<Option<Vec<u8>>, sp_blockchain::Error>
91where
92 CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
93 CClient::Api: DomainsApi<CBlock, Block::Header>,
94 CBlock: BlockT,
95 Block: BlockT,
96{
97 if is_runtime_upgraded::<_, _, Block>(consensus_client, consensus_block_hash, domain_id)? {
98 let new_domain_runtime = consensus_client
99 .runtime_api()
100 .domain_runtime_code(consensus_block_hash, domain_id)?
101 .ok_or_else(|| {
102 sp_blockchain::Error::Application(Box::from(format!(
103 "No new runtime code for {domain_id:?}"
104 )))
105 })?;
106
107 Ok(Some(new_domain_runtime))
108 } else {
109 Ok(None)
110 }
111}
112
113#[derive(Debug)]
114pub struct CreateInherentDataProvider<CClient, CBlock: BlockT> {
115 consensus_client: Arc<CClient>,
116 maybe_consensus_block_hash: Option<CBlock::Hash>,
117 domain_id: DomainId,
118}
119
120impl<CClient, CBlock: BlockT + Clone> Clone for CreateInherentDataProvider<CClient, CBlock> {
121 fn clone(&self) -> Self {
122 Self {
123 consensus_client: self.consensus_client.clone(),
124 maybe_consensus_block_hash: self.maybe_consensus_block_hash,
125 domain_id: self.domain_id,
126 }
127 }
128}
129
130impl<CClient, CBlock: BlockT> CreateInherentDataProvider<CClient, CBlock> {
131 pub fn new(
132 consensus_client: Arc<CClient>,
133 maybe_consensus_block_hash: Option<CBlock::Hash>,
134 domain_id: DomainId,
135 ) -> Self {
136 Self {
137 consensus_client,
138 maybe_consensus_block_hash,
139 domain_id,
140 }
141 }
142}
143
144#[async_trait::async_trait]
145impl<CClient, CBlock, Block> CreateInherentDataProviders<Block, ()>
146 for CreateInherentDataProvider<CClient, CBlock>
147where
148 Block: BlockT,
149 CBlock: BlockT,
150 CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
151 CClient::Api:
152 DomainsApi<CBlock, Block::Header> + MessengerApi<CBlock, NumberFor<CBlock>, CBlock::Hash>,
153{
154 type InherentDataProviders = (
155 sp_timestamp::InherentDataProvider,
156 sp_block_fees::InherentDataProvider,
157 sp_executive::InherentDataProvider,
158 sp_messenger::InherentDataProvider,
159 sp_domain_sudo::InherentDataProvider,
160 sp_evm_tracker::InherentDataProvider,
161 );
162
163 async fn create_inherent_data_providers(
164 &self,
165 _parent: Block::Hash,
166 _extra_args: (),
167 ) -> Result<Self::InherentDataProviders, Box<dyn Error + Send + Sync>> {
168 let consensus_block_hash = self
174 .maybe_consensus_block_hash
175 .unwrap_or(self.consensus_client.info().best_hash);
176
177 let runtime_api = self.consensus_client.runtime_api();
178
179 let timestamp = runtime_api.domain_timestamp(consensus_block_hash)?;
180 let timestamp_provider =
181 sp_timestamp::InherentDataProvider::new(InherentType::new(timestamp));
182
183 let maybe_runtime_upgrade_code = extract_domain_runtime_upgrade_code::<_, _, Block>(
184 &self.consensus_client,
185 consensus_block_hash,
186 self.domain_id,
187 )?;
188 let runtime_upgrade_provider =
189 sp_executive::InherentDataProvider::new(maybe_runtime_upgrade_code);
190
191 let consensus_chain_byte_fee =
192 runtime_api.consensus_transaction_byte_fee(consensus_block_hash)?;
193 let storage_price_provider =
194 sp_block_fees::InherentDataProvider::new(consensus_chain_byte_fee);
195
196 let domain_chains_allowlist_update =
197 runtime_api.domain_chains_allowlist_update(consensus_block_hash, self.domain_id)?;
198 let messenger_inherent_provider =
199 sp_messenger::InherentDataProvider::new(sp_messenger::InherentType {
200 maybe_updates: domain_chains_allowlist_update,
201 });
202
203 let maybe_domain_sudo_call =
204 runtime_api.domain_sudo_call(consensus_block_hash, self.domain_id)?;
205 let domain_sudo_call_inherent_provider =
206 sp_domain_sudo::InherentDataProvider::new(maybe_domain_sudo_call);
207
208 let maybe_evm_domain_contract_creation_allowed_by_call = runtime_api
209 .evm_domain_contract_creation_allowed_by_call(consensus_block_hash, self.domain_id)?;
210 let evm_domain_contract_creation_allowed_by_call_inherent_provider =
211 sp_evm_tracker::InherentDataProvider::new(
212 maybe_evm_domain_contract_creation_allowed_by_call,
213 );
214
215 Ok((
216 timestamp_provider,
217 storage_price_provider,
218 runtime_upgrade_provider,
219 messenger_inherent_provider,
220 domain_sudo_call_inherent_provider,
221 evm_domain_contract_creation_allowed_by_call_inherent_provider,
222 ))
223 }
224}