use crate::{DynamicPayload, Error, call};
use scale::{Decode, Encode};
use sp_core::twox_128;
use subxt::{
OnlineClient,
dynamic::{self, Value},
events::StaticEvent,
ext::{scale_decode::DecodeAsType, scale_encode::EncodeAsType},
utils::H256,
};
pub async fn clear_dmpq(endpoint: &str, para_ids: &[u32]) -> Result<H256, Error> {
let client = OnlineClient::<subxt::PolkadotConfig>::from_url(endpoint)
.await
.map_err(|e| Error::SubXtError(e.into()))?;
let mut sub = client
.blocks()
.subscribe_finalized()
.await
.map_err(|e| Error::SubXtError(e.into()))?;
for _ in 0..2 {
sub.next().await;
}
let clear_dmq_keys = generate_storage_keys(para_ids);
let kill_storage = construct_kill_storage_call(clear_dmq_keys);
let sudo = subxt_signer::sr25519::dev::alice();
let sudo_call = call::construct_sudo_extrinsic(kill_storage);
client
.tx()
.sign_and_submit_default(&sudo_call, &sudo)
.await
.map_err(|e| Error::SubXtError(e.into()))
}
fn construct_kill_storage_call(keys: Vec<Vec<u8>>) -> DynamicPayload {
dynamic::tx(
"System",
"kill_storage",
vec![Value::unnamed_composite(keys.into_iter().map(Value::from_bytes))],
)
}
fn generate_storage_keys(para_ids: &[u32]) -> Vec<Vec<u8>> {
let dmp = twox_128("Dmp".as_bytes());
let dmp_queue_heads = twox_128("DownwardMessageQueueHeads".as_bytes());
let dmp_queues = twox_128("DownwardMessageQueues".as_bytes());
let mut clear_dmq_keys = Vec::<Vec<u8>>::new();
for id in para_ids {
let id = id.to_le_bytes();
let mut key = dmp.to_vec();
key.extend(&dmp_queue_heads);
key.extend(sp_core::twox_64(&id));
key.extend(id);
clear_dmq_keys.push(key);
let mut key = dmp.to_vec();
key.extend(&dmp_queues);
key.extend(sp_core::twox_64(&id));
key.extend(id);
clear_dmq_keys.push(key);
}
clear_dmq_keys
}
#[derive(Debug, PartialEq)]
pub enum RelayChain {
PaseoLocal,
WestendLocal,
}
impl RelayChain {
pub fn from(id: &str) -> Option<RelayChain> {
match id {
"paseo-local" => Some(RelayChain::PaseoLocal),
"westend-local" => Some(RelayChain::WestendLocal),
_ => None,
}
}
}
#[derive(Debug, Encode, Decode, DecodeAsType, EncodeAsType)]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
pub struct Reserved {
pub para_id: u32,
}
impl StaticEvent for Reserved {
const PALLET: &'static str = "Registrar";
const EVENT: &'static str = "Reserved";
}
#[cfg(test)]
mod tests {
use super::*;
use RelayChain::*;
use sp_core::twox_64;
#[test]
fn construct_kill_storage_call_works() {
let keys = vec!["key".as_bytes().to_vec()];
assert_eq!(
construct_kill_storage_call(keys.clone()),
dynamic::tx(
"System",
"kill_storage",
vec![Value::unnamed_composite(keys.into_iter().map(Value::from_bytes))],
)
)
}
#[test]
fn generate_storage_keys_works() {
let para_ids = vec![1_000, 4_385];
let dmp = twox_128("Dmp".as_bytes());
let dmp_queue_heads = [dmp, twox_128("DownwardMessageQueueHeads".as_bytes())].concat();
let dmp_queues = [dmp, twox_128("DownwardMessageQueues".as_bytes())].concat();
assert_eq!(
generate_storage_keys(¶_ids),
para_ids
.iter()
.flat_map(|id| {
let id = id.to_le_bytes().to_vec();
[
[dmp_queue_heads.clone(), twox_64(&id).to_vec(), id.clone()].concat(),
[dmp_queues.clone(), twox_64(&id).to_vec(), id].concat(),
]
})
.collect::<Vec<_>>()
)
}
#[test]
fn supported_relay_chains() {
for (s, e) in [
("paseo-local", Some(PaseoLocal)),
("westend-local", Some(WestendLocal)),
("kusama-local", None),
("polkadot-local", None),
] {
assert_eq!(RelayChain::from(s), e)
}
}
}