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