From 9d8b0bbde33454d2e033ea5c21984a91988a0950 Mon Sep 17 00:00:00 2001 From: Ulan Degenbaev Date: Tue, 5 Dec 2023 15:57:23 +0000 Subject: [PATCH 1/3] Add docs about the resource reservation mechanism Context: https://forum.dfinity.org/t/23447 --- docs/developer-docs/gas-cost.md | 20 ++++++++++ .../level-1/1.6-managing-canisters.md | 40 ++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/docs/developer-docs/gas-cost.md b/docs/developer-docs/gas-cost.md index d31fabba0a..465b0aa1ff 100644 --- a/docs/developer-docs/gas-cost.md +++ b/docs/developer-docs/gas-cost.md @@ -78,3 +78,23 @@ The following table shows the calculated storage cost per GB for a 30-day month: | | | 13-node Application Subnets | 34-node Application Subnets | |----------------------|------------------------------------|-----------------------------|-----------------------------| | GB Storage Per Month | For storing a GB of data per month | $0.431 | $1.127 | + +## Resource reservation mechanism + +In order to encourage long-term usage and discourage spiky usage patterns of resources, the Internet Computer uses a *resource reservation mechanism* that was adopted by the community in [NNS proposal 12604](https://dashboard.internetcomputer.org/proposal/126094). +Every time a canister allocates new storage bytes, the system sets aside some amount of cycles from the main balance of the canister. These reserved cycles are used to cover future payments for the newly allocated bytes. The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is. For example, it may cover days, months, or even years of payments for the newly allocated bytes. + +The operations that allocate new bytes are: + +- Wasm instruction: `memory.grow`. +- System API calls: `ic0.stable_grow()` `ic0.stable64_grow()`. +- Increasing the `memory_allocation` in canister settings. + +These operations reserve some amount of cycles by moving them from the main balance of the canister to the reserved cycles balance. +The amount of reserved cycles depends on how many bytes are allocated and on the current subnet usage: + +- If subnet usage is below `450GiB``, then the amount of reserved cycles per allocated byte is `0``. +- If subnet usage is above `450GiB`, then the amount of reserved cycles per allocated byte grows linearly depending on the subnet usage from `0` to `10`` years worth of storage payments at the subnet capacity (which is currently `750GiB``). + +A controller of a canister can disable resource reservation by setting the `reserved_cycles_limit=0` in canister settings. +Such opted-out canisters would not be able to allocate if the subnet usage is above `450GiB` though. \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md index a0ce2b9d09..e898a86129 100644 --- a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md +++ b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md @@ -157,6 +157,8 @@ Compute allocation: 0 Freezing threshold: 2_592_000 Memory Size: Nat(2363181) Balance: 3_100_000_000_000 Cycles +Reserved: 0 Cycles +Reserved Cycles Limit: 5_000_000_000_000 Cycles Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17 ``` @@ -196,6 +198,8 @@ Compute allocation: 0 Freezing threshold: 2_592_000 Memory Size: Nat(2363181) Balance: 3_100_000_000_000 Cycles +Reserved: 0 Cycles +Reserved Cycles Limit: 5_000_000_000_000 Cycles Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17 ``` @@ -220,7 +224,7 @@ To check a canister's cycles balance, you must be the controller of the canister dfx canister status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic ``` -The output will resemble the following, where the value `Balance` refers to the cycles balance: +The output will resemble the following, where the value `Balance` refers to the main cycles balance and `Reserved` refers to the reserved cycles balance: ``` Canister status call result for 5o6tz-saaaa-aaaaa-qaacq-cai. @@ -231,6 +235,8 @@ Compute allocation: 0 Freezing threshold: 2_592_000 Memory Size: Nat(2363181) Balance: 3_100_000_000_000 Cycles +Reserved: 0 Cycles +Reserved Cycles Limit: 5_000_000_000_000 Cycles Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17 ``` @@ -249,6 +255,38 @@ There are a few ways to top up a canister: This tutorial will cover the first two workflows. For more information on using a third-party service for cycles management, please see [here](../../../developer-docs/setup/cycles/cycles_management_services). + +## Setting the reserved cycles limit + +When a canister allocate storage bytes, the system may reserve some amount of cycles by moving them from the main cycles balance of the canister to the reserved cycles balance. +These reserved cycles are used for future storage payments as explained [here][../../../developer-docs/gas-cost#resource-reservation-mechanism]. + +You can control the maximum amount of reserved cycles by setting the reserved cycles limit: + +```sh +dfx canister update-settings 5o6tz-saaaa-aaaaa-qaacq-cai --reserved-cycles-limit 42 --network ic +dfx canister status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic +``` + +The first command sets the reserved cycles limit to `42` and the second command queries the canister status and shows the following output: + +``` +Canister status call result for 5o6tz-saaaa-aaaaa-qaacq-cai. +... +Reserved: 0 Cycles +Reserved Cycles Limit: 42 Cycles +... + +``` + +Once the reserved cycles balances reaches the reserved cycles limit, the system is going to fail all operations that require cycle reservation. +The error message might look like this: + +``` +Canister cannot grow memory by 65536 bytes due to its reserved cycles limit. The current limit (42) would be exceeded by 1000. +``` + + ### Using ICP If you currently have a balance of ICP tokens within your dfx ledger account ID, you can use the `dfx ledger top-up` command to automatically convert that ICP into cycles and deposit it into the specified canister, for example: From 9c26f323f8a5880af039c05eeb52e58452098616 Mon Sep 17 00:00:00 2001 From: Ulan Degenbaev Date: Tue, 5 Dec 2023 15:59:28 +0000 Subject: [PATCH 2/3] Fix markdown --- docs/developer-docs/gas-cost.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer-docs/gas-cost.md b/docs/developer-docs/gas-cost.md index 465b0aa1ff..fd1089385c 100644 --- a/docs/developer-docs/gas-cost.md +++ b/docs/developer-docs/gas-cost.md @@ -93,8 +93,8 @@ The operations that allocate new bytes are: These operations reserve some amount of cycles by moving them from the main balance of the canister to the reserved cycles balance. The amount of reserved cycles depends on how many bytes are allocated and on the current subnet usage: -- If subnet usage is below `450GiB``, then the amount of reserved cycles per allocated byte is `0``. -- If subnet usage is above `450GiB`, then the amount of reserved cycles per allocated byte grows linearly depending on the subnet usage from `0` to `10`` years worth of storage payments at the subnet capacity (which is currently `750GiB``). +- If subnet usage is below `450GiB`, then the amount of reserved cycles per allocated byte is `0`. +- If subnet usage is above `450GiB`, then the amount of reserved cycles per allocated byte grows linearly depending on the subnet usage from `0` to `10` years worth of storage payments at the subnet capacity (which is currently `750GiB`). A controller of a canister can disable resource reservation by setting the `reserved_cycles_limit=0` in canister settings. Such opted-out canisters would not be able to allocate if the subnet usage is above `450GiB` though. \ No newline at end of file From a508e617e93b87b0129d3fda4a3bd22d7f47bba6 Mon Sep 17 00:00:00 2001 From: Ulan Degenbaev Date: Tue, 5 Dec 2023 16:01:07 +0000 Subject: [PATCH 3/3] Fixes --- .../developer-journey/level-1/1.6-managing-canisters.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md index e898a86129..a6e9d915be 100644 --- a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md +++ b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md @@ -258,8 +258,8 @@ This tutorial will cover the first two workflows. For more information on using ## Setting the reserved cycles limit -When a canister allocate storage bytes, the system may reserve some amount of cycles by moving them from the main cycles balance of the canister to the reserved cycles balance. -These reserved cycles are used for future storage payments as explained [here][../../../developer-docs/gas-cost#resource-reservation-mechanism]. +When a canister allocates storage bytes, the system may reserve some amount of cycles by moving them from the main cycles balance of the canister to the reserved cycles balance. +These reserved cycles are used for future storage payments as explained [here](../../../developer-docs/gas-cost#resource-reservation-mechanism). You can control the maximum amount of reserved cycles by setting the reserved cycles limit: @@ -286,6 +286,8 @@ The error message might look like this: Canister cannot grow memory by 65536 bytes due to its reserved cycles limit. The current limit (42) would be exceeded by 1000. ``` +Such errors can be fixed by increasing the reserved cycles limit. + ### Using ICP