Skip to main content

zombienet_orchestrator/tx_helper/
runtime_upgrade.rs

1use subxt::{dynamic::Value, tx::TxStatus, OnlineClient, SubstrateConfig};
2use subxt_signer::sr25519::Keypair;
3use tracing::{debug, info};
4
5use crate::network::node::NetworkNode;
6
7pub async fn upgrade(
8    node: &NetworkNode,
9    wasm_data: &[u8],
10    sudo: &Keypair,
11) -> Result<(), anyhow::Error> {
12    debug!(
13        "Upgrading runtime, using node: {} with endpoting {}",
14        node.name(),
15        node.ws_uri
16    );
17    let api: OnlineClient<SubstrateConfig> = node.wait_client().await?;
18
19    let upgrade = subxt::dynamic::tx(
20        "System",
21        "set_code_without_checks",
22        vec![Value::from_bytes(wasm_data)],
23    );
24
25    let sudo_call = subxt::dynamic::tx(
26        "Sudo",
27        "sudo_unchecked_weight",
28        vec![
29            upgrade.into_value(),
30            Value::named_composite([
31                ("ref_time", Value::primitive(1.into())),
32                ("proof_size", Value::primitive(1.into())),
33            ]),
34        ],
35    );
36
37    let mut tx = api
38        .tx()
39        .sign_and_submit_then_watch_default(&sudo_call, sudo)
40        .await?;
41
42    // Below we use the low level API to replicate the `wait_for_in_block` behaviour
43    // which was removed in subxt 0.33.0. See https://github.com/paritytech/subxt/pull/1237.
44    while let Some(status) = tx.next().await {
45        let status = status?;
46        match &status {
47            TxStatus::InBestBlock(tx_in_block) | TxStatus::InFinalizedBlock(tx_in_block) => {
48                let _result = tx_in_block.wait_for_success().await?;
49                let block_status = if status.as_finalized().is_some() {
50                    "Finalized"
51                } else {
52                    "Best"
53                };
54                info!(
55                    "[{}] In block: {:#?}",
56                    block_status,
57                    tx_in_block.block_hash()
58                );
59            },
60            TxStatus::Error { message }
61            | TxStatus::Invalid { message }
62            | TxStatus::Dropped { message } => {
63                return Err(anyhow::format_err!("Error submitting tx: {message}"));
64            },
65            _ => continue,
66        }
67    }
68
69    Ok(())
70}