cumulus_client_parachain_inherent/
lib.rs1use codec::Decode;
20use cumulus_primitives_core::{
21 relay_chain::{self, Hash as PHash, HrmpChannelId},
22 ParaId, PersistedValidationData,
23};
24use cumulus_relay_chain_interface::RelayChainInterface;
25
26mod mock;
27
28pub use cumulus_primitives_parachain_inherent::{ParachainInherentData, INHERENT_IDENTIFIER};
29pub use mock::{MockValidationDataInherentDataProvider, MockXcmConfig};
30
31const LOG_TARGET: &str = "parachain-inherent";
32
33async fn collect_relay_storage_proof(
36 relay_chain_interface: &impl RelayChainInterface,
37 para_id: ParaId,
38 relay_parent: PHash,
39) -> Option<sp_state_machine::StorageProof> {
40 use relay_chain::well_known_keys as relay_well_known_keys;
41
42 let ingress_channels = relay_chain_interface
43 .get_storage_by_key(
44 relay_parent,
45 &relay_well_known_keys::hrmp_ingress_channel_index(para_id),
46 )
47 .await
48 .map_err(|e| {
49 tracing::error!(
50 target: LOG_TARGET,
51 relay_parent = ?relay_parent,
52 error = ?e,
53 "Cannot obtain the hrmp ingress channel."
54 )
55 })
56 .ok()?;
57
58 let ingress_channels = ingress_channels
59 .map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
60 .transpose()
61 .map_err(|e| {
62 tracing::error!(
63 target: LOG_TARGET,
64 error = ?e,
65 "Cannot decode the hrmp ingress channel index.",
66 )
67 })
68 .ok()?
69 .unwrap_or_default();
70
71 let egress_channels = relay_chain_interface
72 .get_storage_by_key(
73 relay_parent,
74 &relay_well_known_keys::hrmp_egress_channel_index(para_id),
75 )
76 .await
77 .map_err(|e| {
78 tracing::error!(
79 target: LOG_TARGET,
80 error = ?e,
81 "Cannot obtain the hrmp egress channel.",
82 )
83 })
84 .ok()?;
85
86 let egress_channels = egress_channels
87 .map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
88 .transpose()
89 .map_err(|e| {
90 tracing::error!(
91 target: LOG_TARGET,
92 error = ?e,
93 "Cannot decode the hrmp egress channel index.",
94 )
95 })
96 .ok()?
97 .unwrap_or_default();
98
99 let mut relevant_keys = vec![
100 relay_well_known_keys::CURRENT_BLOCK_RANDOMNESS.to_vec(),
101 relay_well_known_keys::ONE_EPOCH_AGO_RANDOMNESS.to_vec(),
102 relay_well_known_keys::TWO_EPOCHS_AGO_RANDOMNESS.to_vec(),
103 relay_well_known_keys::CURRENT_SLOT.to_vec(),
104 relay_well_known_keys::ACTIVE_CONFIG.to_vec(),
105 relay_well_known_keys::dmq_mqc_head(para_id),
106 #[allow(deprecated)]
110 relay_well_known_keys::relay_dispatch_queue_size(para_id),
111 relay_well_known_keys::relay_dispatch_queue_remaining_capacity(para_id).key,
112 relay_well_known_keys::hrmp_ingress_channel_index(para_id),
113 relay_well_known_keys::hrmp_egress_channel_index(para_id),
114 relay_well_known_keys::upgrade_go_ahead_signal(para_id),
115 relay_well_known_keys::upgrade_restriction_signal(para_id),
116 relay_well_known_keys::para_head(para_id),
117 ];
118 relevant_keys.extend(ingress_channels.into_iter().map(|sender| {
119 relay_well_known_keys::hrmp_channels(HrmpChannelId { sender, recipient: para_id })
120 }));
121 relevant_keys.extend(egress_channels.into_iter().map(|recipient| {
122 relay_well_known_keys::hrmp_channels(HrmpChannelId { sender: para_id, recipient })
123 }));
124
125 relay_chain_interface
126 .prove_read(relay_parent, &relevant_keys)
127 .await
128 .map_err(|e| {
129 tracing::error!(
130 target: LOG_TARGET,
131 relay_parent = ?relay_parent,
132 error = ?e,
133 "Cannot obtain read proof from relay chain.",
134 );
135 })
136 .ok()
137}
138
139pub struct ParachainInherentDataProvider;
140
141impl ParachainInherentDataProvider {
142 pub async fn create_at(
146 relay_parent: PHash,
147 relay_chain_interface: &impl RelayChainInterface,
148 validation_data: &PersistedValidationData,
149 para_id: ParaId,
150 ) -> Option<ParachainInherentData> {
151 let relay_chain_state =
152 collect_relay_storage_proof(relay_chain_interface, para_id, relay_parent).await?;
153
154 let downward_messages = relay_chain_interface
155 .retrieve_dmq_contents(para_id, relay_parent)
156 .await
157 .map_err(|e| {
158 tracing::error!(
159 target: LOG_TARGET,
160 relay_parent = ?relay_parent,
161 error = ?e,
162 "An error occurred during requesting the downward messages.",
163 );
164 })
165 .ok()?;
166 let horizontal_messages = relay_chain_interface
167 .retrieve_all_inbound_hrmp_channel_contents(para_id, relay_parent)
168 .await
169 .map_err(|e| {
170 tracing::error!(
171 target: LOG_TARGET,
172 relay_parent = ?relay_parent,
173 error = ?e,
174 "An error occurred during requesting the inbound HRMP messages.",
175 );
176 })
177 .ok()?;
178
179 Some(ParachainInherentData {
180 downward_messages,
181 horizontal_messages,
182 validation_data: validation_data.clone(),
183 relay_chain_state,
184 })
185 }
186}