1use crate::{DynamicPayload, Error, call};
4use scale::{Decode, Encode};
5use sp_core::twox_128;
6use subxt::{
7 OnlineClient,
8 dynamic::{self, Value},
9 events::StaticEvent,
10 ext::{scale_decode::DecodeAsType, scale_encode::EncodeAsType},
11 utils::H256,
12};
13
14pub async fn clear_dmpq(endpoint: &str, para_ids: &[u32]) -> Result<H256, Error> {
20 let client = OnlineClient::<subxt::PolkadotConfig>::from_url(endpoint)
21 .await
22 .map_err(|e| Error::SubXtError(e.into()))?;
23 let mut sub = client
25 .blocks()
26 .subscribe_finalized()
27 .await
28 .map_err(|e| Error::SubXtError(e.into()))?;
29 for _ in 0..2 {
30 sub.next().await;
31 }
32
33 let clear_dmq_keys = generate_storage_keys(para_ids);
35
36 let kill_storage = construct_kill_storage_call(clear_dmq_keys);
38 let sudo = subxt_signer::sr25519::dev::alice();
39 let sudo_call = call::construct_sudo_extrinsic(kill_storage);
40 client
41 .tx()
42 .sign_and_submit_default(&sudo_call, &sudo)
43 .await
44 .map_err(|e| Error::SubXtError(e.into()))
45}
46
47fn construct_kill_storage_call(keys: Vec<Vec<u8>>) -> DynamicPayload {
48 dynamic::tx(
49 "System",
50 "kill_storage",
51 vec![Value::unnamed_composite(keys.into_iter().map(Value::from_bytes))],
52 )
53}
54
55fn generate_storage_keys(para_ids: &[u32]) -> Vec<Vec<u8>> {
56 let dmp = twox_128("Dmp".as_bytes());
57 let dmp_queue_heads = twox_128("DownwardMessageQueueHeads".as_bytes());
58 let dmp_queues = twox_128("DownwardMessageQueues".as_bytes());
59 let mut clear_dmq_keys = Vec::<Vec<u8>>::new();
60 for id in para_ids {
61 let id = id.to_le_bytes();
62 let mut key = dmp.to_vec();
64 key.extend(&dmp_queue_heads);
65 key.extend(sp_core::twox_64(&id));
66 key.extend(id);
67 clear_dmq_keys.push(key);
68 let mut key = dmp.to_vec();
70 key.extend(&dmp_queues);
71 key.extend(sp_core::twox_64(&id));
72 key.extend(id);
73 clear_dmq_keys.push(key);
74 }
75 clear_dmq_keys
76}
77
78#[derive(Debug, PartialEq)]
80pub enum RelayChain {
81 PaseoLocal,
83 WestendLocal,
85}
86
87impl RelayChain {
88 pub fn from(id: &str) -> Option<RelayChain> {
93 match id {
94 "paseo-local" => Some(RelayChain::PaseoLocal),
95 "westend-local" => Some(RelayChain::WestendLocal),
96 _ => None,
97 }
98 }
99}
100
101#[derive(Debug, Encode, Decode, DecodeAsType, EncodeAsType)]
103#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
104#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
105pub struct Reserved {
106 pub para_id: u32,
108}
109impl StaticEvent for Reserved {
110 const PALLET: &'static str = "Registrar";
111 const EVENT: &'static str = "Reserved";
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use RelayChain::*;
118 use sp_core::twox_64;
119
120 #[test]
121 fn construct_kill_storage_call_works() {
122 let keys = vec!["key".as_bytes().to_vec()];
123 assert_eq!(
124 construct_kill_storage_call(keys.clone()),
125 dynamic::tx(
126 "System",
127 "kill_storage",
128 vec![Value::unnamed_composite(keys.into_iter().map(Value::from_bytes))],
129 )
130 )
131 }
132
133 #[test]
134 fn generate_storage_keys_works() {
135 let para_ids = vec![1_000, 4_385];
136 let dmp = twox_128("Dmp".as_bytes());
137 let dmp_queue_heads = [dmp, twox_128("DownwardMessageQueueHeads".as_bytes())].concat();
138 let dmp_queues = [dmp, twox_128("DownwardMessageQueues".as_bytes())].concat();
139
140 assert_eq!(
141 generate_storage_keys(¶_ids),
142 para_ids
143 .iter()
144 .flat_map(|id| {
145 let id = id.to_le_bytes().to_vec();
146 [
147 [dmp_queue_heads.clone(), twox_64(&id).to_vec(), id.clone()].concat(),
149 [dmp_queues.clone(), twox_64(&id).to_vec(), id].concat(),
151 ]
152 })
153 .collect::<Vec<_>>()
154 )
155 }
156
157 #[test]
158 fn supported_relay_chains() {
159 for (s, e) in [
160 ("paseo-local", Some(PaseoLocal)),
162 ("westend-local", Some(WestendLocal)),
163 ("kusama-local", None),
164 ("polkadot-local", None),
165 ] {
166 assert_eq!(RelayChain::from(s), e)
167 }
168 }
169}