diff --git a/e2e-tests/canisters/canister_info.rs b/e2e-tests/canisters/canister_info.rs index b04d38a34..33a108b22 100644 --- a/e2e-tests/canisters/canister_info.rs +++ b/e2e-tests/canisters/canister_info.rs @@ -72,6 +72,7 @@ async fn canister_lifecycle() -> Principal { memory_allocation: None, freezing_threshold: None, reserved_cycles_limit: None, + wasm_memory_limit: None, }, canister_id: canister_id.canister_id, }) diff --git a/e2e-tests/canisters/management_caller.rs b/e2e-tests/canisters/management_caller.rs index ecadb4b6b..07b9cb444 100644 --- a/e2e-tests/canisters/management_caller.rs +++ b/e2e-tests/canisters/management_caller.rs @@ -1,5 +1,8 @@ use ic_cdk::*; +/// Some management canister "main" methods are tested with other e2e canisters: +/// - canister_info.rs +/// - chunk.rs mod main { use super::*; use ic_cdk::api::management_canister::main::*; @@ -8,10 +11,14 @@ mod main { let arg = CreateCanisterArgument { settings: Some(CanisterSettings { controllers: Some(vec![ic_cdk::id()]), - compute_allocation: Some(0u8.into()), + // There is no canister in the subnet, so we can set it to 100. + compute_allocation: Some(100u8.into()), + // Though the upper limit is 256TiB, the actual subnet may have less memory resource (e.g. local replica). + // Here we set it to 10KiB for testing. memory_allocation: Some(10000u16.into()), - freezing_threshold: Some(10000u16.into()), - reserved_cycles_limit: Some(10000u16.into()), + freezing_threshold: Some(u64::MAX.into()), + reserved_cycles_limit: Some(u128::MAX.into()), + wasm_memory_limit: Some((2u64.pow(48) - 1).into()), }), }; let canister_id = create_canister(arg, 100_000_000_000u128 / 13) @@ -20,6 +27,21 @@ mod main { .0 .canister_id; + let canister_id_record = CanisterIdRecord { canister_id }; + let response = canister_status(canister_id_record).await.unwrap().0; + assert_eq!(response.status, CanisterStatusType::Running); + assert_eq!(response.reserved_cycles.0, 0u128.into()); + let definite_canister_setting = response.settings; + assert_eq!(definite_canister_setting.controllers, vec![ic_cdk::id()]); + assert_eq!(definite_canister_setting.compute_allocation, 100u8); + assert_eq!(definite_canister_setting.memory_allocation, 10000u16); + assert_eq!(definite_canister_setting.freezing_threshold, u64::MAX); + assert_eq!(definite_canister_setting.reserved_cycles_limit, u128::MAX); + assert_eq!( + definite_canister_setting.wasm_memory_limit, + 2u64.pow(48) - 1 + ); + let arg = UpdateSettingsArgument { canister_id, settings: CanisterSettings::default(), @@ -35,15 +57,14 @@ mod main { arg: vec![], }; install_code(arg).await.unwrap(); - let arg = CanisterIdRecord { canister_id }; - uninstall_code(arg).await.unwrap(); - start_canister(arg).await.unwrap(); - stop_canister(arg).await.unwrap(); - let response = canister_status(arg).await.unwrap().0; - assert_eq!(response.status, CanisterStatusType::Stopped); - assert_eq!(response.reserved_cycles.0, 0u128.into()); - deposit_cycles(arg, 1_000_000_000_000u128).await.unwrap(); - delete_canister(arg).await.unwrap(); + + uninstall_code(canister_id_record).await.unwrap(); + start_canister(canister_id_record).await.unwrap(); + stop_canister(canister_id_record).await.unwrap(); + deposit_cycles(canister_id_record, 1_000_000_000_000u128) + .await + .unwrap(); + delete_canister(canister_id_record).await.unwrap(); let response = raw_rand().await.unwrap().0; assert_eq!(response.len(), 32); } @@ -61,6 +82,7 @@ mod provisional { memory_allocation: Some(10000u16.into()), freezing_threshold: Some(10000u16.into()), reserved_cycles_limit: Some(10000u16.into()), + wasm_memory_limit: Some(10000u16.into()), }; let arg = ProvisionalCreateCanisterWithCyclesArgument { amount: Some(1_000_000_000u64.into()), diff --git a/src/ic-cdk/CHANGELOG.md b/src/ic-cdk/CHANGELOG.md index 0532d2f13..014688e6c 100644 --- a/src/ic-cdk/CHANGELOG.md +++ b/src/ic-cdk/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +### Added + +- Add `wasm_memory_limit` to the management canister API types: (#483) + * `CanisterSettings` + * `DefiniteCanisterSettings`. + ## [0.13.2] - 2024-04-08 ### Added diff --git a/src/ic-cdk/src/api/management_canister/main/types.rs b/src/ic-cdk/src/api/management_canister/main/types.rs index 5499c5087..fd047f735 100644 --- a/src/ic-cdk/src/api/management_canister/main/types.rs +++ b/src/ic-cdk/src/api/management_canister/main/types.rs @@ -6,22 +6,58 @@ pub type CanisterId = Principal; /// Canister settings. /// +/// The settings are optional. If they are not explicitly set, the default values will be applied automatically. +/// /// See [`settings`](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-create_canister). #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] pub struct CanisterSettings { - /// A list of principals. Must be between 0 and 10 in size. + /// A list of at most 10 principals. + /// + /// The principals in this list become the *controllers* of the canister. + /// + /// Default value: A list containing only the caller of the create_canister call. pub controllers: Option>, /// Must be a number between 0 and 100, inclusively. + /// + /// It indicates how much compute power should be guaranteed to this canister, + /// expressed as a percentage of the maximum compute power that a single canister can allocate. + /// + /// If the IC cannot provide the requested allocation, + /// for example because it is oversubscribed, the call will be **rejected**. + /// + /// Default value: 0 pub compute_allocation: Option, - /// Must be a number between 0 and 2^48^ (i.e 256TB), inclusively. + /// Must be a number between 0 and 248 (i.e 256TB), inclusively. + /// + /// It indicates how much memory the canister is allowed to use in total. + /// + /// If the IC cannot provide the requested allocation, + /// for example because it is oversubscribed, the call will be **rejected**. + /// + /// If set to 0, then memory growth of the canister will be best-effort and subject to the available memory on the IC. + /// + /// Default value: 0 pub memory_allocation: Option, - /// Must be a number between 0 and 2^64^-1, inclusively, and indicates a length of time in seconds. + /// Must be a number between 0 and 264-1, inclusively. + /// + /// It indicates a length of time in seconds. + /// + /// Default value: 2592000 (approximately 30 days). pub freezing_threshold: Option, - /// Must be a number between 0 and 2^128^-1, inclusively, and indicates the - /// upper limit on cycles in the `reserved_cycles` balance of the canister. + /// Must be a number between 0 and 2128-1, inclusively. + /// + /// It indicates the upper limit on `reserved_cycles` of the canister. + /// + /// Default value: 5_000_000_000_000 (5 trillion cycles). pub reserved_cycles_limit: Option, + /// Must be a number between 0 and 248-1 (i.e 256TB), inclusively. + /// + /// It indicates the upper limit on the WASM heap memory consumption of the canister. + /// + /// Default value: 3_221_225_472 (3 GiB). + pub wasm_memory_limit: Option, } /// Argument type of [create_canister](super::create_canister). @@ -281,6 +317,8 @@ pub struct DefiniteCanisterSettings { pub freezing_threshold: Nat, /// Reserved cycles limit. pub reserved_cycles_limit: Nat, + /// The Wasm memory limit. + pub wasm_memory_limit: Nat, } /// Query statistics, returned by [canister_status](super::canister_status).