-
Notifications
You must be signed in to change notification settings - Fork 510
A specification for the cycles minting canister. #5574
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
base: master
Are you sure you want to change the base?
Conversation
|
🤖 Here's your preview: https://tai3p-vaaaa-aaaam-abema-cai.icp0.io |
Co-authored-by: Jessie Mongeon <133128541+jessiemongeon1@users.noreply.github.com>
Co-authored-by: Severin Siffert <severin.siffert@dfinity.org> Co-authored-by: Jessie Mongeon <133128541+jessiemongeon1@users.noreply.github.com>
|
|
||
| - Topping up existing canisters. | ||
| - Creating new canisters. | ||
| - Minting and depositing minted cycles into cycle ledger-managed accounts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"cycle ledger-managed" has hyphenation that is confusing.
Perhaps "into accounts managed by the Cycles Ledger" would be clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| - Minting and depositing minted cycles into cycle ledger-managed accounts. | ||
| - Fetching exchange rates and subnet configuration. | ||
|
|
||
| The CMC is governed solely by the [NNS (Network Nervous System)](https://internetcomputer.org/nns/) and receives configuration updates through proposals. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"receives configuration updates" - this is true, but not exhaustive. It also receives new functionality, bug fixes, etc.
Something more general, like "updates" or "updates to functionality and configuration" might be clearer to those who aren't already IC aficionados.
|
|
||
| ## Configuration parameters | ||
|
|
||
| - **Conversion rate source**: The ICP/XDR exchange rate is **pushed** into the CMC by a dedicated [exchange rate canister](/references/exchange-rate-canister). This data reflects live market pricing and determines the ICP→cycles conversion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CMC actually pulls the info from the XRC
| - `get_principals_authorized_to_create_canisters_to_subnets`: Indicates which principals are permitted by governance to create canisters on specific, non-default subnets. | ||
| - `get_default_subnets`: Returns the subnets designated by governance for general-purpose public canister creation. | ||
| - `total_cycles_minted`: Returns the total number of cycles ever minted by the CMC. | ||
| - `get_build_metadata`: Displays internal version and build information for the CMC. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are supposed to be removed at some point (get_build_metadata endpoints), as we now attach that information as metadata to the WASMs.
| - The **memo field** must explicitly indicate the intent to create a canister. This can be expressed as: | ||
| - A legacy 64-bit unsigned integer memo with value (in decimal): | ||
| ``` | ||
| 1095062083 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How was this derived? It would be good to have an explanation, so it can be checked. I believe it should work out to "CREA" but in little endian if I remember correctly.
| ``` | ||
| - Or, for ICRC-1-compatible transfers (e.g., `icrc1_transfer`, `icrc2_transfer_from`), a memo blob equal to: | ||
| ``` | ||
| "\50\55\50\54\00\00\00\00" // ASCII "TUPT" + 4 zero bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "\50\55\50\54\00\00\00\00" // ASCII "TUPT" + 4 zero bytes | |
| "\50\55\50\54\00\00\00\00" // ASCII "TPUP" + 4 zero bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hex may also need to be updated but it actually looks right...
pub const MEMO_TOP_UP_CANISTER: Memo = Memo(0x50555054); // == 'TPUP'
| - If a previous `notify_*` call has already successfully processed a transfer at the same block height, the new call returns the same cached result (Ok or a terminal Err like `InvalidTransaction` or `Refunded`). | ||
| - To support safe retries, the result of a successful call or a terminal error is **cached** for a bounded (but generous) number of blocks (`MAX_NOTIFY_HISTORY`). Calls referring to blocks older than the cache window will fail with `NotifyError::TransactionTooOld`. | ||
|
|
||
| These semantics ensure that all `notify_*` methods are idempotent. Clients can safely retry using the original parameters (memo, block height, destination account). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: idempotent within the supported block window.
| - Topping up existing canisters. | ||
| - Creating new canisters. | ||
| - Minting and depositing minted cycles into cycle ledger-managed accounts. | ||
| - Fetching exchange rates and subnet configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here I was wondering: is this exchange rate just between cycles:ICP or more? (I thought it used to be more but now we have a separate exchange rate canister. But since I am also not sure, I wonder if others might have the same question :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it maybe also be useful to already say here what subnet configuration is here (because it is very little and specific i.e., just the subnet types, right?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add links to the docs on the XRC canister and subnet types for more info
|
|
||
| ## `notify_create_canister` | ||
|
|
||
| Uses tokens from an ICP transfer to **mint cycles**, which are then used to **create a new canister**. The CMC first verifies that the transfer has been recorded in the ICP ledger and that it matches the expected structure. If the `subnet_selection` field is omitted, the CMC selects a suitable subnet at random from the list of subnets available to the `controller` (either default or authorized). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the controller always the sender of the ICP? Maybe we could add how the controller is defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might also make the first point below clearer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the change that Daniel implemented to deal with a security issue? I thought only the nns-dapp is allowed to break this rule.
| - The **destination account** of the ICP transfer must be the CMC's account with a **subaccount derived from the intended controller's principal** (see the section on [Encoding a principal into a subaccount](#encoding-a-principal-into-a-subaccount)). | ||
| - The **principal encoded in the subaccount is the intended controller** of the created canister. | ||
| - Only that principal is authorized to call `notify_create_canister` and can set **arbitrary canister settings**, including additional controllers. | ||
| - **Exception**: The [NNS dapp](https://nns.ic0.app/) is permitted to call `notify_create_canister` on behalf of users and acts as a proxy in that case. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this case, how is the controller determined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only remember the old flow where the controller is the whatever is encoded in the subaccount. I don't think we've changed that.
|
|
||
| The CMC expects the payment to follow a strict structure that encodes the **intent** and **destination**: | ||
|
|
||
| - The subaccount used in the transfer must be derived from the caller principal using the standard 32-byte encoding (see “Shared Logic” section). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to add a link to the section here as in other places?
|
|
||
| All `notify_*` methods (such as `notify_create_canister` and `notify_top_up`) follow the same core semantics: | ||
|
|
||
| - Before processing any specific operation (like create or top-up), the CMC checks the memo of the incoming ICP transfer identified by `block_index`. If the memo (either the legacy `u64` memo or the ICRC-1 `blob` memo interpreted as a little-endian `u64`) does **not** match one of the recognized operation memos (`1095062083` for create, `1347768404` for top-up, `1414416717` for mint), the CMC attempts to automatically refund the ICP amount (minus the standard ledger transfer fee) back to the sender's account (`from` account in the transfer). If the refund succeeds or fails terminally, the call will return a `NotifyError::Refunded` or `NotifyError::InvalidTransaction` respectively. If the refund attempt fails transiently (e.g., ledger unavailable), the status is cleared, allowing a retry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the retry (last line here) has then to be triggered manually?
so the CMC just tries ones can then stops trying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, just like the original notify_*, since the ICPs are still with the CMC
| type NotifyError = variant { | ||
| Refunded: record { reason : text; block_index : opt nat64 }; // Request was invalid; ICP (minus fees) was refunded (or attempted). `block_index` is the refund transaction index, if successful. | ||
| InvalidTransaction: text; // Transaction details (e.g., destination, memo) don't match the request, or it was already processed for a different operation. | ||
| Processing: null; // The specified block_index is currently being processed by another call. Retry shortly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Retry shortly" is what we ask the caller who sees this error to do, right?
I was first not sure if this indicates "the canister will retry shortly", so maybe we can make this more precise?
|
|
||
| **Key Points:** | ||
|
|
||
| - **`Refunded`**: This occurs if the initial ICP transfer had an unrecognized memo (automatic refund), or if the canister creation/top-up/minting failed *after* the ICP transfer was validated (e.g., subnet unavailable, deposit cycles failed). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do these points here refer to? are all of them error reasons? If so, should there maybe be 1 sentence explaining this?
| - **`InvalidTransaction`**: The provided `block_index` might correspond to a transaction that doesn't match the request (e.g., wrong memo for the operation, wrong destination subaccount) or was already processed under a *different* `notify_*` call. | ||
| - **`Processing`**: Indicates contention. Simply retrying the *exact same call* after a short delay is appropriate. | ||
| - **`TransactionTooOld`**: The CMC only keeps a history of recent notifications (`MAX_NOTIFY_HISTORY` entries, currently 1,000,000). Older transactions cannot be processed. The returned value is the oldest `block_index` the CMC *might* still know about. | ||
| - **`Other`**: Catches various issues, such as failure to fetch the block from the ledger (`FailedToFetchBlock` error code `1`), internal CMC errors, or authorization issues (`Unauthorized` error code `3` if `notify_create_canister` caller != creator and is not NNS Dapp), bad subnet selection (`BadSubnetSelection` error code `4`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is internal CMC errror code '2' ? Just noticed that we don't give the code for this case and that we left out the nubmer 2 :D
| Refunded : record { refund_amount: nat; create_error: text; }; | ||
| }; | ||
| ``` | ||
| - `create_error`: Text description of the failure (e.g., "Insufficient cycles attached", "No subnets in which to create a canister", or errors from the IC management canister). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we still call this "IC management canister" even though we should use "ICP" instead of "IC" in most places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will let @jessiemongeon1 take this one :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be the ICP management canister, though in some other contexts we've been using "ICP system API"
| - **Purpose**: | ||
| - Sets the **default list** of subnets where *any* principal can create canisters (when `who` parameter is `null`). | ||
| - Sets a specific list of subnets where a designated `who` principal is authorized to create canisters. If the `subnets` list is empty, the authorization for `who` is removed. | ||
| - **Preconditions**: Subnets added to the default or authorized lists cannot already be assigned to a named subnet type (see `update_subnet_type`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is a "named subnet" the same as a "subnet type"? or do we mean sth else where?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess subnet type is accurate
|
|
||
| ## `get_principals_authorized_to_create_canisters_to_subnets` | ||
|
|
||
| Lists principals specifically authorized by NNS Governance to create canisters on non-default subnets, and the corresponding list of subnet principals they are permitted to use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the relationship between default / non-default subnets (with special permissions) and the "named types" (where any principal can deploy AFAIK) is clear. If we want to be extra clear, maybe we could have a small section introducing these different concepts?
| compute_allocation : opt nat; // Percentage (0-100) of guaranteed compute capacity | ||
| memory_allocation : opt nat; // Memory reserved for the canister, in bytes | ||
| freezing_threshold : opt nat; // Number of seconds the canister can go without being topped up before being frozen | ||
| // reserved_cycles_limit : opt nat; // (Note: This field might not be directly settable via CMC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the note here.
All of this cannot be set by CMC but needs to be set by its controller (NNS root), right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you create a canister, you can decide on canister settings -- I'll check if reserved_cycles_limit can be set by the CMC canister creation mechanism.
Co-authored-by: Lara Schmid <73884086+LaraAS@users.noreply.github.com>
Co-authored-by: Lara Schmid <73884086+LaraAS@users.noreply.github.com>
Co-authored-by: Lara Schmid <73884086+LaraAS@users.noreply.github.com>
Co-authored-by: Lara Schmid <73884086+LaraAS@users.noreply.github.com>
|
@bogwar @LaraAS bumping this after the recent call I had with Bogdan 😅 @jessiemongeon1 context:
|
Thank you for your contribution to the IC Developer Portal. This repo contains the content for https://internetcomputer.org and the ICP Developer Documentation, https://internetcomputer.org/docs/.
If you are submitting a Pull Request for adding or changing content on the ICP Developer Documentation, please make sure that your contribution meets the following requirements:
.mdxfile format to support the previous two components./sidebars.js, otherwise, it will not appear in theside navigation bar.
.github/CODEOWNERSfile isfilled with new documents that you added. This way we can ensure that future Pull Requests are reviewed by the right people.