From 2190613d3b5bcd9b74c382b22d151580b8ac271a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Bj=C3=B6rkqvist?= Date: Thu, 28 Nov 2024 17:00:44 +0100 Subject: [PATCH] test(ICRC_Ledger): FI-1589: Adapt icrc golden state tests to ledger V3 stable structures migration (#2739) The ICRC ledger does not support downgrading once allowances have been migrated to stable structures. This PR adapts the golden state tests accordingly. --------- Co-authored-by: Maciej Modelski Co-authored-by: IDX GitHub Automation Co-authored-by: maciejdfinity <122265298+maciejdfinity@users.noreply.github.com> Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com> --- WORKSPACE.bazel | 2 + mainnet-canisters.json | 4 + rs/ledger_suite/icrc1/BUILD.bazel | 2 + .../tests/golden_state_upgrade_downgrade.rs | 108 +++++++++++++----- 4 files changed, 87 insertions(+), 29 deletions(-) diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 2c28698c88f..3cabb35ab87 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -34,6 +34,7 @@ canisters( "sns_governance": "sns-governance-canister.wasm.gz", "swap": "sns-swap-canister.wasm.gz", "sns_ledger": "ic-icrc1-ledger.wasm.gz", + "sns_ledger_v2": "ic-icrc1-ledger.wasm.gz", "sns_archive": "ic-icrc1-archive.wasm.gz", "sns_index": "ic-icrc1-index-ng.wasm.gz", }, @@ -59,6 +60,7 @@ canisters( "sns_governance": "mainnet_sns-governance-canister", "swap": "mainnet_sns-swap-canister", "sns_ledger": "mainnet_ic-icrc1-ledger", + "sns_ledger_v2": "mainnet_ic-icrc1-ledger-v2", "sns_archive": "mainnet_ic-icrc1-archive", "sns_index": "mainnet_ic-icrc1-index-ng", }, diff --git a/mainnet-canisters.json b/mainnet-canisters.json index 13be50dcf62..e84a6b131e3 100644 --- a/mainnet-canisters.json +++ b/mainnet-canisters.json @@ -79,6 +79,10 @@ "rev": "e54d3fa34ded227c885d04e64505fa4b5d564743", "sha256": "3d808fa63a3d8ebd4510c0400aa078e99a31afaa0515f0b68778f929ce4b2a46" }, + "sns_ledger_v2": { + "rev": "e54d3fa34ded227c885d04e64505fa4b5d564743", + "sha256": "3d808fa63a3d8ebd4510c0400aa078e99a31afaa0515f0b68778f929ce4b2a46" + }, "sns_root": { "rev": "aa91ecacdf3824e193e21b70e0127e8d3edab51a", "sha256": "431cb333feb3f762f742b0dea58745633a2a2ca41075e9933183d850b4ddb259" diff --git a/rs/ledger_suite/icrc1/BUILD.bazel b/rs/ledger_suite/icrc1/BUILD.bazel index 5adb58c8d76..98cdb922ecb 100644 --- a/rs/ledger_suite/icrc1/BUILD.bazel +++ b/rs/ledger_suite/icrc1/BUILD.bazel @@ -129,6 +129,7 @@ rust_test( "@mainnet_cketh_ic-icrc1-ledger-u256//file", "@mainnet_ic-icrc1-archive//file", "@mainnet_ic-icrc1-index-ng//file", + "@mainnet_ic-icrc1-ledger-v2//file", "@mainnet_ic-icrc1-ledger//file", ], env = { @@ -142,6 +143,7 @@ rust_test( "IC_ICRC1_ARCHIVE_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_ic-icrc1-archive//file)", "IC_ICRC1_INDEX_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_ic-icrc1-index-ng//file)", "IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_ic-icrc1-ledger//file)", + "IC_ICRC1_LEDGER_DEPLOYED_VERSION_2_WASM_PATH": "$(rootpath @mainnet_ic-icrc1-ledger-v2//file)", "IC_ICRC1_ARCHIVE_WASM_PATH": "$(rootpath //rs/ledger_suite/icrc1/archive:archive_canister" + name_suffix + ".wasm.gz)", "IC_ICRC1_INDEX_NG_WASM_PATH": "$(rootpath //rs/ledger_suite/icrc1/index-ng:index_ng_canister" + name_suffix + ".wasm.gz)", "IC_ICRC1_LEDGER_WASM_PATH": "$(rootpath //rs/ledger_suite/icrc1/ledger:ledger_canister" + name_suffix + ".wasm)", diff --git a/rs/ledger_suite/icrc1/tests/golden_state_upgrade_downgrade.rs b/rs/ledger_suite/icrc1/tests/golden_state_upgrade_downgrade.rs index c36245c47ea..070915d955c 100644 --- a/rs/ledger_suite/icrc1/tests/golden_state_upgrade_downgrade.rs +++ b/rs/ledger_suite/icrc1/tests/golden_state_upgrade_downgrade.rs @@ -13,7 +13,7 @@ use ic_ledger_suite_state_machine_tests::{ TransactionGenerationParameters, }; use ic_nns_test_utils_golden_nns_state::new_state_machine_with_golden_fiduciary_state_or_panic; -use ic_state_machine_tests::StateMachine; +use ic_state_machine_tests::{ErrorCode, StateMachine, UserError}; use icrc_ledger_types::icrc1::account::Account; use lazy_static::lazy_static; use std::str::FromStr; @@ -44,7 +44,8 @@ lazy_static! { )), Wasm::from_bytes(load_wasm_using_env_var( "CKBTC_IC_ICRC1_ARCHIVE_DEPLOYED_VERSION_WASM_PATH", - )) + )), + None, ); pub static ref MAINNET_SNS_WASMS: Wasms = Wasms::new( Wasm::from_bytes(load_wasm_using_env_var( @@ -55,12 +56,16 @@ lazy_static! { )), Wasm::from_bytes(load_wasm_using_env_var( "IC_ICRC1_ARCHIVE_DEPLOYED_VERSION_WASM_PATH", - )) + )), + Some(Wasm::from_bytes(load_wasm_using_env_var( + "IC_ICRC1_LEDGER_DEPLOYED_VERSION_2_WASM_PATH" + ))), ); pub static ref MASTER_WASMS: Wasms = Wasms::new( Wasm::from_bytes(index_ng_wasm()), Wasm::from_bytes(ledger_wasm()), - Wasm::from_bytes(archive_wasm()) + Wasm::from_bytes(archive_wasm()), + None, ); } @@ -75,12 +80,14 @@ lazy_static! { )), Wasm::from_bytes(load_wasm_using_env_var( "CKETH_IC_ICRC1_ARCHIVE_DEPLOYED_VERSION_WASM_PATH", - )) + )), + None, ); pub static ref MASTER_WASMS: Wasms = Wasms::new( Wasm::from_bytes(index_ng_wasm()), Wasm::from_bytes(ledger_wasm()), - Wasm::from_bytes(archive_wasm()) + Wasm::from_bytes(archive_wasm()), + None, ); } @@ -88,14 +95,21 @@ pub struct Wasms { index_wasm: Wasm, ledger_wasm: Wasm, archive_wasm: Wasm, + ledger_wasm_v2: Option, } impl Wasms { - fn new(index_wasm: Wasm, ledger_wasm: Wasm, archive_wasm: Wasm) -> Self { + fn new( + index_wasm: Wasm, + ledger_wasm: Wasm, + archive_wasm: Wasm, + ledger_wasm_v2: Option, + ) -> Self { Self { index_wasm, ledger_wasm, archive_wasm, + ledger_wasm_v2, } } } @@ -188,7 +202,7 @@ impl LedgerSuiteConfig { } } - fn upgrade_archives(&self, state_machine: &StateMachine, wasm: &Wasm) { + fn upgrade_archives_or_panic(&self, state_machine: &StateMachine, wasm: &Wasm) { let canister_id = CanisterId::unchecked_from_principal(PrincipalId::from_str(self.ledger_id).unwrap()); let archives = list_archives(state_machine, canister_id); @@ -208,7 +222,7 @@ impl LedgerSuiteConfig { println!("Upgraded {} archive(s)", num_archives); } - fn upgrade_index(&self, state_machine: &StateMachine, wasm: &Wasm) { + fn upgrade_index_or_panic(&self, state_machine: &StateMachine, wasm: &Wasm) { let canister_id = CanisterId::unchecked_from_principal(PrincipalId::from_str(self.index_id).unwrap()); let index_upgrade_arg = IndexArg::Upgrade(IndexUpgradeArg { @@ -222,38 +236,74 @@ impl LedgerSuiteConfig { println!("Upgraded {} index '{}'", self.canister_name, self.index_id); } - fn upgrade_ledger(&self, state_machine: &StateMachine, wasm: &Wasm) { + fn upgrade_ledger(&self, state_machine: &StateMachine, wasm: &Wasm) -> Result<(), UserError> { let canister_id = CanisterId::unchecked_from_principal(PrincipalId::from_str(self.ledger_id).unwrap()); let args = ic_icrc1_ledger::LedgerArgument::Upgrade(None); let args = Encode!(&args).unwrap(); - state_machine - .upgrade_canister(canister_id, wasm.clone().bytes(), args.clone()) - .expect("should successfully upgrade ledger canister"); - println!( - "Upgraded {} ledger '{}'", - self.canister_name, self.ledger_id - ); + match state_machine.upgrade_canister(canister_id, wasm.clone().bytes(), args.clone()) { + Ok(_) => { + println!( + "Upgraded {} ledger '{}'", + self.canister_name, self.ledger_id + ); + Ok(()) + } + Err(e) => { + println!( + "Error upgrading {} ledger '{}': {:?}", + self.canister_name, self.ledger_id, e + ); + Err(e) + } + } } fn upgrade_to_mainnet(&self, state_machine: &StateMachine) { // Upgrade each canister twice to exercise pre-upgrade - self.upgrade_index(state_machine, &self.mainnet_wasms.index_wasm); - self.upgrade_index(state_machine, &self.mainnet_wasms.index_wasm); - self.upgrade_ledger(state_machine, &self.mainnet_wasms.ledger_wasm); - self.upgrade_ledger(state_machine, &self.mainnet_wasms.ledger_wasm); - self.upgrade_archives(state_machine, &self.mainnet_wasms.archive_wasm); - self.upgrade_archives(state_machine, &self.mainnet_wasms.archive_wasm); + self.upgrade_index_or_panic(state_machine, &self.mainnet_wasms.index_wasm); + self.upgrade_index_or_panic(state_machine, &self.mainnet_wasms.index_wasm); + match self.upgrade_ledger(state_machine, &self.mainnet_wasms.ledger_wasm) { + Ok(_) => { + panic!("should not successfully downgrade ledger"); + } + Err(user_error) => user_error.assert_contains( + ErrorCode::CanisterCalledTrap, + "Trying to downgrade from incompatible version", + ), + } + self.upgrade_archives_or_panic(state_machine, &self.mainnet_wasms.archive_wasm); + self.upgrade_archives_or_panic(state_machine, &self.mainnet_wasms.archive_wasm); } fn upgrade_to_master(&self, state_machine: &StateMachine) { // Upgrade each canister twice to exercise pre-upgrade - self.upgrade_index(state_machine, &self.master_wasms.index_wasm); - self.upgrade_index(state_machine, &self.master_wasms.index_wasm); - self.upgrade_ledger(state_machine, &self.master_wasms.ledger_wasm); - self.upgrade_ledger(state_machine, &self.master_wasms.ledger_wasm); - self.upgrade_archives(state_machine, &self.master_wasms.archive_wasm); - self.upgrade_archives(state_machine, &self.master_wasms.archive_wasm); + self.upgrade_index_or_panic(state_machine, &self.master_wasms.index_wasm); + self.upgrade_index_or_panic(state_machine, &self.master_wasms.index_wasm); + self.upgrade_ledger(state_machine, &self.master_wasms.ledger_wasm) + .or_else(|e| { + match ( + e.description().contains( + "Cannot upgrade from scratch stable memory, please upgrade to memory manager first." + ), + &self.mainnet_wasms.ledger_wasm_v2 + ) { + // The upgrade may fail if the target canister is too old - in the case of + // migration to stable structures, the ledger canister must be at least at V2, + // i.e., the ledger state must be managed by the memory manager. + (true, Some(wasm_v2)) => { + self.upgrade_ledger(state_machine, wasm_v2) + .expect("should successfully upgrade ledger to V2"); + self.upgrade_ledger(state_machine, &self.master_wasms.ledger_wasm) + } + _ => Err(e) + } + }) + .expect("should successfully upgrade ledger"); + self.upgrade_ledger(state_machine, &self.master_wasms.ledger_wasm) + .expect("should successfully upgrade ledger"); + self.upgrade_archives_or_panic(state_machine, &self.master_wasms.archive_wasm); + self.upgrade_archives_or_panic(state_machine, &self.master_wasms.archive_wasm); } }