diff --git a/CHANGELOG.md b/CHANGELOG.md index c81002d5bc..e1c883e30f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ # UNRELEASED +### feat: WASM memory soft-limit + +Adds support for the `wasm_memory_limit` canister setting, which limits the canister's heap during most calls but does not affect queries. As with other canister settings, it can be set in `dfx canister create` or `dfx canister update-settings` via the `--wasm-memory-limit` flag, as well as in `dfx.json` under `canisters[].initialization_values.wasm_memory_limit`. + ### feat: extensions can define a canister type Please see [extension-defined-canister-types](docs/concepts/extension-defined-canister-types.md) for details. @@ -21,12 +25,26 @@ This field accepts a relative path, from the directory containing the `dfx.json` `dfx new` could fail with "Failed to scaffold frontend code" if node was installed but npm was not installed. +## Dependencies + ### Cycles wallet Updated cycles wallet to a gzipped version of `20240410` release: - Module hash: `7745d3114e3e5fbafe8a7150a0a8c15a5b8dc9257f294d5ced67d41be76065bc`, in gzipped form: `664df1045e093084f4ebafedd3a793cc3b3be0a7ef1b245d8d3defe20b33057c` - https://github.com/dfinity/cycles-wallet/commit/b013764dd827560d8538ee2b7be9ecf66bed6be7 +### Replica + +Updated replica to elected commit 63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f. +This incorporates the following executed proposals: + +- [129428](https://dashboard.internetcomputer.org/proposal/129428) +- [129427](https://dashboard.internetcomputer.org/proposal/129427) +- [129423](https://dashboard.internetcomputer.org/proposal/129423) +- [129408](https://dashboard.internetcomputer.org/proposal/129408) +- [129379](https://dashboard.internetcomputer.org/proposal/129379) +- [129378](https://dashboard.internetcomputer.org/proposal/129378) + # 0.20.0 ### fix: set `CANISTER_CANDID_PATH_` properly for remote canisters diff --git a/Cargo.lock b/Cargo.lock index abaf0ba0e0..49a0fc1ba3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,7 +341,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", @@ -361,7 +361,18 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -1912,6 +1923,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + [[package]] name = "fake" version = "2.9.2" @@ -2505,8 +2537,9 @@ dependencies = [ [[package]] name = "ic-agent" version = "0.34.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=7840c34933fc509f443c3045c1c634201ad87e07#7840c34933fc509f443c3045c1c634201ad87e07" +source = "git+https://github.com/dfinity/agent-rs.git?rev=dac18df939dd7e63295083a2a9b2d024cb9b0c71#dac18df939dd7e63295083a2a9b2d024cb9b0c71" dependencies = [ + "async-lock 3.3.0", "backoff", "cached 0.46.1", "candid", @@ -2942,7 +2975,7 @@ dependencies = [ [[package]] name = "ic-identity-hsm" version = "0.34.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=7840c34933fc509f443c3045c1c634201ad87e07#7840c34933fc509f443c3045c1c634201ad87e07" +source = "git+https://github.com/dfinity/agent-rs.git?rev=dac18df939dd7e63295083a2a9b2d024cb9b0c71#dac18df939dd7e63295083a2a9b2d024cb9b0c71" dependencies = [ "hex", "ic-agent", @@ -3042,7 +3075,7 @@ dependencies = [ [[package]] name = "ic-transport-types" version = "0.34.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=7840c34933fc509f443c3045c1c634201ad87e07#7840c34933fc509f443c3045c1c634201ad87e07" +source = "git+https://github.com/dfinity/agent-rs.git?rev=dac18df939dd7e63295083a2a9b2d024cb9b0c71#dac18df939dd7e63295083a2a9b2d024cb9b0c71" dependencies = [ "candid", "hex", @@ -3111,7 +3144,7 @@ dependencies = [ [[package]] name = "ic-utils" version = "0.34.0" -source = "git+https://github.com/dfinity/agent-rs.git?rev=7840c34933fc509f443c3045c1c634201ad87e07#7840c34933fc509f443c3045c1c634201ad87e07" +source = "git+https://github.com/dfinity/agent-rs.git?rev=dac18df939dd7e63295083a2a9b2d024cb9b0c71#dac18df939dd7e63295083a2a9b2d024cb9b0c71" dependencies = [ "async-trait", "candid", @@ -3126,6 +3159,7 @@ dependencies = [ "strum_macros 0.24.3", "thiserror", "time", + "tokio", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1a689930e5..00d6c0e4f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,11 @@ license = "Apache-2.0" [workspace.dependencies] candid = "0.10.4" candid_parser = "0.1.4" -ic-agent = { git = "https://github.com/dfinity/agent-rs.git", rev = "7840c34933fc509f443c3045c1c634201ad87e07" } +ic-agent = { git = "https://github.com/dfinity/agent-rs.git", rev = "dac18df939dd7e63295083a2a9b2d024cb9b0c71" } ic-asset = { path = "src/canisters/frontend/ic-asset" } ic-cdk = "0.13.1" -ic-identity-hsm = { git = "https://github.com/dfinity/agent-rs.git", rev = "7840c34933fc509f443c3045c1c634201ad87e07" } -ic-utils = { git = "https://github.com/dfinity/agent-rs.git", rev = "7840c34933fc509f443c3045c1c634201ad87e07" } +ic-identity-hsm = { git = "https://github.com/dfinity/agent-rs.git", rev = "dac18df939dd7e63295083a2a9b2d024cb9b0c71" } +ic-utils = { git = "https://github.com/dfinity/agent-rs.git", rev = "dac18df939dd7e63295083a2a9b2d024cb9b0c71" } aes-gcm = "0.10.3" anyhow = "1.0.56" diff --git a/docs/cli-reference/dfx-canister.mdx b/docs/cli-reference/dfx-canister.mdx index 4ba8aa7295..d021821131 100644 --- a/docs/cli-reference/dfx-canister.mdx +++ b/docs/cli-reference/dfx-canister.mdx @@ -203,28 +203,28 @@ Notably, the following Candid types map to strings rather than numbers: nat, nat These are the mappings: -| Candid type | JSON type | -|-------------|-----------| -| `null` | `null` | -| `bool` | `boolean` | -| `nat` | `string` | -| `nat8` | `number` | -| `nat16` | `number` | -| `nat32` | `number` | -| `nat64` | `string` | -| `int` | `string` | -| `int8` | `number` | -| `int16` | `number` | -| `int32` | `number` | -| `int64` | `string` | -| `float32` | float or "NaN" | -| `float64` | float or "NaN" | -| `text` | `string` | +| Candid type | JSON type | +|-------------|----------------------------| +| `null` | `null` | +| `bool` | `boolean` | +| `nat` | `string` | +| `nat8` | `number` | +| `nat16` | `number` | +| `nat32` | `number` | +| `nat64` | `string` | +| `int` | `string` | +| `int8` | `number` | +| `int16` | `number` | +| `int32` | `number` | +| `int64` | `string` | +| `float32` | float or "NaN" | +| `float64` | float or "NaN" | +| `text` | `string` | | `opt` | array with 0 or 1 elements | -| `vec` | array | -| `record` | object | -| `variant` | object | -| `blob` | array of numbers | +| `vec` | array | +| `record` | object | +| `variant` | object | +| `blob` | array of numbers | ## dfx canister create @@ -250,10 +250,11 @@ You can use the following options with the `dfx canister create` command. |-------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `-c`, `--compute-allocation ` | Specifies the canister's compute allocation. This should be a percent in the range [0..100]. | | `--controller ` | Specifies the identity name or the principal of the new controller. | -| `--created-at-time ` | Transaction timestamp, in nanoseconds, for use in controlling transaction deduplication, default is system time. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | +| `--created-at-time ` | Transaction timestamp, in nanoseconds, for use in controlling transaction deduplication, default is system time. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | | `--from-subaccount ` | Subaccount of the selected identity to spend cycles from. | | `--memory-allocation ` | Specifies how much memory the canister is allowed to use in total. This should be a value in the range [0..12 GiB]. A setting of 0 means the canister will have access to memory on a “best-effort” basis: It will only be charged for the memory it uses, but at any point in time may stop running if it tries to allocate more memory when there isn’t space available on the subnet. | | `--reserved-cycles-limit ` | Specifies the upper limit for the canister's reserved cycles. | +| `--wasm-memory-limit ` | Specifies a soft upper limit for the canister's heap memory. | | `--no-wallet` | Performs the call with the user Identity as the Sender of messages. Bypasses the Wallet canister. Enabled by default. | | `--with-cycles ` | Specifies the initial cycle balance to deposit into the newly created canister. The specified amount needs to take the canister create fee into account. This amount is deducted from the wallet's cycle balance. | | `--specified-id ` | Attempts to create the canister with this Canister ID | @@ -385,10 +386,10 @@ You can use the following arguments with the `dfx canister deposit-cycles` comma You can use the following options with the `dfx canister deposit-cycles` command. -| Option | Description | -|-------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--created-at-time ` | Transaction timestamp, in nanoseconds, for use in controlling transaction deduplication, default is system time. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | -| `--from-subaccount ` | Subaccount of the selected identity to spend cycles from. | +| Option | Description | +|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--created-at-time ` | Transaction timestamp, in nanoseconds, for use in controlling transaction deduplication, default is system time. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | +| `--from-subaccount ` | Subaccount of the selected identity to spend cycles from. | ### Examples @@ -990,6 +991,7 @@ You can specify the following options for the `dfx canister update-settings` com | `--set-controller ` | Specifies the identity name or the principal of the new controller. Can be specified more than once, indicating the canister will have multiple controllers. If any controllers are set with this parameter, any other controllers will be removed. | | `--memory-allocation ` | Specifies how much memory the canister is allowed to use in total. This should be a value in the range [0..12 GiB]. A setting of 0 means the canister will have access to memory on a “best-effort” basis: It will only be charged for the memory it uses, but at any point in time may stop running if it tries to allocate more memory when there isn’t space available on the subnet. | | `--reserved-cycles-limit ` | Specifies the upper limit of the canister's reserved cycles. | +| `--wasm-memory-limit ` | Specifies a soft upper limit for the canister's heap memory. | | `--remove-controller ` | Removes a principal from the list of controllers of the canister. | | `--freezing-threshold ` | Set the [freezing threshold](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-create_canister) in seconds for a canister. This should be a value in the range [0..2^64^-1]. Very long thresholds require the `--confirm-very-long-freezing-threshold` option. | | `-y`, `--yes` | Skips yes/no checks by answering 'yes'. Such checks can result in loss of control, so this is not recommended outside of CI. | diff --git a/docs/dfx-json-schema.json b/docs/dfx-json-schema.json index 5cfdc8128e..11455bc916 100644 --- a/docs/dfx-json-schema.json +++ b/docs/dfx-json-schema.json @@ -82,6 +82,20 @@ "trace" ] }, + "Byte": { + "title": "Byte Count", + "description": "A quantity of bytes. Representable either as an integer, or as an SI unit string", + "examples": [ + 72, + "2KB", + "4 MiB" + ], + "type": [ + "integer", + "string" + ], + "pattern": "^[0-9]+( *([KkMmGgTtPpEeZzYy]i?)?B)?$" + }, "CanisterDeclarationsConfig": { "title": "Declarations Configuration", "description": "Configurations about which canister interface declarations to generate, and where to generate them.", @@ -397,7 +411,8 @@ "compute_allocation": null, "freezing_threshold": null, "memory_allocation": null, - "reserved_cycles_limit": null + "reserved_cycles_limit": null, + "wasm_memory_limit": null }, "allOf": [ { @@ -923,14 +938,16 @@ }, "memory_allocation": { "title": "Memory Allocation", - "description": "Maximum memory (in bytes) this canister is allowed to occupy.", + "description": "Maximum memory (in bytes) this canister is allowed to occupy. Can be specified as an integer, or as an SI unit string (e.g. \"4KB\", \"2 MiB\")", "default": null, - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 + "anyOf": [ + { + "$ref": "#/definitions/Byte" + }, + { + "type": "null" + } + ] }, "reserved_cycles_limit": { "title": "Reserved Cycles Limit", @@ -942,6 +959,19 @@ ], "format": "uint128", "minimum": 0.0 + }, + "wasm_memory_limit": { + "title": "WASM Memory Limit", + "description": "Specifies a soft limit (in bytes) on the Wasm memory usage of the canister.\n\nUpdate calls, timers, heartbeats, installs, and post-upgrades fail if the WASM memory usage exceeds this limit. The main purpose of this setting is to protect against the case when the canister reaches the hard 4GiB limit.\n\nMust be a number of bytes between 0 and 2^48 (i.e. 256 TiB), inclusive. Can be specified as an integer, or as an SI unit string (e.g. \"4KB\", \"2 MiB\")", + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Byte" + }, + { + "type": "null" + } + ] } } }, @@ -1177,4 +1207,4 @@ ] } } -} \ No newline at end of file +} diff --git a/e2e/assets/allocate_memory/src/e2e_project_backend/src/lib.rs b/e2e/assets/allocate_memory/src/e2e_project_backend/src/lib.rs new file mode 100644 index 0000000000..7ea906db17 --- /dev/null +++ b/e2e/assets/allocate_memory/src/e2e_project_backend/src/lib.rs @@ -0,0 +1,9 @@ +#[ic_cdk::query] +fn greet(s: String) -> String { + format!("Hello, {s}!") +} + +#[ic_cdk::update] +fn greet_update(s: String) -> String { + format!("Hello, {s}!") +} diff --git a/e2e/tests-dfx/create.bash b/e2e/tests-dfx/create.bash index 2f78fe0be7..de38fda373 100644 --- a/e2e/tests-dfx/create.bash +++ b/e2e/tests-dfx/create.bash @@ -315,3 +315,21 @@ teardown() { assert_command dfx canister call fake-cmc last_create_canister_args assert_contains 'subnet_type = opt "custom_subnet_type"' } + +@test "create with dfx.json settings" { + jq '.canisters.e2e_project_backend.initialization_values={ + "compute_allocation": 5, + "freezing_threshold": "7days", + "memory_allocation": "2 GiB", + "reserved_cycles_limit": 1000000000000, + "wasm_memory_limit": "1 GiB", + }' dfx.json | sponge dfx.json + dfx_start + assert_command dfx deploy e2e_project_backend --no-wallet + assert_command dfx canister status e2e_project_backend + assert_contains 'Memory allocation: 2_147_483_648' + assert_contains 'Compute allocation: 5' + assert_contains 'Reserved Cycles Limit: 1_000_000_000_000' + assert_contains 'WASM Memory Limit: 1_073_741_824' + assert_contains 'Freezing threshold: 604_800' +} diff --git a/e2e/tests-dfx/update_settings.bash b/e2e/tests-dfx/update_settings.bash index 54f529948d..464f97156a 100644 --- a/e2e/tests-dfx/update_settings.bash +++ b/e2e/tests-dfx/update_settings.bash @@ -42,6 +42,25 @@ teardown() { assert_match "Freezing threshold: 100_000_000_000" } +@test "set wasm memory limit" { + dfx_new_rust + install_asset allocate_memory + dfx_start + assert_command dfx canister create e2e_project_backend --no-wallet --wasm-memory-limit 2MiB + assert_command dfx deploy e2e_project_backend + assert_command dfx canister status e2e_project_backend + assert_contains "WASM Memory Limit: 2_097_152 Bytes" + # currently the limit is only checked when the memory grows. uncomment this line when that changes + # assert_command dfx canister call e2e_project_backend greet_update '("alice")' + assert_command dfx canister update-settings e2e_project_backend --wasm-memory-limit 8b + assert_command dfx canister status e2e_project_backend + assert_contains "WASM Memory Limit: 8 Bytes" + assert_command dfx canister call e2e_project_backend greet '("alice")' --query + assert_command dfx canister call e2e_project_backend greet '("alice")' --update + assert_command_fail dfx canister call e2e_project_backend greet_update '("alice")' + assert_contains "Canister exceeded its current Wasm memory limit of 8 bytes" +} + @test "set controller" { # Create two identities assert_command dfx identity new --storage-mode plaintext alice diff --git a/nix/sources.json b/nix/sources.json index 8b4839a92a..8a2b38efb8 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,53 +2,53 @@ "canister_sandbox-x86_64-darwin": { "builtin": false, "description": "The canister_sandbox binary. It must be updated together with the replica binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "17dx37iy8ylchafjql1lr8z3spb01klwys599aigp6bgbhrg4fls", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "0hah1870pbpgqcn3vlc96jykjbgkxy10ya7ddx1i5zwn77h7jiiv", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/canister_sandbox.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/canister_sandbox.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/canister_sandbox.gz" }, "canister_sandbox-x86_64-linux": { "builtin": false, "description": "The canister_sandbox binary. It must be updated together with the replica binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1bikj4z9mdz4d8ilhjdpfcdmcx10vmhvfiizxmxg84bb55xjlf2j", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1wnhz3gsqxfl3vgszpn49i88g0hi9yxyncshpcg85lgi6sa4n472", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/canister_sandbox.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/canister_sandbox.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/canister_sandbox.gz" }, "ic-admin-x86_64-darwin": { "builtin": false, "description": "The ic-admin binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1zxxh3zfidvfnm5an9ami6vkckj8r4yk2b5rfdn53ah37vbs315n", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "04m995h1mf9fdwiadsqpxpad2r1m6ya46hhh73jglrjpcwsw9hym", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-admin.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-admin.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/ic-admin.gz" }, "ic-admin-x86_64-linux": { "builtin": false, "description": "The ic-admin binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "163dybhyj3cxfd13q9frf2drfgqkkahv5f353jgbp9ix9w52cr27", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "03q0rnjk0qrb7zignxjvq8mlwh5njazgxmax2lhyfsh4zfb1v4kn", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-admin.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-admin.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/ic-admin.gz" }, "ic-btc-adapter-x86_64-darwin": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0fnw8npj1dq2nck246vhkkcaggkxg5whckndk8l7m1cd8fzg3275", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "0gmkzvxffg5ipj89j15h8ny4vp3pnpl7gfhyniwxpi59zh1lbsyz", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-btc-adapter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-btc-adapter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/ic-btc-adapter.gz" }, "ic-btc-adapter-x86_64-linux": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0yg53zwxd2ihgi8m8rn1d0j47bl9iazzcsnc8hv67dqncjv24isf", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "0izyd14zgflllmrjaam469zg1igsy0m3vwymp4igf3yw4pxvgcf1", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-btc-adapter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-btc-adapter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/ic-btc-adapter.gz" }, "ic-btc-canister": { @@ -61,52 +61,52 @@ }, "ic-https-outcalls-adapter-x86_64-darwin": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0prfvypnglimr92rb9vdmyqfl278c0lxy85n324any97dfdwqml1", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1kh5ap1gsfc9s6sl6y40z2sxna8khi6mlrwhzj44r1kmrvh2z9g4", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-https-outcalls-adapter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-https-outcalls-adapter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/ic-https-outcalls-adapter.gz" }, "ic-https-outcalls-adapter-x86_64-linux": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1yj4bznhh1n98174hyyr9qdyc65axskfc86l58l3vz7f6mkj1qcv", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "08nz27l1248y5vjvhivl831czr6ddxwl9yxy8faczyfmvv8cxzfh", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-https-outcalls-adapter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-https-outcalls-adapter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/ic-https-outcalls-adapter.gz" }, "ic-nns-init-x86_64-darwin": { "builtin": false, "description": "The ic-nns-init binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "077glk129693k9d8k0gpfhxw0pr63w8lr2kg3ihp0jqbrs50wfgl", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1i9la6052cmanh7k87gyxi9miwhkqjay3izxq9r8xm76i2y8ycdk", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-nns-init.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-nns-init.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/ic-nns-init.gz" }, "ic-nns-init-x86_64-linux": { "builtin": false, "description": "The ic-nns-init binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0qjiiw9m5dsh5c90p0q936a3l5z287gh5q25i1p1nwzy7ds46h1v", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "13wcic4x67xy7pi778jq1wpj8f5f7c99rknjph9lxsfqkdm6nmgz", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-nns-init.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-nns-init.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/ic-nns-init.gz" }, "ic-starter-x86_64-darwin": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0z4fr85ik3a01qhxvkyskqchh3h7svr8kmf2skw5yrafl0qv34mj", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "07y5qqgcbz493g47c1xh29n209nipvh58j9j3hhsmr1gbpiinf5z", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-starter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-starter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/ic-starter.gz" }, "ic-starter-x86_64-linux": { "builtin": false, - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "03qdnvgb8hln8qalmpz93an36h2cf7mqgqcamrrw5y8jjra069nw", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1fl69h6gsybqv6lqf8yvrdi8ni70c4hzwf7yvdii71sx05s8ssch", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-starter.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-starter.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/ic-starter.gz" }, "icx-proxy-x86_64-darwin": { @@ -154,55 +154,55 @@ "replica-x86_64-darwin": { "builtin": false, "description": "The replica binary. It must be updated together with the canister_sandbox binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1zcdydknl0xz31a8rbljy2spbyp3v4fn1kqm0lcxcjk32d3q3231", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1n6yfqz0z68jd64qb4yyhcjs13f42mmdmndbb1qv35p4azb28m2j", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/replica.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/replica.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/replica.gz" }, "replica-x86_64-linux": { "builtin": false, "description": "The replica binary. It must be updated together with the canister_sandbox binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "17zmq8gf09x4ylsaq06qgflkvj3gf7mzcczqdq57di2a6v5j881j", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "021n31ngyxn1lwp45lgscdncli7fgn6l9b6lvpf0pkf87w7jr494", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/replica.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/replica.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/replica.gz" }, "sandbox_launcher-x86_64-darwin": { "builtin": false, "description": "The sandbox_launcher binary. It must be updated together with the replica binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1vfz5a8lr93f4ckzq3l2f4dklzgvxm5cnrfi53qx7rgb66gikpb4", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "08sf8yx5jdq1b6y4av38h9spr950ndvlcrfmrdzhpzkaanmlk87p", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/sandbox_launcher.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/sandbox_launcher.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/sandbox_launcher.gz" }, "sandbox_launcher-x86_64-linux": { "builtin": false, "description": "The sandbox_launcher binary. It must be updated together with the replica binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "15nmrn4iir6wlm3z7nq2jd6q0bxl9x03wna5b75sw2fkb7f017zh", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1sg35y61ghsxppmn5cwfp9vpdv8s7g2jpx3vhkhrq9yn1mgfxbxs", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/sandbox_launcher.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/sandbox_launcher.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/sandbox_launcher.gz" }, "sns-x86_64-darwin": { "builtin": false, "description": "The sns binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "1l2fy42h8mhg747h9kq4gwndljfb0j3xzy2b4y9dmm7zysklrr0z", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "167x70b8j76llkh7mic6cphgadsdk88y2cssa8y12flkbf7mf1pq", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/sns.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/sns.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-darwin/sns.gz" }, "sns-x86_64-linux": { "builtin": false, "description": "The sns binary.", - "rev": "02dcaf3ccdfe46bd959d683d43c5513d37a1420d", - "sha256": "0w53bwajmakd55rcnis9dhfyxr39s88jllvl7k46abs5ayw6zfz8", + "rev": "63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f", + "sha256": "1hvvc1xlwxq5886yxrw2qznyz84pc6w6npjf00k7dj31b828312v", "type": "file", - "url": "https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/sns.gz", + "url": "https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/sns.gz", "url_template": "https://download.dfinity.systems/ic//binaries/x86_64-linux/sns.gz" } } diff --git a/src/dfx-core/src/config/model/dfinity.rs b/src/dfx-core/src/config/model/dfinity.rs index 1d9a2aa4a9..420063e0da 100644 --- a/src/dfx-core/src/config/model/dfinity.rs +++ b/src/dfx-core/src/config/model/dfinity.rs @@ -14,11 +14,12 @@ use crate::error::dfx_config::GetPullCanistersError::PullCanistersSameId; use crate::error::dfx_config::GetRemoteCanisterIdError::GetRemoteCanisterIdFailed; use crate::error::dfx_config::GetReservedCyclesLimitError::GetReservedCyclesLimitFailed; use crate::error::dfx_config::GetSpecifiedIdError::GetSpecifiedIdFailed; +use crate::error::dfx_config::GetWasmMemoryLimitError::GetWasmMemoryLimitFailed; use crate::error::dfx_config::{ AddDependenciesError, GetCanisterConfigError, GetCanisterNamesWithDependenciesError, GetComputeAllocationError, GetFreezingThresholdError, GetMemoryAllocationError, GetPullCanistersError, GetRemoteCanisterIdError, GetReservedCyclesLimitError, - GetSpecifiedIdError, + GetSpecifiedIdError, GetWasmMemoryLimitError, }; use crate::error::load_dfx_config::LoadDfxConfigError; use crate::error::load_dfx_config::LoadDfxConfigError::{ @@ -40,6 +41,7 @@ use crate::extension::manager::ExtensionManager; use crate::fs::create_dir_all; use crate::json::save_json_file; use crate::json::structure::{PossiblyStr, SerdeVec}; +use crate::util::ByteSchema; use byte_unit::Byte; use candid::Principal; use schemars::JsonSchema; @@ -407,7 +409,8 @@ pub struct InitializationValues { /// # Memory Allocation /// Maximum memory (in bytes) this canister is allowed to occupy. - #[schemars(with = "Option")] + /// Can be specified as an integer, or as an SI unit string (e.g. "4KB", "2 MiB") + #[schemars(with = "Option")] pub memory_allocation: Option, /// # Freezing Threshold @@ -429,6 +432,19 @@ pub struct InitializationValues { /// A setting of 0 means that the canister will trap if it tries to allocate new storage while the subnet's memory usage exceeds 450 GiB. #[schemars(with = "Option")] pub reserved_cycles_limit: Option, + + /// # WASM Memory Limit + /// Specifies a soft limit (in bytes) on the Wasm memory usage of the canister. + /// + /// Update calls, timers, heartbeats, installs, and post-upgrades fail if the + /// WASM memory usage exceeds this limit. The main purpose of this setting is + /// to protect against the case when the canister reaches the hard 4GiB + /// limit. + /// + /// Must be a number of bytes between 0 and 2^48 (i.e. 256 TiB), inclusive. + /// Can be specified as an integer, or as an SI unit string (e.g. "4KB", "2 MiB") + #[schemars(with = "Option")] + pub wasm_memory_limit: Option, } /// # Declarations Configuration @@ -938,6 +954,17 @@ impl ConfigInterface { .reserved_cycles_limit) } + pub fn get_wasm_memory_limit( + &self, + canister_name: &str, + ) -> Result, GetWasmMemoryLimitError> { + Ok(self + .get_canister_config(canister_name) + .map_err(|e| GetWasmMemoryLimitFailed(canister_name.to_string(), e))? + .initialization_values + .wasm_memory_limit) + } + fn get_canister_config( &self, canister_name: &str, diff --git a/src/dfx-core/src/error/dfx_config.rs b/src/dfx-core/src/error/dfx_config.rs index f72f538a55..c9a5813856 100644 --- a/src/dfx-core/src/error/dfx_config.rs +++ b/src/dfx-core/src/error/dfx_config.rs @@ -52,6 +52,12 @@ pub enum GetMemoryAllocationError { GetMemoryAllocationFailed(String, GetCanisterConfigError), } +#[derive(Error, Debug)] +pub enum GetWasmMemoryLimitError { + #[error("Failed to get WASM memory limit for canister '{0}': {1}")] + GetWasmMemoryLimitFailed(String, GetCanisterConfigError), +} + #[derive(Error, Debug)] pub enum GetPullCanistersError { #[error("Pull dependencies '{0}' and '{1}' have the same canister ID: {2}")] diff --git a/src/dfx-core/src/util/mod.rs b/src/dfx-core/src/util/mod.rs index efb41ba088..5236d8ae8f 100644 --- a/src/dfx-core/src/util/mod.rs +++ b/src/dfx-core/src/util/mod.rs @@ -1,4 +1,10 @@ -use std::time::Duration; +use std::{borrow::Cow, time::Duration}; + +use schemars::{ + gen::SchemaGenerator, + schema::{InstanceType, Metadata, Schema, SchemaObject, StringValidation}, + JsonSchema, +}; pub fn network_to_pathcompat(network_name: &str) -> String { network_name.replace(|c: char| !c.is_ascii_alphanumeric(), "_") @@ -9,3 +15,31 @@ pub fn expiry_duration() -> Duration { // 4 minutes accounts for possible replica drift Duration::from_secs(60 * 4) } + +pub struct ByteSchema; + +impl JsonSchema for ByteSchema { + fn schema_name() -> String { + "Byte".to_string() + } + fn schema_id() -> Cow<'static, str> { + Cow::Borrowed("byte_unit::Byte") + } + fn json_schema(_: &mut SchemaGenerator) -> Schema { + Schema::Object(SchemaObject { + instance_type: Some(vec![InstanceType::Integer, InstanceType::String].into()), + number: None, + string: Some(Box::new(StringValidation { + pattern: Some("^[0-9]+( *([KkMmGgTtPpEeZzYy]i?)?[Bb])?$".to_string()), + ..Default::default() + })), + metadata: Some(Box::new(Metadata { + title: Some("Byte Count".to_string()), + description: Some("A quantity of bytes. Representable either as an integer, or as an SI unit string".to_string()), + examples: vec![72.into(), "2KB".into(), "4 MiB".into()], + ..Default::default() + })), + ..Default::default() + }) + } +} diff --git a/src/dfx/assets/dfx-asset-sources.toml b/src/dfx/assets/dfx-asset-sources.toml index 34e7bb5c00..7be739f096 100644 --- a/src/dfx/assets/dfx-asset-sources.toml +++ b/src/dfx/assets/dfx-asset-sources.toml @@ -1,29 +1,29 @@ # generated by write-dfx-asset-sources.sh -replica-rev = '02dcaf3ccdfe46bd959d683d43c5513d37a1420d' +replica-rev = '63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f' [x86_64-darwin.icx-proxy] url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe861/openssl-static-binaries/x86_64-darwin/icx-proxy-dev.gz' sha256 = 'b07f2784abddcb54f0b0d3ce7585b9283cf814870905d58c26a1c8823ead2fdd' [x86_64-darwin.ic-admin] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-admin.gz' -sha256 = 'b684a1d73e03aa516c73b92c313dc9484e36b7895525ab4ab56eb7e8fe80bdff' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-admin.gz' +sha256 = 'd5c3c435675766fae43810424394373564d1d4ed17eba6226f2eb91a6049a912' [x86_64-darwin.ic-btc-adapter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-btc-adapter.gz' -sha256 = 'e588f1be438d857a289acd4e0679797dbea7d89c701b2226b302b720af45dc3a' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-btc-adapter.gz' +sha256 = 'dfeb4503fca9c4db79b41eba77e8b577dc4dbc45b0049990bcb13ce7fafeb33e' [x86_64-darwin.ic-https-outcalls-adapter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-https-outcalls-adapter.gz' -sha256 = '8156cc9b6b2779ab8818b620df2960e808eab0af6da79545ca35d267afdf2e5f' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-https-outcalls-adapter.gz' +sha256 = 'e4a52fe0ce75864c88fc90675a4d841329dbb5f8807843b5d18939fdc25505ce' [x86_64-darwin.ic-nns-init] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-nns-init.gz' -sha256 = 'f4390e8ace0b4b70611c6f8a4c111f265fc03b74f781895a9a239924c2a4ef1c' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-nns-init.gz' +sha256 = 'b3318fbc88e6d48e72c2fdc7e195c413f25853ecfe1d340fb4aa3251805134c5' [x86_64-darwin.ic-starter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/ic-starter.gz' -sha256 = 'b292b131a04e655ff8d4c2d589f2d6070e08199edacfdd210e408d190bca8e7c' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/ic-starter.gz' +sha256 = 'bf381be35d2fe4aa211c324954e0bed126206c12b00776c81b89fcc51ec6c51f' [x86_64-darwin.motoko] url = 'https://github.com/dfinity/motoko/releases/download/0.11.1/motoko-Darwin-x86_64-0.11.1.tar.gz' @@ -31,21 +31,21 @@ sha256 = '41c71aa0fea08226147ef1db01c5ca122a894ac0ab20e41cb149b9002ce3a24f' # The replica and canister_sandbox binaries must have the same revision. [x86_64-darwin.replica] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/replica.gz' -sha256 = '6188814713634ad6190515cf601dd9e3fa75b5f092ae8c5418bf036a67f38dfd' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/replica.gz' +sha256 = '525424d657e496b17158abd9da6a15c48da02583de9385896912990f3e76ded8' # The replica and canister_sandbox binaries must have the same revision. [x86_64-darwin.canister_sandbox] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/canister_sandbox.gz' -sha256 = '9a3af2325c6f99fba24aa968cfe90c605d3d3eca34502c9d828c7ae4e319bd9d' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/canister_sandbox.gz' +sha256 = '3b4679e03996ff12436fed280f82eff32d39bd3489d13d2cc3efae0b0e0a5041' [x86_64-darwin.sandbox_launcher] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/sandbox_launcher.gz' -sha256 = '64dd199f31ebe5d3f128d165cb4aedfb7d3a1b71820efc27236ea44c912adfed' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/sandbox_launcher.gz' +sha256 = 'f7a049ab556afe0b7fcbd5654677b3a0a47c7582686c45bc59013759ba474e23' [x86_64-darwin.sns] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-darwin/sns.gz' -sha256 = '1fe44ca7f6ffd4da92274bf8df8704cb49da2c7f04cf040f390f560405f14ed0' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-darwin/sns.gz' +sha256 = 'f806578f5b933a113c525a33e1119a4d37f5e06586c57ae0a4d41c891638fd98' [x86_64-darwin.motoko-base] url = 'https://github.com/dfinity/motoko/releases/download/0.11.1/motoko-base-library.tar.gz' @@ -60,24 +60,24 @@ url = 'https://download.dfinity.systems/ic/69e1408347723dbaa7a6cd2faa9b65c42abbe sha256 = '2bff6952a65e2d94f49ffa5ce03bfbd0eef0fb6ca82a839844c84fd3efa8b280' [x86_64-linux.ic-admin] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-admin.gz' -sha256 = '4764260a4f3da6bb9e1c65b8b2a19a133f979b70d9253c42739d0de9e1f26d98' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-admin.gz' +sha256 = '76921d96fb046ae721155dd5febe92b6404e2bc25b76fbe23f2b6330a5cd000f' [x86_64-linux.ic-btc-adapter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-btc-adapter.gz' -sha256 = '4e4722b66416b7633644cc6af6bf8a89ae432468c16654517c308ad6f91fe579' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-btc-adapter.gz' +sha256 = 'c1b1b7fb25dc0ff722b9d5f33d2af0fac5f07e32a42a2573a594baf74968fe47' [x86_64-linux.ic-https-outcalls-adapter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-https-outcalls-adapter.gz' -sha256 = '9be1206735eefc3d282ad420e6a6eeaa18e61b4ed97b484e40c90608ed5f44fa' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-https-outcalls-adapter.gz' +sha256 = 'd0fdced0ded5f9cf9443befb44796fcde4cfc2407447b8e52e1e1111e811df22' [x86_64-linux.ic-nns-init] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-nns-init.gz' -sha256 = '3b4043743bfe731b6e8845e002df41e2173a941909830b122b50b752138f5162' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-nns-init.gz' +sha256 = 'ff556b6a9bd8e94e13bcd2ce9c123bae38242f0f58a273e23dbe1fd3098b8c8f' [x86_64-linux.ic-starter] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/ic-starter.gz' -sha256 = 'dc2603549612f9c273ae8ae187eb714c4033ac1ae9df4a15469642b4deb60d0f' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/ic-starter.gz' +sha256 = '90698d74015d871363dbfe38fe2161e0448b62cbdb2387a9d97879fd0c4c86ba' [x86_64-linux.motoko] url = 'https://github.com/dfinity/motoko/releases/download/0.11.1/motoko-Linux-x86_64-0.11.1.tar.gz' @@ -85,21 +85,21 @@ sha256 = '6a6c1b9d9d69bb49b40859c1c51b40b0dabf2dd3aabacf37c73817dafee60a70' # The replica and canister_sandbox binaries must have the same revision. [x86_64-linux.replica] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/replica.gz' -sha256 = '322024cb364ac4760a6ef833f6eb716fc83da97bd800ac34f5a427e01ec2f59f' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/replica.gz' +sha256 = '24912c0f3fc8cd0bdcddd4ac448d7dee44ca6c63fad1422ea7c176ff6c183608' # The replica and canister_sandbox binaries must have the same revision. [x86_64-linux.canister_sandbox] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/canister_sandbox.gz' -sha256 = '52382a7b296b11f47aed3f46b761dd2074561b73b74948236ae4b79a3e9133ae' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/canister_sandbox.gz' +sha256 = 'e2104b9436f1d1821ebb5033ebbb4f118287504cc4deafdf1ed475acdff8d0f2' [x86_64-linux.sandbox_launcher] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/sandbox_launcher.gz' -sha256 = 'f09f00dc59d309aecb5945593e404fb42f804d9302dbf347a5dce41889cdd596' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/sandbox_launcher.gz' +sha256 = 'baafee5e0dd6279ce1847bf42bc53b1aed7677ba8eb362ebbd5dc3178c2fe3e9' [x86_64-linux.sns] -url = 'https://download.dfinity.systems/ic/02dcaf3ccdfe46bd959d683d43c5513d37a1420d/binaries/x86_64-linux/sns.gz' -sha256 = 'e8bb6fb857452f65c83c74532a11d269e4ee1d6c4947cb72296daa2a155fa370' +url = 'https://download.dfinity.systems/ic/63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f/binaries/x86_64-linux/sns.gz' +sha256 = '5b8481045a61c87626004e5e6bb86197a0efedc782e7ee0d4205774e7b607bc3' [x86_64-linux.motoko-base] url = 'https://github.com/dfinity/motoko/releases/download/0.11.1/motoko-base-library.tar.gz' diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index e9009f3250..7145890ef2 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -3,13 +3,13 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::ic_attributes::{ get_compute_allocation, get_freezing_threshold, get_memory_allocation, - get_reserved_cycles_limit, CanisterSettings, + get_reserved_cycles_limit, get_wasm_memory_limit, CanisterSettings, }; use crate::lib::operations::canister::create_canister; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::{ compute_allocation_parser, freezing_threshold_parser, memory_allocation_parser, - reserved_cycles_limit_parser, + reserved_cycles_limit_parser, wasm_memory_limit_parser, }; use crate::util::clap::parsers::{cycle_amount_parser, icrc_subaccount_parser}; use crate::util::clap::subnet_selection_opt::SubnetSelectionOpt; @@ -56,7 +56,7 @@ pub struct CanisterCreateOpts { compute_allocation: Option, /// Specifies how much memory the canister is allowed to use in total. - /// This should be a value in the range [0..12 GiB]. + /// This should be a value in the range [0..12 GiB]. Can include units, e.g. "4KiB". /// A setting of 0 means the canister will have access to memory on a “best-effort” basis: /// It will only be charged for the memory it uses, but at any point in time may stop running /// if it tries to allocate more memory when there isn’t space available on the subnet. @@ -78,6 +78,17 @@ pub struct CanisterCreateOpts { #[arg(long, value_parser = reserved_cycles_limit_parser, hide = true)] reserved_cycles_limit: Option, + /// Specifies a soft limit on the Wasm memory usage of the canister. + /// + /// Update calls, timers, heartbeats, installs, and post-upgrades fail if the + /// WASM memory usage exceeds this limit. The main purpose of this setting is + /// to protect against the case when the canister reaches the hard 4GiB + /// limit. + /// + /// Must be a number between 0 B and 256 TiB, inclusive. Can include units, e.g. "4KiB". + #[arg(long, value_parser = wasm_memory_limit_parser, hide = true)] + wasm_memory_limit: Option, + /// Performs the call with the user Identity as the Sender of messages. /// Bypasses the Wallet canister. #[arg(long)] @@ -147,40 +158,43 @@ pub async fn exec( let pull_canisters_in_config = get_pull_canisters_in_config(env)?; if let Some(canister_name) = opts.canister_name.as_deref() { if pull_canisters_in_config.contains_key(canister_name) { - bail!( - "{0} is a pull dependency. Please deploy it using `dfx deps deploy {0}`", - canister_name - ); + bail!("{canister_name} is a pull dependency. Please deploy it using `dfx deps deploy {canister_name}`"); } let canister_is_remote = config_interface.is_remote_canister(canister_name, &network.name)?; if canister_is_remote { - bail!("Canister '{}' is a remote canister on network '{}', and cannot be created from here.", canister_name, &network.name) + bail!("Canister '{canister_name}' is a remote canister on network '{}', and cannot be created from here.", &network.name) } let compute_allocation = get_compute_allocation( opts.compute_allocation, Some(config_interface), Some(canister_name), ) - .with_context(|| format!("Failed to read compute allocation of {}.", canister_name))?; + .with_context(|| format!("Failed to read compute allocation of {canister_name}."))?; let memory_allocation = get_memory_allocation( opts.memory_allocation, Some(config_interface), Some(canister_name), ) - .with_context(|| format!("Failed to read memory allocation of {}.", canister_name))?; + .with_context(|| format!("Failed to read memory allocation of {canister_name}."))?; let freezing_threshold = get_freezing_threshold( opts.freezing_threshold, Some(config_interface), Some(canister_name), ) - .with_context(|| format!("Failed to read freezing threshold of {}.", canister_name))?; + .with_context(|| format!("Failed to read freezing threshold of {canister_name}."))?; let reserved_cycles_limit = get_reserved_cycles_limit( opts.reserved_cycles_limit, Some(config_interface), Some(canister_name), ) - .with_context(|| format!("Failed to read reserved cycles limit of {}.", canister_name))?; + .with_context(|| format!("Failed to read reserved cycles limit of {canister_name}."))?; + let wasm_memory_limit = get_wasm_memory_limit( + opts.wasm_memory_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| format!("Failed to read WASM memory limit of {canister_name}."))?; create_canister( env, canister_name, @@ -195,6 +209,7 @@ pub async fn exec( memory_allocation, freezing_threshold, reserved_cycles_limit, + wasm_memory_limit, }, opts.created_at_time, &mut subnet_selection, @@ -213,8 +228,7 @@ pub async fn exec( if canister_is_remote { info!( env.get_logger(), - "Skipping canister '{}' because it is remote for network '{}'", - canister_name, + "Skipping canister '{canister_name}' because it is remote for network '{}'", &network.name, ); @@ -227,23 +241,21 @@ pub async fn exec( Some(canister_name), ) .with_context(|| { - format!("Failed to read compute allocation of {}.", canister_name) + format!("Failed to read compute allocation of {canister_name}.") })?; let memory_allocation = get_memory_allocation( opts.memory_allocation, Some(config_interface), Some(canister_name), ) - .with_context(|| { - format!("Failed to read memory allocation of {}.", canister_name) - })?; + .with_context(|| format!("Failed to read memory allocation of {canister_name}."))?; let freezing_threshold = get_freezing_threshold( opts.freezing_threshold, Some(config_interface), Some(canister_name), ) .with_context(|| { - format!("Failed to read freezing threshold of {}.", canister_name) + format!("Failed to read freezing threshold of {canister_name}.") })?; let reserved_cycles_limit = get_reserved_cycles_limit( opts.reserved_cycles_limit, @@ -251,8 +263,14 @@ pub async fn exec( Some(canister_name), ) .with_context(|| { - format!("Failed to read reserved cycles limit of {}.", canister_name) + format!("Failed to read reserved cycles limit of {canister_name}.") })?; + let wasm_memory_limit = get_wasm_memory_limit( + opts.wasm_memory_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| format!("Failed to read WASM memory limit of {canister_name}."))?; create_canister( env, canister_name, @@ -267,6 +285,7 @@ pub async fn exec( memory_allocation, freezing_threshold, reserved_cycles_limit, + wasm_memory_limit, }, opts.created_at_time, &mut subnet_selection, diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 84d46e3d23..d5dce84118 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -187,6 +187,7 @@ async fn delete_canister( memory_allocation: None, freezing_threshold: Some(FreezingThreshold::try_from(0u8).unwrap()), reserved_cycles_limit: None, + wasm_memory_limit: None, }; info!(log, "Setting the controller to identity principal."); update_settings(env, canister_id, settings, call_sender).await?; diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index b436ccd629..2a998c331f 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -45,22 +45,26 @@ async fn canister_status( "Not Set".to_string() }; - println!("Canister status call result for {}.\nStatus: {}\nControllers: {}\nMemory allocation: {}\nCompute allocation: {}\nFreezing threshold: {}\nMemory Size: {:?}\nBalance: {} Cycles\nReserved: {} Cycles\nReserved Cycles Limit: {}\nModule hash: {}\nNumber of queries: {}\nInstructions spent in queries: {}\nTotal query request paylod size (bytes): {}\nTotal query response payload size (bytes): {}", - canister, - status.status, - controllers.join(" "), - status.settings.memory_allocation, - status.settings.compute_allocation, - status.settings.freezing_threshold, - status.memory_size, - status.cycles, - status.reserved_cycles, - reserved_cycles_limit, - status.module_hash.map_or_else(|| "None".to_string(), |v| format!("0x{}", hex::encode(v))), - status.query_stats.num_calls_total, - status.query_stats.num_instructions_total, - status.query_stats.request_payload_bytes_total, - status.query_stats.response_payload_bytes_total, + let wasm_memory_limit = if let Some(limit) = status.settings.wasm_memory_limit { + format!("{} Bytes", limit) + } else { + "Not Set".to_string() + }; + + println!("Canister status call result for {canister}.\nStatus: {status}\nControllers: {controllers}\nMemory allocation: {memory_allocation}\nCompute allocation: {compute_allocation}\nFreezing threshold: {freezing_threshold}\nMemory Size: {memory_size:?}\nBalance: {balance} Cycles\nReserved: {reserved} Cycles\nReserved Cycles Limit: {reserved_cycles_limit}\nWASM Memory Limit: {wasm_memory_limit}\nModule hash: {module_hash}\nNumber of queries: {queries_total}\nInstructions spent in queries: {query_instructions_total}\nTotal query request payload size (bytes): {query_req_payload_total}\nTotal query response payload size (bytes): {query_resp_payload_total}", + status = status.status, + controllers = controllers.join(" "), + memory_allocation = status.settings.memory_allocation, + compute_allocation = status.settings.compute_allocation, + freezing_threshold = status.settings.freezing_threshold, + memory_size = status.memory_size, + balance = status.cycles, + reserved = status.reserved_cycles, + module_hash = status.module_hash.map_or_else(|| "None".to_string(), |v| format!("0x{}", hex::encode(v))), + queries_total = status.query_stats.num_calls_total, + query_instructions_total = status.query_stats.num_instructions_total, + query_req_payload_total = status.query_stats.request_payload_bytes_total, + query_resp_payload_total = status.query_stats.response_payload_bytes_total, ); Ok(()) } diff --git a/src/dfx/src/commands/canister/update_settings.rs b/src/dfx/src/commands/canister/update_settings.rs index 936daa8b5a..aae79d1c62 100644 --- a/src/dfx/src/commands/canister/update_settings.rs +++ b/src/dfx/src/commands/canister/update_settings.rs @@ -3,13 +3,13 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::ic_attributes::{ get_compute_allocation, get_freezing_threshold, get_memory_allocation, - get_reserved_cycles_limit, CanisterSettings, + get_reserved_cycles_limit, get_wasm_memory_limit, CanisterSettings, }; use crate::lib::operations::canister::{get_canister_status, update_settings}; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::{ compute_allocation_parser, freezing_threshold_parser, memory_allocation_parser, - reserved_cycles_limit_parser, + reserved_cycles_limit_parser, wasm_memory_limit_parser, }; use anyhow::{bail, Context}; use byte_unit::Byte; @@ -50,7 +50,7 @@ pub struct UpdateSettingsOpts { compute_allocation: Option, /// Specifies how much memory the canister is allowed to use in total. - /// This should be a value in the range [0..12 GiB]. + /// This should be a value in the range [0..12 GiB]. Can include units, e.g. "4KiB". /// A setting of 0 means the canister will have access to memory on a “best-effort” basis: /// It will only be charged for the memory it uses, but at any point in time may stop running /// if it tries to allocate more memory when there isn’t space available on the subnet. @@ -76,6 +76,17 @@ pub struct UpdateSettingsOpts { #[arg(long, value_parser = reserved_cycles_limit_parser)] reserved_cycles_limit: Option, + /// Sets a soft limit on the Wasm memory usage of the canister. + /// + /// Update calls, timers, heartbeats, installs, and post-upgrades fail if the + /// WASM memory usage exceeds this limit. The main purpose of this setting is + /// to protect against the case when the canister reaches the hard 4GiB + /// limit. + /// + /// Must be a number between 0 B and 256 TiB, inclusive. Can include units, e.g. "4KiB". + #[arg(long, value_parser = wasm_memory_limit_parser)] + wasm_memory_limit: Option, + /// Freezing thresholds above ~1.5 years require this flag as confirmation. #[arg(long)] confirm_very_long_freezing_threshold: bool, @@ -138,6 +149,8 @@ pub async fn exec( get_freezing_threshold(opts.freezing_threshold, config_interface, canister_name)?; let reserved_cycles_limit = get_reserved_cycles_limit(opts.reserved_cycles_limit, config_interface, canister_name)?; + let wasm_memory_limit = + get_wasm_memory_limit(opts.wasm_memory_limit, config_interface, canister_name)?; if let Some(added) = &opts.add_controller { let status = get_canister_status(env, canister_id, call_sender).await?; let mut existing_controllers = status.settings.controllers; @@ -170,6 +183,7 @@ pub async fn exec( memory_allocation, freezing_threshold, reserved_cycles_limit, + wasm_memory_limit, }; update_settings(env, canister_id, settings, call_sender).await?; display_controller_update(&opts, canister_name_or_id); @@ -187,23 +201,21 @@ pub async fn exec( Some(canister_name), ) .with_context(|| { - format!("Failed to get compute allocation for {}.", canister_name) + format!("Failed to get compute allocation for {canister_name}.") })?; let memory_allocation = get_memory_allocation( opts.memory_allocation, Some(config_interface), Some(canister_name), ) - .with_context(|| { - format!("Failed to get memory allocation for {}.", canister_name) - })?; + .with_context(|| format!("Failed to get memory allocation for {canister_name}."))?; let freezing_threshold = get_freezing_threshold( opts.freezing_threshold, Some(config_interface), Some(canister_name), ) .with_context(|| { - format!("Failed to get freezing threshold for {}.", canister_name) + format!("Failed to get freezing threshold for {canister_name}.") })?; let reserved_cycles_limit = get_reserved_cycles_limit( opts.reserved_cycles_limit, @@ -211,8 +223,14 @@ pub async fn exec( Some(canister_name), ) .with_context(|| { - format!("Failed to get reserved cycles limit for {}.", canister_name) + format!("Failed to get reserved cycles limit for {canister_name}.") })?; + let wasm_memory_limit = get_wasm_memory_limit( + opts.wasm_memory_limit, + Some(config_interface), + Some(canister_name), + ) + .with_context(|| format!("Failed to get WASM memory limit for {canister_name}."))?; if let Some(added) = &opts.add_controller { let status = get_canister_status(env, canister_id, call_sender).await?; let mut existing_controllers = status.settings.controllers; @@ -245,6 +263,7 @@ pub async fn exec( memory_allocation, freezing_threshold, reserved_cycles_limit, + wasm_memory_limit, }; update_settings(env, canister_id, settings, call_sender).await?; display_controller_update(&opts, canister_name); diff --git a/src/dfx/src/lib/ic_attributes/mod.rs b/src/dfx/src/lib/ic_attributes/mod.rs index 0b3bf7a7af..14ff136f34 100644 --- a/src/dfx/src/lib/ic_attributes/mod.rs +++ b/src/dfx/src/lib/ic_attributes/mod.rs @@ -4,8 +4,9 @@ use byte_unit::Byte; use candid::Principal; use dfx_core::config::model::dfinity::ConfigInterface; use fn_error_context::context; -use ic_utils::interfaces::management_canister::attributes::{ - ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit, +use ic_utils::interfaces::management_canister::{ + attributes::{ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit}, + builders::WasmMemoryLimit, }; use num_traits::ToPrimitive; use std::convert::TryFrom; @@ -17,6 +18,7 @@ pub struct CanisterSettings { pub memory_allocation: Option, pub freezing_threshold: Option, pub reserved_cycles_limit: Option, + pub wasm_memory_limit: Option, } impl From @@ -41,6 +43,10 @@ impl From .reserved_cycles_limit .map(u128::from) .map(candid::Nat::from), + wasm_memory_limit: value + .wasm_memory_limit + .map(u64::from) + .map(candid::Nat::from), } } } @@ -88,6 +94,14 @@ impl TryFrom, + config_interface: Option<&ConfigInterface>, + canister_name: Option<&str>, +) -> DfxResult> { + let wasm_memory_limit = match (wasm_memory_limit, config_interface, canister_name) { + (Some(memory_limit), _, _) => Some(memory_limit), + (None, Some(config_interface), Some(canister_name)) => { + config_interface.get_wasm_memory_limit(canister_name)? + } + _ => None, + }; + wasm_memory_limit + .map(|arg| { + u64::try_from(arg.get_bytes()) + .map_err(|e| anyhow!(e)) + .and_then(|n| Ok(WasmMemoryLimit::try_from(n)?)) + .context("WASM memory limit must be between 0 and 2^48 (i.e 256TB), inclusively.") + }) + .transpose() +} diff --git a/src/dfx/src/lib/migrate.rs b/src/dfx/src/lib/migrate.rs index d1cf5025c9..c6cea35236 100644 --- a/src/dfx/src/lib/migrate.rs +++ b/src/dfx/src/lib/migrate.rs @@ -121,6 +121,7 @@ async fn migrate_canister( freezing_threshold: None, memory_allocation: None, reserved_cycles_limit: None, + wasm_memory_limit: None, }, },)), 0, diff --git a/src/dfx/src/lib/operations/canister/create_canister.rs b/src/dfx/src/lib/operations/canister/create_canister.rs index a8b52ff360..e05a9460a7 100644 --- a/src/dfx/src/lib/operations/canister/create_canister.rs +++ b/src/dfx/src/lib/operations/canister/create_canister.rs @@ -217,6 +217,7 @@ async fn create_with_management_canister( .with_optional_memory_allocation(settings.memory_allocation) .with_optional_freezing_threshold(settings.freezing_threshold) .with_optional_reserved_cycles_limit(settings.reserved_cycles_limit) + .with_optional_wasm_memory_limit(settings.wasm_memory_limit) .call_and_wait() .await; const NEEDS_WALLET: &str = "In order to create a canister on this network, you must use a wallet in order to allocate cycles to the new canister. \ @@ -295,6 +296,9 @@ async fn create_with_wallet( bail!( "Cannot create a canister using a wallet if the reserved_cycles_limit is set. Please create with --no-wallet or use dfx canister update-settings instead.") } + if settings.wasm_memory_limit.is_some() { + bail!("Cannot create a canister using a wallet if the wasm_memory_limit is set. Please create with --no-wallet or use dfx canister update-settings instead.") + } match wallet .wallet_create_canister( cycles, diff --git a/src/dfx/src/lib/operations/canister/deploy_canisters.rs b/src/dfx/src/lib/operations/canister/deploy_canisters.rs index 9624ec40a9..559e6d3d36 100644 --- a/src/dfx/src/lib/operations/canister/deploy_canisters.rs +++ b/src/dfx/src/lib/operations/canister/deploy_canisters.rs @@ -23,7 +23,7 @@ use fn_error_context::context; use ic_utils::interfaces::management_canister::attributes::{ ComputeAllocation, FreezingThreshold, MemoryAllocation, ReservedCyclesLimit, }; -use ic_utils::interfaces::management_canister::builders::InstallMode; +use ic_utils::interfaces::management_canister::builders::{InstallMode, WasmMemoryLimit}; use icrc_ledger_types::icrc1::account::Subaccount; use slog::info; use std::convert::TryFrom; @@ -249,6 +249,17 @@ async fn register_canisters( ReservedCyclesLimit::try_from(arg) .expect("Reserved cycles limit must be between 0 and 2^128-1, inclusively.") }); + let wasm_memory_limit = config_interface.get_wasm_memory_limit(canister_name)?.map( + |arg| { + u64::try_from(arg.get_bytes()) + .map_err(|e| anyhow!(e)) + .and_then(|n| Ok(WasmMemoryLimit::try_from(n)?)) + .context( + "WASM memory limit must be between 0 and 2^48 (i.e 256TB), inclusively.", + ) + }, + ).transpose()?; + let controllers = None; create_canister( env, @@ -264,6 +275,7 @@ async fn register_canisters( memory_allocation, freezing_threshold, reserved_cycles_limit, + wasm_memory_limit, }, created_at_time, subnet_selection, diff --git a/src/dfx/src/util/clap/parsers.rs b/src/dfx/src/util/clap/parsers.rs index 39df55cb47..e051f6d81d 100644 --- a/src/dfx/src/util/clap/parsers.rs +++ b/src/dfx/src/util/clap/parsers.rs @@ -118,6 +118,16 @@ pub fn memory_allocation_parser(memory_allocation: &str) -> Result Err("Must be a value between 0..12 GiB inclusive.".to_string()) } +pub fn wasm_memory_limit_parser(memory_limit: &str) -> Result { + let limit = Byte::from_unit(256., ByteUnit::TiB).expect("Parse Overflow."); + if let Ok(bytes) = memory_limit.parse::() { + if bytes <= limit { + return Ok(bytes); + } + } + Err("Must be a value between 0..256 TiB inclusive (e.g. `2GiB`).".to_string()) +} + pub fn freezing_threshold_parser(freezing_threshold: &str) -> Result { freezing_threshold .parse::()