zombienet_orchestrator/tx_helper/
parachain.rs

1use anyhow::anyhow;
2use subxt::{dynamic::Value, ext::codec::Encode, tx::DynamicPayload, OnlineClient, PolkadotConfig};
3
4/// Fetches the genesis header from a parachain node
5pub async fn fetch_genesis_header(
6    client: &OnlineClient<PolkadotConfig>,
7) -> Result<Vec<u8>, anyhow::Error> {
8    let genesis_hash = client.genesis_hash();
9    let header = client
10        .backend()
11        .block_header(genesis_hash)
12        .await?
13        .ok_or_else(|| anyhow!("Failed to fetch genesis header"))?;
14    Ok(header.encode())
15}
16
17/// Fetches the validation code from a parachain node
18pub async fn fetch_validation_code(
19    client: &OnlineClient<PolkadotConfig>,
20) -> Result<Vec<u8>, anyhow::Error> {
21    let code_key = sp_core::storage::well_known_keys::CODE;
22    client
23        .storage()
24        .at_latest()
25        .await?
26        .fetch_raw(code_key)
27        .await?
28        .ok_or_else(|| anyhow!("Failed to fetch validation code"))
29}
30
31/// Creates a sudo call to deregister a validator
32pub fn create_deregister_validator_call(stash_account: Value) -> DynamicPayload {
33    let deregister_call = Value::named_composite([(
34        "deregister_validators",
35        Value::named_composite([("validators", stash_account)]),
36    )]);
37
38    subxt::dynamic::tx(
39        "Sudo",
40        "sudo",
41        vec![Value::named_composite([(
42            "ValidatorManager",
43            deregister_call,
44        )])],
45    )
46}
47
48/// Creates a sudo call to register a validator
49pub fn create_register_validator_call(stash_account: Value) -> DynamicPayload {
50    let register_call = Value::named_composite([(
51        "register_validators",
52        Value::named_composite([("validators", stash_account)]),
53    )]);
54
55    subxt::dynamic::tx(
56        "Sudo",
57        "sudo",
58        vec![Value::named_composite([(
59            "ValidatorManager",
60            register_call,
61        )])],
62    )
63}
64
65/// Creates a sudo batch call to register a parachain with trusted validation code
66pub fn create_register_para_call(
67    genesis_header: &[u8],
68    validation_code: &[u8],
69    para_id: u32,
70    registrar_account: Value,
71) -> DynamicPayload {
72    let genesis_head_value = Value::from_bytes(genesis_header);
73    let validation_code_value = Value::from_bytes(validation_code);
74    let validation_code_for_trusted = Value::from_bytes(validation_code);
75
76    let add_trusted_code_call = Value::named_composite([(
77        "Paras",
78        Value::named_composite([(
79            "add_trusted_validation_code",
80            Value::named_composite([("validation_code", validation_code_for_trusted)]),
81        )]),
82    )]);
83
84    let force_register_call = Value::named_composite([(
85        "Registrar",
86        Value::named_composite([(
87            "force_register",
88            Value::named_composite([
89                ("who", registrar_account),
90                ("deposit", Value::u128(0)),
91                ("id", Value::u128(para_id as u128)),
92                ("genesis_head", genesis_head_value),
93                ("validation_code", validation_code_value),
94            ]),
95        )]),
96    )]);
97
98    let calls = Value::unnamed_composite(vec![add_trusted_code_call, force_register_call]);
99
100    subxt::dynamic::tx(
101        "Sudo",
102        "sudo",
103        vec![Value::named_composite([(
104            "Utility",
105            Value::named_composite([("batch", Value::named_composite([("calls", calls)]))]),
106        )])],
107    )
108}