referrerpolicy=no-referrer-when-downgrade

cumulus_test_relay_sproof_builder/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17extern crate alloc;
18
19use alloc::collections::btree_map::BTreeMap;
20use cumulus_primitives_core::{
21	relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId,
22};
23use polkadot_primitives::UpgradeGoAhead;
24use sp_runtime::traits::HashingFor;
25use sp_trie::PrefixedMemoryDB;
26
27/// Builds a sproof (portmanteau of 'spoof' and 'proof') of the relay chain state.
28#[derive(Clone)]
29pub struct RelayStateSproofBuilder {
30	/// The para id of the current parachain.
31	///
32	/// This doesn't get into the storage proof produced by the builder, however, it is used for
33	/// generation of the storage image and by auxiliary methods.
34	///
35	/// It's recommended to change this value once in the very beginning of usage.
36	///
37	/// The default value is 200.
38	pub para_id: ParaId,
39
40	pub host_config: AbridgedHostConfiguration,
41	pub dmq_mqc_head: Option<relay_chain::Hash>,
42	pub upgrade_go_ahead: Option<UpgradeGoAhead>,
43	pub relay_dispatch_queue_remaining_capacity: Option<(u32, u32)>,
44	pub hrmp_ingress_channel_index: Option<Vec<ParaId>>,
45	pub hrmp_egress_channel_index: Option<Vec<ParaId>>,
46	pub hrmp_channels: BTreeMap<relay_chain::HrmpChannelId, AbridgedHrmpChannel>,
47	pub current_slot: relay_chain::Slot,
48	pub current_epoch: u64,
49	pub randomness: relay_chain::Hash,
50	pub additional_key_values: Vec<(Vec<u8>, Vec<u8>)>,
51	pub included_para_head: Option<relay_chain::HeadData>,
52}
53
54impl Default for RelayStateSproofBuilder {
55	fn default() -> Self {
56		RelayStateSproofBuilder {
57			para_id: ParaId::from(200),
58			host_config: cumulus_primitives_core::AbridgedHostConfiguration {
59				max_code_size: 2 * 1024 * 1024,
60				max_head_data_size: 1024 * 1024,
61				max_upward_queue_count: 8,
62				max_upward_queue_size: 1024,
63				max_upward_message_size: 256,
64				max_upward_message_num_per_candidate: 5,
65				hrmp_max_message_num_per_candidate: 5,
66				validation_upgrade_cooldown: 6,
67				validation_upgrade_delay: 6,
68				async_backing_params: relay_chain::AsyncBackingParams {
69					allowed_ancestry_len: 0,
70					max_candidate_depth: 0,
71				},
72			},
73			dmq_mqc_head: None,
74			upgrade_go_ahead: None,
75			relay_dispatch_queue_remaining_capacity: None,
76			hrmp_ingress_channel_index: None,
77			hrmp_egress_channel_index: None,
78			hrmp_channels: BTreeMap::new(),
79			current_slot: 0.into(),
80			current_epoch: 0u64,
81			randomness: relay_chain::Hash::default(),
82			additional_key_values: vec![],
83			included_para_head: None,
84		}
85	}
86}
87
88impl RelayStateSproofBuilder {
89	/// Returns a mutable reference to HRMP channel metadata for a channel (`sender`,
90	/// `self.para_id`).
91	///
92	/// If there is no channel, a new default one is created.
93	///
94	/// It also updates the `hrmp_ingress_channel_index`, creating it if needed.
95	pub fn upsert_inbound_channel(&mut self, sender: ParaId) -> &mut AbridgedHrmpChannel {
96		let in_index = self.hrmp_ingress_channel_index.get_or_insert_with(Vec::new);
97		if let Err(idx) = in_index.binary_search(&sender) {
98			in_index.insert(idx, sender);
99		}
100
101		self.upsert_channel(relay_chain::HrmpChannelId { sender, recipient: self.para_id })
102	}
103
104	/// Returns a mutable reference to HRMP channel metadata for a channel (`self.para_id`,
105	/// `recipient`).
106	///
107	/// If there is no channel, a new default one is created.
108	///
109	/// It also updates the `hrmp_egress_channel_index`, creating it if needed.
110	pub fn upsert_outbound_channel(&mut self, recipient: ParaId) -> &mut AbridgedHrmpChannel {
111		let in_index = self.hrmp_egress_channel_index.get_or_insert_with(Vec::new);
112		if let Err(idx) = in_index.binary_search(&recipient) {
113			in_index.insert(idx, recipient);
114		}
115
116		self.upsert_channel(relay_chain::HrmpChannelId { sender: self.para_id, recipient })
117	}
118
119	/// Creates a new default entry in the hrmp channels mapping if not exists, and returns mutable
120	/// reference to it.
121	fn upsert_channel(&mut self, id: relay_chain::HrmpChannelId) -> &mut AbridgedHrmpChannel {
122		self.hrmp_channels.entry(id).or_insert_with(|| AbridgedHrmpChannel {
123			max_capacity: 0,
124			max_total_size: 0,
125			max_message_size: 0,
126			msg_count: 0,
127			total_size: 0,
128			mqc_head: None,
129		})
130	}
131
132	pub fn into_state_root_and_proof(
133		self,
134	) -> (polkadot_primitives::Hash, sp_state_machine::StorageProof) {
135		let (db, root) =
136			PrefixedMemoryDB::<HashingFor<polkadot_primitives::Block>>::default_with_root();
137		let state_version = Default::default(); // for test using default.
138		let mut backend = sp_state_machine::TrieBackendBuilder::new(db, root).build();
139
140		let mut relevant_keys = Vec::new();
141		{
142			use codec::Encode as _;
143
144			let mut insert = |key: Vec<u8>, value: Vec<u8>| {
145				relevant_keys.push(key.clone());
146				backend.insert(vec![(None, vec![(key, Some(value))])], state_version);
147			};
148
149			insert(relay_chain::well_known_keys::ACTIVE_CONFIG.to_vec(), self.host_config.encode());
150			if let Some(dmq_mqc_head) = self.dmq_mqc_head {
151				insert(
152					relay_chain::well_known_keys::dmq_mqc_head(self.para_id),
153					dmq_mqc_head.encode(),
154				);
155			}
156			if let Some(para_head) = self.included_para_head {
157				insert(relay_chain::well_known_keys::para_head(self.para_id), para_head.encode());
158			}
159			if let Some(relay_dispatch_queue_remaining_capacity) =
160				self.relay_dispatch_queue_remaining_capacity
161			{
162				insert(
163					relay_chain::well_known_keys::relay_dispatch_queue_remaining_capacity(
164						self.para_id,
165					)
166					.key,
167					relay_dispatch_queue_remaining_capacity.encode(),
168				);
169			}
170			if let Some(upgrade_go_ahead) = self.upgrade_go_ahead {
171				insert(
172					relay_chain::well_known_keys::upgrade_go_ahead_signal(self.para_id),
173					upgrade_go_ahead.encode(),
174				);
175			}
176			if let Some(hrmp_ingress_channel_index) = self.hrmp_ingress_channel_index {
177				let mut sorted = hrmp_ingress_channel_index.clone();
178				sorted.sort();
179				assert_eq!(sorted, hrmp_ingress_channel_index);
180
181				insert(
182					relay_chain::well_known_keys::hrmp_ingress_channel_index(self.para_id),
183					hrmp_ingress_channel_index.encode(),
184				);
185			}
186			if let Some(hrmp_egress_channel_index) = self.hrmp_egress_channel_index {
187				let mut sorted = hrmp_egress_channel_index.clone();
188				sorted.sort();
189				assert_eq!(sorted, hrmp_egress_channel_index);
190
191				insert(
192					relay_chain::well_known_keys::hrmp_egress_channel_index(self.para_id),
193					hrmp_egress_channel_index.encode(),
194				);
195			}
196			for (channel, metadata) in self.hrmp_channels {
197				insert(relay_chain::well_known_keys::hrmp_channels(channel), metadata.encode());
198			}
199			insert(relay_chain::well_known_keys::EPOCH_INDEX.to_vec(), self.current_epoch.encode());
200			insert(
201				relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS.to_vec(),
202				self.randomness.encode(),
203			);
204			insert(relay_chain::well_known_keys::CURRENT_SLOT.to_vec(), self.current_slot.encode());
205
206			for (key, value) in self.additional_key_values {
207				insert(key, value);
208			}
209		}
210
211		let root = *backend.root();
212		let proof = sp_state_machine::prove_read(backend, relevant_keys).expect("prove read");
213		(root, proof)
214	}
215}