diff --git a/Cargo.lock b/Cargo.lock index 0acdfac6009..edb28fc101e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10455,11 +10455,11 @@ dependencies = [ "candid_parser", "canister-test", "dfn_candid", - "dfn_core", - "dfn_macro", "hex", "ic-base-types", "ic-canisters-http-types", + "ic-cdk 0.16.0", + "ic-cdk-macros 0.9.0", "ic-crypto-sha2", "ic-management-canister-types", "ic-metrics-encoder", @@ -10503,6 +10503,7 @@ dependencies = [ "dfn_candid", "dfn_core", "ic-base-types", + "ic-cdk 0.16.0", "ic-nervous-system-clients", "ic-nns-constants", "serde", diff --git a/rs/nns/handlers/root/impl/BUILD.bazel b/rs/nns/handlers/root/impl/BUILD.bazel index 4f8758f7795..4ac7d056804 100644 --- a/rs/nns/handlers/root/impl/BUILD.bazel +++ b/rs/nns/handlers/root/impl/BUILD.bazel @@ -30,13 +30,13 @@ BASE_DEPENDENCIES = [ "//rs/registry/routing_table", "//rs/registry/transport", "//rs/rust_canisters/dfn_candid", - "//rs/rust_canisters/dfn_core", "//rs/rust_canisters/http_types", "//rs/rust_canisters/on_wire", "//rs/types/base_types", "//rs/types/management_canister_types", "@crate_index//:build-info", "@crate_index//:candid", + "@crate_index//:ic-cdk", "@crate_index//:ic-metrics-encoder", "@crate_index//:lazy_static", "@crate_index//:maplit", @@ -54,7 +54,7 @@ DEPENDENCIES_WITH_TEST_FEATURES = BASE_DEPENDENCIES MACRO_DEPENDENCIES = [ # Keep sorted. "//rs/nervous_system/common/build_metadata", - "//rs/rust_canisters/dfn_macro", + "@crate_index//:ic-cdk-macros", ] BUILD_DEPENDENCIES = [ diff --git a/rs/nns/handlers/root/impl/Cargo.toml b/rs/nns/handlers/root/impl/Cargo.toml index 732834ec4db..3e591c022d4 100644 --- a/rs/nns/handlers/root/impl/Cargo.toml +++ b/rs/nns/handlers/root/impl/Cargo.toml @@ -21,10 +21,10 @@ path = "src/lib.rs" build-info = { workspace = true } candid = { workspace = true } dfn_candid = { path = "../../../../rust_canisters/dfn_candid" } -dfn_core = { path = "../../../../rust_canisters/dfn_core" } -dfn_macro = { path = "../../../../rust_canisters/dfn_macro" } ic-base-types = { path = "../../../../types/base_types" } ic-canisters-http-types = { path = "../../../../rust_canisters/http_types" } +ic-cdk = { workspace = true } +ic-cdk-macros = { workspace = true } ic-crypto-sha2 = { path = "../../../../crypto/sha2" } ic-management-canister-types = { path = "../../../../types/management_canister_types" } ic-metrics-encoder = "1" diff --git a/rs/nns/handlers/root/impl/canister/canister.rs b/rs/nns/handlers/root/impl/canister/canister.rs index 030fb4878bf..1a4b3e334ac 100644 --- a/rs/nns/handlers/root/impl/canister/canister.rs +++ b/rs/nns/handlers/root/impl/canister/canister.rs @@ -1,10 +1,3 @@ -use candid::candid_method; -use dfn_candid::{candid, candid_one, candid_one_with_config}; -use dfn_core::{ - api::caller, - endpoint::{over, over_async}, - stable, -}; use ic_base_types::{CanisterId, PrincipalId}; use ic_canisters_http_types::{HttpRequest, HttpResponse, HttpResponseBuilder}; use ic_nervous_system_clients::{ @@ -23,7 +16,7 @@ use ic_nervous_system_root::{ }, LOG_PREFIX, }; -use ic_nervous_system_runtime::DfnRuntime; +use ic_nervous_system_runtime::CdkRuntime; use ic_nns_common::{ access_control::{check_caller_is_governance, check_caller_is_sns_w}, types::CallCanisterProposal, @@ -43,7 +36,12 @@ use ic_nns_handler_root_interface::{ use std::cell::RefCell; #[cfg(target_arch = "wasm32")] -use dfn_core::println; +use ic_cdk::println; +use ic_cdk::{post_upgrade, query, spawn, update}; + +fn caller() -> PrincipalId { + PrincipalId::from(ic_cdk::caller()) +} thread_local! { // How this value was chosen: queues become full at 500. This is 1/3 of that, which seems to be @@ -53,7 +51,7 @@ thread_local! { fn new_management_canister_client() -> impl ManagementCanisterClient { let client = - ManagementCanisterClientImpl::::new(Some(&PROXIED_CANISTER_CALLS_TRACKER)); + ManagementCanisterClientImpl::::new(Some(&PROXIED_CANISTER_CALLS_TRACKER)); // Here, VIP = is an NNS canister let is_caller_vip = CanisterId::try_from(caller()) @@ -72,20 +70,15 @@ fn new_management_canister_client() -> impl ManagementCanisterClient { // messages are quite obscure. #[export_name = "canister_init"] fn canister_init() { - dfn_core::printer::hook(); println!("{}canister_init", LOG_PREFIX); } -#[export_name = "canister_post_upgrade"] +#[post_upgrade] fn canister_post_upgrade() { - dfn_core::printer::hook(); println!("{}canister_post_upgrade", LOG_PREFIX); - // Wipe out stable memory, because earlier version of this canister were - // stateful. This minimizes risk of future misinterpretation of data. - stable::set(&[]); } -ic_nervous_system_common_build_metadata::define_get_build_metadata_candid_method! {} +ic_nervous_system_common_build_metadata::define_get_build_metadata_candid_method_cdk! {} /// Returns the status of the canister specified in the input. /// @@ -94,13 +87,8 @@ ic_nervous_system_common_build_metadata::define_get_build_metadata_candid_method /// /// This must be an update, not a query, because an inter-canister call to the /// management canister is required. -#[export_name = "canister_update canister_status"] -fn canister_status() { - over_async(candid_one, canister_status_) -} - -#[candid_method(update, rename = "canister_status")] -async fn canister_status_(canister_id_record: CanisterIdRecord) -> CanisterStatusResult { +#[update] +async fn canister_status(canister_id_record: CanisterIdRecord) -> CanisterStatusResult { let client = new_management_canister_client(); let canister_status_response = client @@ -111,58 +99,44 @@ async fn canister_status_(canister_id_record: CanisterIdRecord) -> CanisterStatu canister_status_response.unwrap() } -#[export_name = "canister_update submit_root_proposal_to_upgrade_governance_canister"] -fn submit_root_proposal_to_upgrade_governance_canister() { - over_async( - candid, - |(expected_governance_wasm_sha, proposal): ( - serde_bytes::ByteBuf, - ChangeCanisterRequest, - )| { - ic_nns_handler_root::root_proposals::submit_root_proposal_to_upgrade_governance_canister( - caller(), - expected_governance_wasm_sha.to_vec(), - proposal, - ) - }, - ); +#[update(hidden = true)] +async fn submit_root_proposal_to_upgrade_governance_canister( + expected_governance_wasm_sha: serde_bytes::ByteBuf, + proposal: ChangeCanisterRequest, +) -> Result<(), String> { + ic_nns_handler_root::root_proposals::submit_root_proposal_to_upgrade_governance_canister( + caller(), + expected_governance_wasm_sha.to_vec(), + proposal, + ) + .await } -#[export_name = "canister_update vote_on_root_proposal_to_upgrade_governance_canister"] -fn vote_on_root_proposal_to_upgrade_governance_canister() { - over_async( - candid, - |(proposer, wasm_sha256, ballot): ( - PrincipalId, - serde_bytes::ByteBuf, - RootProposalBallot, - )| { - ic_nns_handler_root::root_proposals::vote_on_root_proposal_to_upgrade_governance_canister( - caller(), - proposer, - wasm_sha256.to_vec(), - ballot, - ) - }, - ); +#[update(hidden = true)] +async fn vote_on_root_proposal_to_upgrade_governance_canister( + proposer: PrincipalId, + wasm_sha256: serde_bytes::ByteBuf, + ballot: RootProposalBallot, +) -> Result<(), String> { + ic_nns_handler_root::root_proposals::vote_on_root_proposal_to_upgrade_governance_canister( + caller(), + proposer, + wasm_sha256.to_vec(), + ballot, + ) + .await } -#[export_name = "canister_update get_pending_root_proposals_to_upgrade_governance_canister"] -fn get_pending_root_proposals_to_upgrade_governance_canister() { - over(candid, |()| -> Vec { - ic_nns_handler_root::root_proposals::get_pending_root_proposals_to_upgrade_governance_canister() - }) +#[update(hidden = true)] +fn get_pending_root_proposals_to_upgrade_governance_canister() -> Vec +{ + ic_nns_handler_root::root_proposals::get_pending_root_proposals_to_upgrade_governance_canister() } /// Executes a proposal to change an NNS canister. -#[export_name = "canister_update change_nns_canister"] -fn change_nns_canister() { +#[update] +fn change_nns_canister(request: ChangeCanisterRequest) { check_caller_is_governance(); - over(candid_one, change_nns_canister_); -} - -#[candid_method(update, rename = "change_nns_canister")] -fn change_nns_canister_(request: ChangeCanisterRequest) { // We want to reply first, so that in the case that we want to upgrade the // governance canister, the root canister no longer holds a pending callback // to it -- and therefore does not prevent the governance canister from being @@ -176,7 +150,7 @@ fn change_nns_canister_(request: ChangeCanisterRequest) { // Because change_canister is async, and because we can't directly use // `await`, we need to use the `spawn` trick. let future = async move { - let change_canister_result = change_canister::(request).await; + let change_canister_result = change_canister::(request).await; match change_canister_result { Ok(()) => { println!("{LOG_PREFIX}change_canister: Canister change completed successfully."); @@ -189,29 +163,19 @@ fn change_nns_canister_(request: ChangeCanisterRequest) { // Starts the proposal execution, which will continue after this function has // returned. - dfn_core::api::futures::spawn(future); + spawn(future); } -#[export_name = "canister_update add_nns_canister"] -fn add_nns_canister() { +#[update] +async fn add_nns_canister(request: AddCanisterRequest) { check_caller_is_governance(); - over_async(candid_one, add_nns_canister_) -} - -#[candid_method(update, rename = "add_nns_canister")] -async fn add_nns_canister_(request: AddCanisterRequest) { canister_management::do_add_nns_canister(request).await; } // Executes a proposal to stop/start an nns canister. -#[export_name = "canister_update stop_or_start_nns_canister"] -fn stop_or_start_nns_canister() { +#[update] +async fn stop_or_start_nns_canister(request: StopOrStartCanisterRequest) { check_caller_is_governance(); - over_async(candid_one, stop_or_start_nns_canister_) -} - -#[candid_method(update, rename = "stop_or_start_nns_canister")] -async fn stop_or_start_nns_canister_(request: StopOrStartCanisterRequest) { // It is a mistake to stop the root or governance canister, because if either of them is // stopped, there is no way to restore them to the running state. That would require executing a // proposal, but executing such proposals requires both of those canisters. Lifelife plays a @@ -231,30 +195,21 @@ async fn stop_or_start_nns_canister_(request: StopOrStartCanisterRequest) { .unwrap() // For compatibility. } -#[export_name = "canister_update call_canister"] -fn call_canister() { +#[update(hidden = true)] +fn call_canister(proposal: CallCanisterProposal) { check_caller_is_governance(); - over_async(candid, |(proposal,): (CallCanisterProposal,)| async move { - // Starts the proposal execution, which will continue after this function has returned. - let future = canister_management::call_canister(proposal); - dfn_core::api::futures::spawn(future); - }); + // Starts the proposal execution, which will continue after this function has returned. + let future = canister_management::call_canister(proposal); + spawn(future); } /// Change the controllers of a canister controlled by NNS Root. Only callable /// by SNS-W. -#[export_name = "canister_update change_canister_controllers"] -fn change_canister_controllers() { - check_caller_is_sns_w(); - over_async(candid_one, change_canister_controllers_) -} - -/// Change the controllers of a canister controlled by NNS Root. Only callable -/// by SNS-W. -#[candid_method(update, rename = "change_canister_controllers")] -async fn change_canister_controllers_( +#[update] +async fn change_canister_controllers( change_canister_controllers_request: ChangeCanisterControllersRequest, ) -> ChangeCanisterControllersResponse { + check_caller_is_sns_w(); canister_management::change_canister_controllers( change_canister_controllers_request, &mut new_management_canister_client(), @@ -264,16 +219,11 @@ async fn change_canister_controllers_( /// Updates the canister settings of a canister controlled by NNS Root. Only callable by NNS /// Governance. -#[export_name = "canister_update update_canister_settings"] -fn update_canister_settings() { - check_caller_is_governance(); - over_async(candid_one, update_canister_settings_); -} - -#[candid_method(update, rename = "update_canister_settings")] -async fn update_canister_settings_( +#[update] +async fn update_canister_settings( update_settings: UpdateCanisterSettingsRequest, ) -> UpdateCanisterSettingsResponse { + check_caller_is_governance(); canister_management::update_canister_settings( update_settings, &mut new_management_canister_client(), @@ -282,13 +232,9 @@ async fn update_canister_settings_( } /// Resources to serve for a given http_request -#[export_name = "canister_query http_request"] -fn http_request() { - over(candid_one_with_config, serve_http) -} - /// Serve an HttpRequest made to this canister -pub fn serve_http(request: HttpRequest) -> HttpResponse { +#[query(hidden = true, decoding_quota = 10000)] +pub fn http_request(request: HttpRequest) -> HttpResponse { match request.path() { "/metrics" => serve_metrics(encode_metrics), _ => HttpResponseBuilder::not_found().build(), diff --git a/rs/nns/handlers/root/impl/src/canister_management.rs b/rs/nns/handlers/root/impl/src/canister_management.rs index 20e7a346f32..a490846b52b 100644 --- a/rs/nns/handlers/root/impl/src/canister_management.rs +++ b/rs/nns/handlers/root/impl/src/canister_management.rs @@ -1,5 +1,9 @@ use crate::PROXIED_CANISTER_CALLS_TRACKER; -use dfn_core::api::{call, call_bytes, call_with_funds, caller, print, CanisterId, Funds}; +use ic_base_types::{CanisterId, PrincipalId}; +use ic_cdk::{ + api::call::{call_with_payment, RejectionCode}, + call, caller, print, +}; use ic_management_canister_types::{CanisterInstallMode::Install, InstallCodeArgs}; use ic_nervous_system_clients::{ canister_id_record::CanisterIdRecord, @@ -10,7 +14,7 @@ use ic_nervous_system_proxied_canister_calls_tracker::ProxiedCanisterCallsTracke use ic_nervous_system_root::change_canister::{ start_canister, stop_canister, AddCanisterRequest, CanisterAction, StopOrStartCanisterRequest, }; -use ic_nervous_system_runtime::DfnRuntime; +use ic_nervous_system_runtime::{CdkRuntime, Runtime}; use ic_nns_common::{ registry::{get_value, mutate_registry}, types::CallCanisterProposal, @@ -113,22 +117,15 @@ pub async fn do_add_nns_canister(request: AddCanisterRequest) { async fn try_to_create_and_install_canister( request: AddCanisterRequest, ) -> Result { - let (id,): (CanisterIdRecord,) = call_with_funds( - CanisterId::ic_00(), + let (id,): (CanisterIdRecord,) = call_with_payment( + CanisterId::ic_00().get().0, "create_canister", - dfn_candid::candid_multi_arity, (), - Funds::new(request.initial_cycles), + request.initial_cycles, ) .await - .map_err(|(code, msg)| { - format!( - "{}{}", - code.map(|c| format!("error code {}: ", c)) - .unwrap_or_default(), - msg - ) - })?; + .map_err(|(code, msg)| format!("error code {}: {}", code as i32, msg))?; + let install_args = InstallCodeArgs { mode: Install, canister_id: id.get_canister_id().get(), @@ -136,23 +133,13 @@ async fn try_to_create_and_install_canister( arg: request.arg, compute_allocation: request.compute_allocation, memory_allocation: request.memory_allocation, - sender_canister_version: Some(dfn_core::api::canister_version()), + sender_canister_version: Some(ic_cdk::api::canister_version()), }; - let install_res: Result<(), (Option, String)> = call( - CanisterId::ic_00(), - "install_code", - dfn_candid::candid_multi_arity, - (install_args,), - ) - .await; - install_res.map_err(|(code, msg)| { - format!( - "{}{}", - code.map(|c| format!("error code {}: ", c)) - .unwrap_or_default(), - msg - ) - })?; + let install_res: Result<(), (RejectionCode, String)> = + call(CanisterId::ic_00().get().0, "install_code", (install_args,)).await; + + install_res.map_err(|(code, msg)| format!("error code {}: {}", code as i32, msg))?; + Ok(id.get_canister_id()) } @@ -161,8 +148,8 @@ pub async fn stop_or_start_nns_canister( request: StopOrStartCanisterRequest, ) -> Result<(), (i32, String)> { match request.action { - CanisterAction::Start => start_canister::(request.canister_id).await, - CanisterAction::Stop => stop_canister::(request.canister_id).await, + CanisterAction::Start => start_canister::(request.canister_id).await, + CanisterAction::Stop => stop_canister::(request.canister_id).await, } } @@ -180,15 +167,15 @@ pub async fn call_canister(proposal: CallCanisterProposal) { let _tracker = ProxiedCanisterCallsTracker::start_tracking( &PROXIED_CANISTER_CALLS_TRACKER, - caller(), + PrincipalId::from(caller()), *canister_id, method_name, payload, ); - let res = call_bytes(*canister_id, method_name, payload, Funds::zero()) + let res = CdkRuntime::call_bytes_with_cleanup(*canister_id, method_name, payload) .await - .map_err(|(code, msg)| format!("Error: {}:{}", code.unwrap_or_default(), msg)); + .map_err(|(code, msg)| format!("Error: {}:{}", code, msg)); print(format!( "Call {}::{} returned {:?}", diff --git a/rs/nns/handlers/root/impl/src/lib.rs b/rs/nns/handlers/root/impl/src/lib.rs index 173aea83e8e..f8bf2398c64 100644 --- a/rs/nns/handlers/root/impl/src/lib.rs +++ b/rs/nns/handlers/root/impl/src/lib.rs @@ -1,4 +1,5 @@ use ic_base_types::{CanisterId, PrincipalId}; +use ic_cdk::api::time; use ic_nervous_system_proxied_canister_calls_tracker::ProxiedCanisterCallsTracker; use ic_nns_constants::{ CYCLES_MINTING_CANISTER_ID, EXCHANGE_RATE_CANISTER_ID, GENESIS_TOKEN_CANISTER_ID, @@ -7,19 +8,45 @@ use ic_nns_constants::{ }; use lazy_static::lazy_static; use maplit::btreemap; -use std::{cell::RefCell, collections::BTreeMap}; +use std::{ + cell::RefCell, + collections::BTreeMap, + time::{Duration, SystemTime, UNIX_EPOCH}, +}; pub mod canister_management; pub mod init; pub mod pb; pub mod root_proposals; +pub fn now_nanoseconds() -> u64 { + if cfg!(target_arch = "wasm32") { + time() + } else { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Failed to get time since epoch") + .as_nanos() + .try_into() + .expect("Failed to convert time to u64") + } +} + +pub fn now_seconds() -> u64 { + Duration::from_nanos(now_nanoseconds()).as_secs() +} + +fn system_time_now() -> SystemTime { + let nanos = now_nanoseconds(); + UNIX_EPOCH + Duration::from_nanos(nanos) +} + thread_local! { // TODO: Move this to canister.rs. It needs to be here for now, because // other libs want to use this. Ideally, this would only be passed to the // constructor of TrackingManagementCanisterClient. pub static PROXIED_CANISTER_CALLS_TRACKER: RefCell = - RefCell::new(ProxiedCanisterCallsTracker::new(dfn_core::api::now)); + RefCell::new(ProxiedCanisterCallsTracker::new(system_time_now)); } /// Encode the metrics in a format that can be understood by Prometheus. diff --git a/rs/nns/handlers/root/impl/src/root_proposals.rs b/rs/nns/handlers/root/impl/src/root_proposals.rs index 2d91fe50055..7d7f30fa148 100644 --- a/rs/nns/handlers/root/impl/src/root_proposals.rs +++ b/rs/nns/handlers/root/impl/src/root_proposals.rs @@ -1,6 +1,6 @@ use candid::{CandidType, Deserialize}; -use dfn_core::api::{call, now, CanisterId}; -use ic_base_types::{NodeId, PrincipalId, SubnetId}; +use ic_base_types::{CanisterId, NodeId, PrincipalId, SubnetId}; +use ic_cdk::call; use ic_management_canister_types::CanisterInstallMode; use ic_nervous_system_clients::{ canister_id_record::CanisterIdRecord, @@ -10,7 +10,7 @@ use ic_nervous_system_root::{ change_canister::{change_canister, ChangeCanisterRequest}, LOG_PREFIX, }; -use ic_nervous_system_runtime::DfnRuntime; +use ic_nervous_system_runtime::CdkRuntime; use ic_nns_common::registry::get_value; use ic_nns_constants::GOVERNANCE_CANISTER_ID; use ic_protobuf::registry::{ @@ -21,10 +21,11 @@ use ic_registry_keys::{ make_node_record_key, make_routing_table_record_key, make_subnet_record_key, }; use ic_registry_routing_table::RoutingTable; -use std::{cell::RefCell, collections::BTreeMap, convert::TryFrom, str::FromStr, time::SystemTime}; +use std::{cell::RefCell, collections::BTreeMap, convert::TryFrom, str::FromStr}; +use crate::now_seconds; #[cfg(target_arch = "wasm32")] -use dfn_core::println; +use ic_cdk::println; const MAX_TIME_FOR_GOVERNANCE_UPGRADE_ROOT_PROPOSAL: u64 = 60 * 60 * 24 * 7; @@ -146,16 +147,16 @@ thread_local! { } async fn get_current_governance_canister_wasm() -> Vec { - let status: CanisterStatusResultFromManagementCanister = call( - CanisterId::ic_00(), + let status: (CanisterStatusResultFromManagementCanister,) = call( + CanisterId::ic_00().get().0, "canister_status", - dfn_candid::candid, (CanisterIdRecord::from(GOVERNANCE_CANISTER_ID),), ) .await .unwrap(); status + .0 .module_hash .expect("Governance canister must return a module hash") } @@ -179,10 +180,7 @@ pub async fn submit_root_proposal_to_upgrade_governance_canister( expected_governance_wasm_sha: Vec, request: ChangeCanisterRequest, ) -> Result<(), String> { - let now = now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("Could not get the duration.") - .as_secs(); + let now = now_seconds(); // This is a new proposal and we're ready to prepare it. // Do some simple validation first: @@ -340,10 +338,7 @@ pub async fn vote_on_root_proposal_to_upgrade_governance_canister( return Err(message); } let proposal = proposal.unwrap(); - let now = now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("Could not get the current time.") - .as_secs(); + let now = now_seconds(); // Check the submission time, if it has elapsed without a majority // we can delete it. @@ -442,7 +437,7 @@ pub async fn vote_on_root_proposal_to_upgrade_governance_canister( println!("{}", message); return Err(message); } - let _ = change_canister::(payload).await; + let _ = change_canister::(payload).await; Ok(()) } else if proposal.is_byzantine_majority_no() { PROPOSALS.with(|proposals| proposals.borrow_mut().remove(&proposer)); diff --git a/rs/nns/handlers/root/impl/test_canisters/upgrade_test_canister.rs b/rs/nns/handlers/root/impl/test_canisters/upgrade_test_canister.rs index dc552112de9..b8bc13be5c8 100644 --- a/rs/nns/handlers/root/impl/test_canisters/upgrade_test_canister.rs +++ b/rs/nns/handlers/root/impl/test_canisters/upgrade_test_canister.rs @@ -1,19 +1,36 @@ // This canister is used for testing upgrades with arguments and stable memory. -use dfn_core::{api::arg_data, endpoint::over_bytes, println, stable}; +use ic_cdk::{ + api::{ + call::arg_data_raw, + stable::{stable_grow, stable_read, stable_write}, + }, + post_upgrade, println, query, +}; +use std::cell::RefCell; + +thread_local! { + static ARG_LEN: RefCell = const {RefCell::new(0) }; +} fn main() {} -#[export_name = "canister_post_upgrade"] +#[post_upgrade] fn post_upgrade() { - dfn_core::printer::hook(); - - let arg = arg_data(); + let arg = arg_data_raw(); println!("Initializing test canister with arg={:?}", arg); - stable::set(&arg); + stable_grow(1).expect("Could not grow stable memory"); + ARG_LEN.with(|len| { + *len.borrow_mut() = arg.len(); + }); + stable_write(0, &arg); } -#[export_name = "canister_query read_stable"] -fn read_stable() { - over_bytes(|_| -> Vec { stable::get() }) +#[query] +fn read_stable() -> Vec { + let len = ARG_LEN.with(|len| *len.borrow()); + let mut buf = vec![0; len]; + stable_read(0, &mut buf); + + buf } diff --git a/rs/nns/handlers/root/impl/tests/test_reinstall_and_upgrade.rs b/rs/nns/handlers/root/impl/tests/test_reinstall_and_upgrade.rs index b437384c87b..135556d6564 100644 --- a/rs/nns/handlers/root/impl/tests/test_reinstall_and_upgrade.rs +++ b/rs/nns/handlers/root/impl/tests/test_reinstall_and_upgrade.rs @@ -1,7 +1,7 @@ use assert_matches::assert_matches; use candid::Encode; use canister_test::{Project, Runtime}; -use dfn_candid::candid; +use dfn_candid::{candid, candid_one}; use ic_management_canister_types::CanisterInstallMode::{self, Install, Reinstall, Upgrade}; use ic_nervous_system_clients::{ canister_id_record::CanisterIdRecord, @@ -192,7 +192,7 @@ fn test_init_payload_is_passed_through_upgrades() { ); // Now let's wait for the upgrade to complete - loop { + for _ in 1..100 { let status: CanisterStatusResult = root .update_( "canister_status", @@ -206,13 +206,11 @@ fn test_init_payload_is_passed_through_upgrades() { } } - assert_eq!( - universal - .query_("read_stable", bytes, Vec::new()) - .await - .unwrap(), - test_byte_array, - ); + let response_bytes: Vec = universal + .query_("read_stable", candid_one::, ()>, ()) + .await + .unwrap(); + assert_eq!(response_bytes, test_byte_array,); Ok(()) }); diff --git a/rs/nns/handlers/root/interface/BUILD.bazel b/rs/nns/handlers/root/interface/BUILD.bazel index 9d18aef9ece..f53e8c3f2a6 100644 --- a/rs/nns/handlers/root/interface/BUILD.bazel +++ b/rs/nns/handlers/root/interface/BUILD.bazel @@ -10,6 +10,7 @@ DEPENDENCIES = [ "//rs/rust_canisters/dfn_core", "//rs/types/base_types", "@crate_index//:candid", + "@crate_index//:ic-cdk", "@crate_index//:serde", ] diff --git a/rs/nns/handlers/root/interface/Cargo.toml b/rs/nns/handlers/root/interface/Cargo.toml index cf08c56b07f..4771015fc9c 100644 --- a/rs/nns/handlers/root/interface/Cargo.toml +++ b/rs/nns/handlers/root/interface/Cargo.toml @@ -9,6 +9,7 @@ candid = { workspace = true } dfn_candid = { path = "../../../../rust_canisters/dfn_candid" } dfn_core = { path = "../../../../rust_canisters/dfn_core" } ic-base-types = { path = "../../../../types/base_types" } +ic-cdk = { workspace = true } ic-nervous-system-clients = { path = "../../../../nervous_system/clients" } ic-nns-constants = { path = "../../../../nns/constants" } serde = { workspace = true } diff --git a/rs/nns/integration_tests/src/http_request.rs b/rs/nns/integration_tests/src/http_request.rs index fb94866f0e7..6d3909dda04 100644 --- a/rs/nns/integration_tests/src/http_request.rs +++ b/rs/nns/integration_tests/src/http_request.rs @@ -48,10 +48,10 @@ fn test_http_request_decoding_quota_for_canister( .execute_ingress(canister_id, "http_request", large_http_request_bytes) .unwrap_err(); let ic_cdk_expected_err = "Decoding cost exceeds the limit"; - let dfn_core_expecte_err = "Deserialization Failed"; + let dfn_core_expected_err = "Deserialization Failed"; assert!( err.description().contains(ic_cdk_expected_err) - || err.description().contains(dfn_core_expecte_err) + || err.description().contains(dfn_core_expected_err) ); }