From 709a253e9f3d460e939df32a9a0c2646264024e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Demay?= Date: Fri, 22 May 2026 13:28:14 +0000 Subject: [PATCH] chore: DEFI-2304 remove deprecated ic-cdk imports in ic-ledger-suite-orchestrator Migrate the orchestrator off the deprecated `ic_cdk::api::management_canister::main::*`, `ic_cdk::api::call::{RejectionCode, call, call_with_payment, notify_with_payment128}`, `ic_cdk::id`, `ic_cdk::api::canister_balance128` and `ic_cdk::api::stable::stable_size` surfaces introduced in #6264, and drop the file-level `#![allow(deprecated)]` attributes. `IcCanisterRuntime` now uses the modern `ic_cdk::management_canister` functions and the `ic_cdk::call::Call` builder; the `Reason::from_reject` helper is rewritten on top of the new `CallFailed` / `OnewayError` enums while keeping the same `Reason` variants. `get_canister_status` now returns the modern `CanisterStatusResult`; `ledger_suite_orchestrator.did` is updated to mirror the new fields (matching the shape already adopted by the ckBTC and ckETH minters). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ledger_suite_orchestrator.did | 23 +- .../ledger-suite-orchestrator/src/main.rs | 16 +- .../src/management/mod.rs | 265 +++++++++--------- .../test_utils/src/lib.rs | 7 +- .../ledger-suite-orchestrator/tests/tests.rs | 1 - 5 files changed, 169 insertions(+), 143 deletions(-) diff --git a/rs/ethereum/ledger-suite-orchestrator/ledger_suite_orchestrator.did b/rs/ethereum/ledger-suite-orchestrator/ledger_suite_orchestrator.did index fb99e776c640..12bba8555717 100644 --- a/rs/ethereum/ledger-suite-orchestrator/ledger_suite_orchestrator.did +++ b/rs/ethereum/ledger-suite-orchestrator/ledger_suite_orchestrator.did @@ -206,19 +206,38 @@ type UpdateCyclesManagement = record { cycles_top_up_increment: opt nat; }; +type environment_variable = record { + name: text; + value: text; +}; + type CanisterStatusResponse = record { - query_stats : QueryStats; status : CanisterStatusType; + ready_for_migration : bool; + version : nat64; memory_size : nat; cycles : nat; settings : DefiniteCanisterSettings; idle_cycles_burned_per_day : nat; module_hash : opt vec nat8; + query_stats : QueryStats; reserved_cycles : nat; + memory_metrics : MemoryMetrics; }; type CanisterStatusType = variant { stopped; stopping; running }; +type MemoryMetrics = record { + wasm_memory_size : nat; + stable_memory_size : nat; + global_memory_size : nat; + wasm_binary_size : nat; + custom_sections_size : nat; + canister_history_size : nat; + wasm_chunk_store_size : nat; + snapshots_size : nat; +}; + type DefiniteCanisterSettings = record { freezing_threshold : nat; controllers : vec principal; @@ -227,6 +246,8 @@ type DefiniteCanisterSettings = record { reserved_cycles_limit : nat; log_visibility: LogVisibility; wasm_memory_limit : nat; + wasm_memory_threshold : nat; + environment_variables : vec environment_variable; }; type LogVisibility = variant { diff --git a/rs/ethereum/ledger-suite-orchestrator/src/main.rs b/rs/ethereum/ledger-suite-orchestrator/src/main.rs index b3c26d040697..5674bd461be0 100644 --- a/rs/ethereum/ledger-suite-orchestrator/src/main.rs +++ b/rs/ethereum/ledger-suite-orchestrator/src/main.rs @@ -1,7 +1,4 @@ -#![allow(deprecated)] -use ic_cdk::api::management_canister::main::{ - CanisterIdRecord, CanisterStatusResponse, canister_status, -}; +use ic_cdk::management_canister::{CanisterStatusArgs, CanisterStatusResult, canister_status}; use ic_cdk::{init, post_upgrade, query, update}; use ic_ledger_suite_orchestrator::candid::Erc20Contract as CandidErc20Contract; use ic_ledger_suite_orchestrator::candid::{ManagedCanisterIds, OrchestratorArg, OrchestratorInfo}; @@ -96,13 +93,12 @@ fn post_upgrade(orchestrator_arg: Option) { } #[update] -async fn get_canister_status() -> CanisterStatusResponse { - canister_status(CanisterIdRecord { - canister_id: ic_cdk::id(), +async fn get_canister_status() -> CanisterStatusResult { + canister_status(&CanisterStatusArgs { + canister_id: ic_cdk::api::canister_self(), }) .await .expect("failed to fetch canister status") - .0 } #[query(hidden = true)] @@ -200,7 +196,7 @@ fn http_request(req: ic_http_types::HttpRequest) -> ic_http_types::HttpResponse w.encode_gauge( "stable_memory_bytes", - ic_cdk::api::stable::stable_size() as f64 * WASM_PAGE_SIZE_IN_BYTES, + ic_cdk::stable::stable_size() as f64 * WASM_PAGE_SIZE_IN_BYTES, "Size of the stable memory allocated by this canister.", )?; @@ -213,7 +209,7 @@ fn http_request(req: ic_http_types::HttpRequest) -> ic_http_types::HttpResponse w.gauge_vec("cycle_balance", "Cycle balance of this canister.")? .value( &[("canister", "ledger-suite-orchestrator")], - ic_cdk::api::canister_balance128() as f64, + ic_cdk::api::canister_cycle_balance() as f64, )?; read_state(|s| { diff --git a/rs/ethereum/ledger-suite-orchestrator/src/management/mod.rs b/rs/ethereum/ledger-suite-orchestrator/src/management/mod.rs index c15ec11ff869..b27ca4e2a70b 100644 --- a/rs/ethereum/ledger-suite-orchestrator/src/management/mod.rs +++ b/rs/ethereum/ledger-suite-orchestrator/src/management/mod.rs @@ -1,12 +1,12 @@ -#![allow(deprecated)] use crate::logs::DEBUG; use async_trait::async_trait; use candid::{CandidType, Encode, Principal}; -use ic_base_types::PrincipalId; use ic_canister_log::log; -use ic_cdk::api::call::RejectionCode; -use ic_management_canister_types::{ - CanisterIdRecord, CanisterInstallMode, CanisterSettings, CreateCanisterArgs, InstallCodeArgs, +use ic_cdk::call::{Call, CallFailed, OnewayError, RejectCode}; +use ic_cdk::management_canister::{ + CanisterInstallMode, CanisterSettings, CanisterStatusArgs, CreateCanisterArgs, + DepositCyclesArgs, InstallCodeArgs, StartCanisterArgs, StopCanisterArgs, canister_status, + install_code, start_canister, stop_canister, }; use serde::de::DeserializeOwned; use std::fmt; @@ -75,16 +75,59 @@ impl fmt::Display for Reason { } impl Reason { - fn from_reject(reject_code: RejectionCode, reject_message: String) -> Self { + fn from_call_error(error: ic_cdk::call::Error) -> Self { + use ic_cdk::call::Error; + match error { + Error::CallRejected(rejected) => Self::from_reject_code_message( + rejected.reject_code(), + rejected.raw_reject_code(), + rejected.reject_message().to_string(), + ), + Error::InsufficientLiquidCycleBalance(_) => Self::OutOfCycles, + Error::CallPerformFailed(_) => Self::InternalError("call_perform failed".to_string()), + Error::CandidDecodeFailed(e) => { + Self::InternalError(format!("candid decode failed: {e}")) + } + } + } + + fn from_call_failed(failed: CallFailed) -> Self { + match failed { + CallFailed::CallRejected(rejected) => Self::from_reject_code_message( + rejected.reject_code(), + rejected.raw_reject_code(), + rejected.reject_message().to_string(), + ), + CallFailed::InsufficientLiquidCycleBalance(_) => Self::OutOfCycles, + CallFailed::CallPerformFailed(_) => { + Self::InternalError("call_perform failed".to_string()) + } + } + } + + fn from_oneway_error(error: OnewayError) -> Self { + match error { + OnewayError::InsufficientLiquidCycleBalance(_) => Self::OutOfCycles, + OnewayError::CallPerformFailed(_) => { + Self::InternalError("call_perform failed".to_string()) + } + } + } + + fn from_reject_code_message( + reject_code: Result, + raw_reject_code: u32, + message: String, + ) -> Self { match reject_code { - RejectionCode::SysTransient => Self::TransientInternalError(reject_message), - RejectionCode::CanisterError => Self::CanisterError(reject_message), - RejectionCode::CanisterReject => Self::Rejected(reject_message), - RejectionCode::NoError - | RejectionCode::SysFatal - | RejectionCode::DestinationInvalid - | RejectionCode::Unknown => Self::InternalError(format!( - "rejection code: {reject_code:?}, rejection message: {reject_message}" + Ok(RejectCode::SysTransient) => Self::TransientInternalError(message), + Ok(RejectCode::CanisterError) => Self::CanisterError(message), + Ok(RejectCode::CanisterReject) => Self::Rejected(message), + Ok(code) => Self::InternalError(format!( + "rejection code: {code:?}, rejection message: {message}" + )), + Err(_) => Self::InternalError(format!( + "unrecognized rejection code: {raw_reject_code}, rejection message: {message}" )), } } @@ -149,42 +192,10 @@ pub trait CanisterRuntime { #[derive(Copy, Clone)] pub struct IcCanisterRuntime {} -impl IcCanisterRuntime { - async fn call(&self, method: &str, payment: u64, input: &I) -> Result - where - I: CandidType, - O: CandidType + DeserializeOwned, - { - let balance = ic_cdk::api::canister_balance128(); - if balance < payment as u128 { - return Err(CallError { - method: method.to_string(), - reason: Reason::OutOfCycles, - }); - } - - let res: Result<(O,), _> = ic_cdk::api::call::call_with_payment( - Principal::management_canister(), - method, - (input,), - payment, - ) - .await; - - match res { - Ok((output,)) => Ok(output), - Err((code, msg)) => Err(CallError { - method: method.to_string(), - reason: Reason::from_reject(code, msg), - }), - } - } -} - #[async_trait] impl CanisterRuntime for IcCanisterRuntime { fn id(&self) -> Principal { - ic_cdk::id() + ic_cdk::api::canister_self() } fn time(&self) -> u64 { @@ -206,44 +217,53 @@ impl CanisterRuntime for IcCanisterRuntime { "BUG: too many controllers. Expected at most 10, got {}", controllers.len() ); + let payment = u128::from(cycles_for_canister_creation); + let balance = ic_cdk::api::canister_cycle_balance(); + if balance < payment { + return Err(CallError { + method: "create_canister".to_string(), + reason: Reason::OutOfCycles, + }); + } let create_args = CreateCanisterArgs { settings: Some(CanisterSettings { - controllers: controllers.into_iter().map(Into::into).collect(), + controllers: Some(controllers), ..Default::default() }), - ..Default::default() }; - let result: CanisterIdRecord = self - .call( - "create_canister", - cycles_for_canister_creation, - &create_args, - ) - .await?; + let result = Call::unbounded_wait(Principal::management_canister(), "create_canister") + .with_arg(&create_args) + .with_cycles(payment) + .await + .map_err(|err| CallError { + method: "create_canister".to_string(), + reason: Reason::from_call_failed(err), + })? + .candid::() + .map_err(|err| CallError { + method: "create_canister".to_string(), + reason: Reason::InternalError(format!("candid decode failed: {err}")), + })?; Ok(result.canister_id) } async fn stop_canister(&self, canister_id: Principal) -> Result<(), CallError> { - ic_cdk::api::management_canister::main::stop_canister( - ic_cdk::api::management_canister::main::CanisterIdRecord { canister_id }, - ) - .await - .map_err(|(code, msg)| CallError { - method: "stop_canister".to_string(), - reason: Reason::from_reject(code, msg), - }) + stop_canister(&StopCanisterArgs { canister_id }) + .await + .map_err(|err| CallError { + method: "stop_canister".to_string(), + reason: Reason::from_call_error(err), + }) } async fn start_canister(&self, canister_id: Principal) -> Result<(), CallError> { - ic_cdk::api::management_canister::main::start_canister( - ic_cdk::api::management_canister::main::CanisterIdRecord { canister_id }, - ) - .await - .map_err(|(code, msg)| CallError { - method: "start_canister".to_string(), - reason: Reason::from_reject(code, msg), - }) + start_canister(&StartCanisterArgs { canister_id }) + .await + .map_err(|err| CallError { + method: "start_canister".to_string(), + reason: Reason::from_call_error(err), + }) } async fn install_code( @@ -252,17 +272,17 @@ impl CanisterRuntime for IcCanisterRuntime { wasm_module: Vec, arg: Vec, ) -> Result<(), CallError> { - let install_code = InstallCodeArgs { + install_code(&InstallCodeArgs { mode: CanisterInstallMode::Install, - canister_id: PrincipalId::from(canister_id).into(), + canister_id, wasm_module, arg, - sender_canister_version: None, - }; - - () = self.call("install_code", 0, &install_code).await?; - - Ok(()) + }) + .await + .map_err(|err| CallError { + method: "install_code".to_string(), + reason: Reason::from_call_error(err), + }) } async fn upgrade_canister( @@ -270,53 +290,39 @@ impl CanisterRuntime for IcCanisterRuntime { canister_id: Principal, wasm_module: Vec, ) -> Result<(), CallError> { - let install_code = InstallCodeArgs { + install_code(&InstallCodeArgs { mode: CanisterInstallMode::Upgrade(None), - canister_id: PrincipalId::from(canister_id).into(), + canister_id, wasm_module, arg: Encode!(&()).unwrap(), - sender_canister_version: None, - }; - - () = self.call("install_code", 0, &install_code).await?; - - Ok(()) + }) + .await + .map_err(|err| CallError { + method: "install_code".to_string(), + reason: Reason::from_call_error(err), + }) } async fn canister_cycles(&self, canister_id: Principal) -> Result { - let result = ic_cdk::api::management_canister::main::canister_status( - ic_cdk::api::management_canister::main::CanisterIdRecord { canister_id }, - ) - .await - .map_err(|(code, msg)| CallError { - method: "canister_status".to_string(), - reason: Reason::from_reject(code, msg), - })? - .0 - .cycles - .0 - .try_into() - .unwrap(); - - Ok(result) + let result = canister_status(&CanisterStatusArgs { canister_id }) + .await + .map_err(|err| CallError { + method: "canister_status".to_string(), + reason: Reason::from_call_error(err), + })?; + + Ok(result.cycles.0.try_into().unwrap()) } fn send_cycles(&self, canister_id: Principal, cycles: u128) -> Result<(), CallError> { - #[derive(CandidType)] - struct DepositCyclesArgs { - canister_id: Principal, - } - - ic_cdk::api::call::notify_with_payment128( - Principal::management_canister(), - "deposit_cycles", - (DepositCyclesArgs { canister_id },), - cycles, - ) - .map_err(|reject_code| CallError { - method: "send_cycles".to_string(), - reason: Reason::from_reject(reject_code, String::default()), - }) + Call::unbounded_wait(Principal::management_canister(), "deposit_cycles") + .with_arg(&DepositCyclesArgs { canister_id }) + .with_cycles(cycles) + .oneway() + .map_err(|err| CallError { + method: "send_cycles".to_string(), + reason: Reason::from_oneway_error(err), + }) } async fn call_canister( @@ -336,7 +342,19 @@ impl CanisterRuntime for IcCanisterRuntime { method, args ); - let res: Result<(O,), _> = ic_cdk::api::call::call(canister_id, method, (&args,)).await; + let res: Result = Call::unbounded_wait(canister_id, method) + .with_arg(&args) + .await + .map_err(|err| CallError { + method: method.to_string(), + reason: Reason::from_call_failed(err), + }) + .and_then(|response| { + response.candid::().map_err(|err| CallError { + method: method.to_string(), + reason: Reason::InternalError(format!("candid decode failed: {err}")), + }) + }); log!( DEBUG, "Result of calling canister '{}' with method '{}' and payload '{:?}': {:?}", @@ -345,13 +363,6 @@ impl CanisterRuntime for IcCanisterRuntime { args, res ); - - match res { - Ok((output,)) => Ok(output), - Err((code, msg)) => Err(CallError { - method: method.to_string(), - reason: Reason::from_reject(code, msg), - }), - } + res } } diff --git a/rs/ethereum/ledger-suite-orchestrator/test_utils/src/lib.rs b/rs/ethereum/ledger-suite-orchestrator/test_utils/src/lib.rs index fe70301e76d6..844f72bc516b 100644 --- a/rs/ethereum/ledger-suite-orchestrator/test_utils/src/lib.rs +++ b/rs/ethereum/ledger-suite-orchestrator/test_utils/src/lib.rs @@ -1,9 +1,8 @@ -#![allow(deprecated)] use crate::flow::{AddErc20TokenFlow, ManagedCanistersAssert}; use assert_matches::assert_matches; use candid::{Decode, Encode, Nat, Principal}; use ic_base_types::{CanisterId, PrincipalId}; -use ic_cdk::api::management_canister::main::CanisterStatusResponse; +use ic_cdk::management_canister::CanisterStatusResult; use ic_ledger_suite_orchestrator::candid::{ AddErc20Arg, CyclesManagement, Erc20Contract, InitArg, InstalledCanister, InstalledLedgerSuite, LedgerInitArg, ManagedCanisterIds, OrchestratorArg, OrchestratorInfo, UpgradeArg, @@ -145,7 +144,7 @@ impl LedgerSuiteOrchestrator { ) } - pub fn get_canister_status(&self) -> CanisterStatusResponse { + pub fn get_canister_status(&self) -> CanisterStatusResult { Decode!( &assert_reply( self.env @@ -156,7 +155,7 @@ impl LedgerSuiteOrchestrator { ) .expect("failed to call get_canister_status") ), - CanisterStatusResponse + CanisterStatusResult ) .unwrap() } diff --git a/rs/ethereum/ledger-suite-orchestrator/tests/tests.rs b/rs/ethereum/ledger-suite-orchestrator/tests/tests.rs index f10408c49ff4..b69d3c1b9630 100644 --- a/rs/ethereum/ledger-suite-orchestrator/tests/tests.rs +++ b/rs/ethereum/ledger-suite-orchestrator/tests/tests.rs @@ -1,4 +1,3 @@ -#![allow(deprecated)] use assert_matches::assert_matches; use candid::{Decode, Encode, Nat, Principal}; use ic_base_types::{CanisterId, PrincipalId};