astar_collator/parachain/
shell_upgrade.rs1use astar_primitives::*;
21use cumulus_primitives_core::relay_chain::PersistedValidationData;
22use cumulus_primitives_core::RelayParentOffsetApi;
23use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
24use fc_rpc::pending::ConsensusDataProvider;
25use sc_client_api::{AuxStore, UsageProvider};
26use sc_consensus::{import_queue::Verifier as VerifierT, BlockImportParams};
27use sp_api::{ApiExt, ProvideRuntimeApi};
28use sp_consensus_aura::{
29 digests::CompatibleDigestItem,
30 sr25519::{AuthorityId as AuraId, AuthoritySignature},
31 AuraApi,
32};
33use sp_inherents::{CreateInherentDataProviders, Error, InherentData};
34use sp_runtime::{
35 traits::{Block as BlockT, Header as HeaderT},
36 Digest, DigestItem,
37};
38use sp_timestamp::TimestampInherentData;
39use std::{marker::PhantomData, sync::Arc};
40
41pub struct Verifier<Client> {
42 pub client: Arc<Client>,
43 pub aura_verifier: Box<dyn VerifierT<Block>>,
44 pub relay_chain_verifier: Box<dyn VerifierT<Block>>,
45}
46
47#[async_trait::async_trait]
48impl<Client> VerifierT<Block> for Verifier<Client>
49where
50 Client: ProvideRuntimeApi<Block> + Send + Sync,
51 Client::Api: AuraApi<Block, AuraId>,
52{
53 async fn verify(
54 &self,
55 block_import: BlockImportParams<Block>,
56 ) -> Result<BlockImportParams<Block>, String> {
57 if self
58 .client
59 .runtime_api()
60 .has_api::<dyn AuraApi<Block, AuraId>>(*block_import.header.parent_hash())
61 .unwrap_or(false)
62 {
63 self.aura_verifier.verify(block_import).await
64 } else {
65 self.relay_chain_verifier.verify(block_import).await
66 }
67 }
68}
69
70pub struct AuraConsensusDataProviderFallback<B, C> {
75 client: Arc<C>,
76 phantom_data: PhantomData<B>,
77}
78
79impl<B, C> AuraConsensusDataProviderFallback<B, C>
80where
81 B: BlockT,
82 C: AuxStore + ProvideRuntimeApi<B> + UsageProvider<B> + Send + Sync,
83 C::Api: AuraApi<B, AuraId>,
84{
85 pub fn new(client: Arc<C>) -> Self {
86 Self {
87 client,
88 phantom_data: Default::default(),
89 }
90 }
91}
92
93impl<B, C> ConsensusDataProvider<B> for AuraConsensusDataProviderFallback<B, C>
94where
95 B: BlockT,
96 C: AuxStore + ProvideRuntimeApi<B> + UsageProvider<B> + Send + Sync,
97 C::Api: AuraApi<B, AuraId>,
98{
99 fn create_digest(&self, parent: &B::Header, data: &InherentData) -> Result<Digest, Error> {
100 if self
101 .client
102 .runtime_api()
103 .has_api::<dyn AuraApi<Block, AuraId>>(parent.hash())
104 .unwrap_or_default()
105 {
106 let slot_duration = sc_consensus_aura::slot_duration(&*self.client)
107 .expect("slot_duration should be present at this point; qed.");
108 let timestamp = data
109 .timestamp_inherent_data()?
110 .expect("Timestamp is always present; qed");
111
112 let digest_item =
113 <DigestItem as CompatibleDigestItem<AuthoritySignature>>::aura_pre_digest(
114 sp_consensus_aura::Slot::from_timestamp(timestamp, slot_duration),
115 );
116
117 return Ok(Digest {
118 logs: vec![digest_item],
119 });
120 }
121 Err(Error::Application("AuraApi is not present".into()))
122 }
123}
124
125pub struct PendingCrateInherentDataProvider<B, C> {
129 client: Arc<C>,
130 phantom_data: PhantomData<B>,
131}
132
133impl<B, C> PendingCrateInherentDataProvider<B, C>
134where
135 B: BlockT,
136 C: AuxStore + ProvideRuntimeApi<B> + UsageProvider<B> + Send + Sync,
137 C::Api: AuraApi<B, AuraId>,
138{
139 pub fn new(client: Arc<C>) -> Self {
140 Self {
141 client,
142 phantom_data: Default::default(),
143 }
144 }
145}
146
147#[async_trait::async_trait]
148impl<B, C> CreateInherentDataProviders<B, ()> for PendingCrateInherentDataProvider<B, C>
149where
150 B: BlockT,
151 C: AuxStore + ProvideRuntimeApi<B> + UsageProvider<B> + Send + Sync,
152 C::Api: AuraApi<B, AuraId> + RelayParentOffsetApi<B>,
153{
154 type InherentDataProviders = (
155 sp_consensus_aura::inherents::InherentDataProvider,
156 sp_timestamp::InherentDataProvider,
157 cumulus_primitives_parachain_inherent::ParachainInherentData,
158 );
159
160 async fn create_inherent_data_providers(
161 &self,
162 parent: B::Hash,
163 _extra_args: (),
164 ) -> Result<Self::InherentDataProviders, Box<dyn std::error::Error + Send + Sync>> {
165 if !self
166 .client
167 .runtime_api()
168 .has_api::<dyn AuraApi<Block, AuraId>>(parent)
169 .unwrap_or_default()
170 {
171 return Err("AuraApi is not present".into());
172 }
173
174 let slot_duration = sc_consensus_aura::slot_duration(&*self.client)
175 .expect("slot_duration should be present at this point; qed.");
176 let current = sp_timestamp::InherentDataProvider::from_system_time();
177 let next_slot = current.timestamp().as_millis() + slot_duration.as_millis();
178 let timestamp = sp_timestamp::InherentDataProvider::new(next_slot.into());
179 let slot =
180 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
181 *timestamp,
182 slot_duration,
183 );
184 let (relay_parent_storage_root, relay_chain_state, relay_parent_descendants) = if self
188 .client
189 .runtime_api()
190 .has_api::<dyn RelayParentOffsetApi<B>>(parent)
191 .unwrap_or(false)
192 {
193 let offset = self
194 .client
195 .runtime_api()
196 .relay_parent_offset(parent)
197 .expect("API present, call should succeed; qed");
198 RelayStateSproofBuilder::default().into_state_root_proof_and_descendants(offset.into())
199 } else {
200 let (root, proof) = RelayStateSproofBuilder::default().into_state_root_and_proof();
201 (root, proof, Default::default())
202 };
203 let vfp = PersistedValidationData {
204 relay_parent_number: u32::MAX,
207 relay_parent_storage_root,
208 ..Default::default()
209 };
210 let parachain_inherent_data =
211 cumulus_primitives_parachain_inherent::ParachainInherentData {
212 validation_data: vfp,
213 relay_chain_state,
214 downward_messages: Default::default(),
215 horizontal_messages: Default::default(),
216 relay_parent_descendants,
217 collator_peer_id: Default::default(),
218 };
219 Ok((slot, timestamp, parachain_inherent_data))
220 }
221}