Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add wasm_memory_limit to the management canister #483

Merged
merged 4 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions e2e-tests/canisters/canister_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand Down
46 changes: 34 additions & 12 deletions e2e-tests/canisters/management_caller.rs
Original file line number Diff line number Diff line change
@@ -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::*;
Expand All @@ -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)
Expand All @@ -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(),
Expand All @@ -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);
}
Expand All @@ -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()),
Expand Down
6 changes: 6 additions & 0 deletions src/ic-cdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 43 additions & 5 deletions src/ic-cdk/src/api/management_canister/main/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<Principal>>,
/// 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<Nat>,
/// Must be a number between 0 and 2^48^ (i.e 256TB), inclusively.
/// Must be a number between 0 and 2<sup>48</sup> (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<Nat>,
/// 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 2<sup>64</sup>-1, inclusively.
///
/// It indicates a length of time in seconds.
///
/// Default value: 2592000 (approximately 30 days).
pub freezing_threshold: Option<Nat>,
/// 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 2<sup>128</sup>-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<Nat>,
/// Must be a number between 0 and 2<sup>48</sup>-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<Nat>,
}

/// Argument type of [create_canister](super::create_canister).
Expand Down Expand Up @@ -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).
Expand Down