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