From 1d3cc48288cc8917f01cd867c574d90f08cfdbb0 Mon Sep 17 00:00:00 2001 From: mraszyk <31483726+mraszyk@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:56:02 +0100 Subject: [PATCH] feat: configure PocketIC SNS and PocketIC default subnet in NNS canisters (#160) * feat: configure PocketIC SNS and default subnet in NNS canisters * changelog * fix * fix --- .github/workflows/e2e.yml | 2 +- Cargo.lock | 32 +++++++++++++++++++++++++- Cargo.toml | 1 + extensions/nns/CHANGELOG.md | 1 + extensions/nns/Cargo.toml | 1 + extensions/nns/e2e/tests/nns.bash | 31 ++++++++++++++++++++----- extensions/nns/src/install_nns.rs | 38 +++++++++++++++++++++++-------- 7 files changed, 88 insertions(+), 18 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6eae456..cbbe955 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -45,7 +45,7 @@ jobs: - name: Install IC SDK (dfx) uses: dfinity/setup-dfx@main with: - dfx-version: "0.24.1" + dfx-version: "0.24.2" - name: Set prebuilt extensions directory run: echo "PREBUILT_EXTENSIONS_DIR=$HOME/prebuilt-extensions" >> $GITHUB_ENV - name: Build extension manually diff --git a/Cargo.lock b/Cargo.lock index dab706f..3783b2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3009,7 +3009,7 @@ dependencies = [ "ic-sns-root", "ic-sns-swap", "ic-sns-wasm", - "pocket-ic", + "pocket-ic 5.0.0", "serde", "tempfile", "thiserror", @@ -4614,6 +4614,7 @@ dependencies = [ "ic-icrc1-ledger", "ic-sns-cli", "ic-utils 0.38.0", + "pocket-ic 6.0.0", "reqwest 0.11.27", "rust_decimal", "serde", @@ -5072,6 +5073,35 @@ dependencies = [ "wslpath", ] +[[package]] +name = "pocket-ic" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "124a2380ca6f557adf8b02517cbfd2f564113230e14cda6f6aadd3dfe156293c" +dependencies = [ + "base64 0.13.1", + "candid", + "hex", + "ic-certification", + "ic-transport-types 0.37.1", + "reqwest 0.12.9", + "schemars", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "slog", + "strum", + "strum_macros", + "thiserror", + "tokio", + "tracing", + "tracing-appender", + "tracing-subscriber", + "wslpath", +] + [[package]] name = "polling" version = "2.8.0" diff --git a/Cargo.toml b/Cargo.toml index bd08229..8d0a2a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ fn-error-context = "0.2.1" futures-util = "0.3.28" ic-agent = "=0.38.0" ic-utils = "=0.38.0" +pocket-ic = "6.0.0" reqwest = { version = "^0.11.22", default-features = false, features = [ "blocking", "json", diff --git a/extensions/nns/CHANGELOG.md b/extensions/nns/CHANGELOG.md index f2b9a7a..32b18e8 100644 --- a/extensions/nns/CHANGELOG.md +++ b/extensions/nns/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] - ReleaseDate - Fixed a bug where `dfx nns install` and `dfx nns import` would fail if a canister type in dfx.json was defined by an extension. - Added support for application subnets for `dfx start --pocketic`. +- Configure the PocketIC SNS subnet in the SNS-W canister and the default subnet in the CMC canister. ## [0.4.7] - 2024-11-08 - Added support for `dfx start --pocketic`. diff --git a/extensions/nns/Cargo.toml b/extensions/nns/Cargo.toml index 50d6f2e..0cc3407 100644 --- a/extensions/nns/Cargo.toml +++ b/extensions/nns/Cargo.toml @@ -30,6 +30,7 @@ ic-icrc1-index-ng.workspace = true ic-icrc1-ledger.workspace = true ic-http-utils.workspace = true hex = "0.4.3" +pocket-ic.workspace = true reqwest.workspace = true rust_decimal = "1.29.1" serde.workspace = true diff --git a/extensions/nns/e2e/tests/nns.bash b/extensions/nns/e2e/tests/nns.bash index ff1bf1e..0b7da9d 100755 --- a/extensions/nns/e2e/tests/nns.bash +++ b/extensions/nns/e2e/tests/nns.bash @@ -101,6 +101,30 @@ assert_nns_canister_id_matches() { if [[ "$USE_POCKET_IC" ]] then assert_success + + SNS_SUBNET_ID=$(curl http://localhost:8080/_/topology | jq -r '.subnet_configs | map_values(select(.subnet_kind=="SNS")) | keys[]') + if [[ "${SNS_SUBNET_ID}" == "" ]] + then + echo "No SNS subnet found in the PocketIC instance topology." + exit 1 + fi + run dfx canister call qaa6y-5yaaa-aaaaa-aaafa-cai get_sns_subnet_ids '(record {})' --query + assert_success + assert_output --partial "${SNS_SUBNET_ID}" + + APP_SUBNET_ID=$(curl http://localhost:8080/_/topology | jq -r '.subnet_configs | map_values(select(.subnet_kind=="Application")) | keys[]') + if [[ "${APP_SUBNET_ID}" == "" ]] + then + echo "No application subnet found in the PocketIC instance topology." + exit 1 + fi + while [[ "$(dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get_default_subnets '()' --query | grep "${APP_SUBNET_ID}")" == "" ]] + do + sleep 1 + done + run dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get_default_subnets '()' --query + assert_success + assert_output --partial "${APP_SUBNET_ID}" else assert_failure assert_output --partial "The replica subnet_type needs to be 'system' to run NNS canisters." @@ -181,12 +205,7 @@ assert_nns_canister_id_matches() { run dfx --identity ident-1 canister call rkp4c-7iaaa-aaaaa-aaaca-cai notify_mint_cycles '(record { block_index = 5 : nat64; })' # If cycles ledger is configured correctly, then notify_mint_cycles will try to call the cycles ledger (and fail because the canister is not even created). # If it is not configured correctly, then this will complain about the cycles ledger canister id not being configured. - if [ "$USE_POCKET_IC" ] - then - assert_output --partial "No route to canister um5iw-rqaaa-aaaaq-qaaba-cai" - else - assert_output --partial "Canister um5iw-rqaaa-aaaaq-qaaba-cai not found" - fi + assert_output --partial "Canister um5iw-rqaaa-aaaaq-qaaba-cai not found" } @test "dfx nns install with a canister type defined by another extension" { diff --git a/extensions/nns/src/install_nns.rs b/extensions/nns/src/install_nns.rs index c158051..6792110 100644 --- a/extensions/nns/src/install_nns.rs +++ b/extensions/nns/src/install_nns.rs @@ -34,6 +34,7 @@ use ic_icrc1_index_ng::{IndexArg, InitArg as IndexInitArg}; use ic_icrc1_ledger::{InitArgsBuilder, LedgerArgument}; use ic_utils::interfaces::management_canister::builders::InstallMode; use ic_utils::interfaces::ManagementCanister; +use pocket_ic::common::rest::Topology; use reqwest::Url; use serde::Serialize; use sha2::{Digest, Sha256}; @@ -89,23 +90,40 @@ pub async fn install_nns( logger: &Logger, ) -> anyhow::Result<()> { eprintln!("Checking out the environment..."); - // check if we're talking to PocketIC defaulting to false if we aren't sure - let is_pocketic = if let Some(descriptor) = &network.local_server_descriptor { - // PocketIC server has `/_/topology` endpoint while the replica does not + // Retrieve the PocketIC instance topology. + let topology = if let Some(descriptor) = &network.local_server_descriptor { let endpoint = format!("http://{}/_/topology", descriptor.bind_address); - let status = reqwest::get(endpoint).await?.status(); - status.is_success() + let resp = reqwest::get(endpoint).await?; + if resp.status().is_success() { + Some(resp.json::().await?) + } else { + None + } } else { - false + None }; // PocketIC has multiple subnets and thus supports default application subnet type. - if !is_pocketic { + if topology.is_none() { verify_local_replica_type_is_system(network, networks_config)?; } verify_nns_canister_ids_are_available(agent).await?; let provider_url = get_and_check_provider(network)?; let nns_url = provider_url.clone(); - let subnet_id = get_subnet_id(agent).await?.to_text(); + let root_subnet_id = get_subnet_id(agent).await?; + let sns_subnet_id = topology + .as_ref() + .and_then(|topology| topology.get_sns()) + .unwrap_or(root_subnet_id); + let default_subnet_id = topology + .as_ref() + .and_then(|topology| { + topology + .get_app_subnets() + .first() + .cloned() + .or_else(|| topology.get_system_subnets().first().cloned()) + }) + .unwrap_or(root_subnet_id); eprintln!("Installing the core backend wasm canisters..."); download_nns_wasms(dfx_cache_path).await?; @@ -118,7 +136,7 @@ pub async fn install_nns( wasm_dir: nns_wasm_dir(dfx_cache_path), nns_url: nns_url.to_string(), test_accounts, - sns_subnets: Some(subnet_id.to_string()), + sns_subnets: Some(sns_subnet_id.to_string()), local_registry_file: network.local_server_descriptor.as_ref().map(|desc| { desc.data_dir_by_settings_digest() .join("state/replicated_state/registry.proto") @@ -240,7 +258,7 @@ pub async fn install_nns( // ... and configure the backend NNS canisters: eprintln!("Configuring the NNS..."); set_xdr_rate(1234567, &nns_url, dfx_cache_path)?; - set_cmc_authorized_subnets(&nns_url, &subnet_id, dfx_cache_path)?; + set_cmc_authorized_subnets(&nns_url, &default_subnet_id.to_string(), dfx_cache_path)?; set_cycles_ledger_canister_id_in_cmc(&nns_url, dfx_cache_path)?; print_nns_details(provider_url)?;