From 1cc0b25575f690cf96db49ee86c89fd7ca14f0ce Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Wed, 6 May 2026 17:32:01 +0200 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20batch=209=20=E2=80=94=20principals?= =?UTF-8?q?=20and=20canister=20computational=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add principals.md: 5 principal classes, self-authenticating IDs, anonymous principal, canister control model, upgrade behavior with stable memory - Expand canisters.md: inter-canister messaging callbacks, trap/rollback behavior (reverts to state after last outgoing call, not start of message) - Fix canisters.md: replace Learn Hub principal link with internal principals.md - Update concepts/index.md: add principals.md entry - Update glossary.md: replace verbose principal definition with concise entry linking to principals.md - Remove 4 consumed Learn Hub staging files --- .../canister-control.md | 19 ----- .../canister-smart-contracts.md | 28 -------- .../computational-model.md | 15 ---- .../what-is-a-principal.md | 23 ------ docs/concepts/canisters.md | 15 +++- docs/concepts/index.md | 1 + docs/concepts/principals.md | 72 +++++++++++++++++++ docs/references/glossary.md | 6 +- 8 files changed, 87 insertions(+), 92 deletions(-) delete mode 100644 .migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-control.md delete mode 100644 .migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-smart-contracts.md delete mode 100644 .migration/learn-hub/how-does-icp-work/canister-smart-contracts/computational-model.md delete mode 100644 .migration/learn-hub/how-does-icp-work/canister-smart-contracts/what-is-a-principal.md create mode 100644 docs/concepts/principals.md diff --git a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-control.md b/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-control.md deleted file mode 100644 index 21e4413..0000000 --- a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-control.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -learn_hub_id: 34573932107796 -learn_hub_url: "https://learn.internetcomputer.org/hc/en-us/articles/34573932107796-Canister-Control" -learn_hub_title: "Canister Control" -learn_hub_section: "Canister Smart Contracts" -learn_hub_category: "How does ICP work?" -migrated: false ---- - -# Canister Control - -Canisters are managed by _controllers_ , which can be users or other canisters. Controllers are responsible for deploying, maintaining, and managing canisters. They can perform operations such as starting, stopping, and updating the canister, as well as adjusting canister parameters like the freezing threshold. The control structure can be centralized (e.g., when the controllers include a centralized entity), organizational (e.g. when the controller is a multi-signer wallet like [Orbit](https://orbitwallet.io/)), decentralized (e.g., when the controller is a DAO), or non-existent, resulting in an immutable smart contract. - -Controllers can update the code that runs on canisters by submitting a new Wasm module to replace the older one. By default, updating the Wasm module of a canister wipes out the Wasm memory, but the content of the stable memory remains unchanged. The Internet Computer offers an upgrade mechanism where three actions are executed atomically: serializing the Wasm memory of the canister and writing it to stable memory, installing the new Wasm code, and then deserializing the content of the stable memory. This allows for the Wasm heap memory to be kept even if the Wasm module changes. Of course, a canister may ensure at all times that the data that needs to be persisted across upgrades is stored in the stable memory, in which case the upgrade process is significantly simpler. - -## Additional Resources - -[25min video on creating, installing, upgrading, and managing canisters](https://www.youtube.com/watch?v=c5nv6vIG3OQ) - diff --git a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-smart-contracts.md b/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-smart-contracts.md deleted file mode 100644 index fd7491c..0000000 --- a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/canister-smart-contracts.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -learn_hub_id: 34210839162004 -learn_hub_url: "https://learn.internetcomputer.org/hc/en-us/articles/34210839162004-Canister-Smart-Contracts" -learn_hub_title: "Canister Smart Contracts" -learn_hub_section: "Canister Smart Contracts" -learn_hub_category: "How does ICP work?" -migrated: false ---- - -# Canister Smart Contracts - -Smart contracts on the Internet Computer come in the form of canisters: computational units that bundle code and state. Canisters expose endpoints that can be called by other canisters and parties external to the IC, such as browsers or mobile apps. - -There are two types of endpoints in canisters: **updates** and **queries**. Updates modify the state of the canister, while queries read from the state without making changes. The code of a canister is a [WebAssembly (Wasm)](https://webassembly.org/) module. The state includes the usual Wasm memory heap, a special type of memory called stable memory and metainformation about the canister. - -The articles in this section describe - - * [Computation model:](https://learn.internetcomputer.org/hc/en-us/articles/34573860369172) how canister code is executed - * [Cycles](https://learn.internetcomputer.org/hc/en-us/articles/34573913497108): how resources consumed by canisters are charged - * [Canister control:](https://learn.internetcomputer.org/hc/en-us/articles/34573932107796) who can deploy and manage canisters - * [Principals](https://learn.internetcomputer.org/hc/en-us/articles/34250491785108): who can call canisters - - - -## Additional Resources - -[Canister Developer Docs](https://internetcomputer.org/docs/current/home) - diff --git a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/computational-model.md b/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/computational-model.md deleted file mode 100644 index 625b67b..0000000 --- a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/computational-model.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -learn_hub_id: 34573860369172 -learn_hub_url: "https://learn.internetcomputer.org/hc/en-us/articles/34573860369172-Computational-Model" -learn_hub_title: "Computational Model" -learn_hub_section: "Canister Smart Contracts" -learn_hub_category: "How does ICP work?" -migrated: false ---- - -# Computational Model - -Canisters behave much like actors from the [actor-based concurrency model](https://en.wikipedia.org/wiki/Actor_model). Their code is single-threaded and executed in complete isolation from other canisters. Canisters communicate with one another via asynchronous messaging. When processing a message, a canister can make changes to its state, send messages to other canisters, or even create other canisters. Unlike in the traditional actor model, communication is bidirectional. Canister messages are either requests or replies. For each request sent, the Internet Computer records a callback to be invoked when the callee sends back a response. If the Internet Computer determines that there is no way for the callee to respond, then it will produce a response instead, thereby ensuring that every request receives a reply. - -An important aspect of the canister-based model is how canisters handle errors during message processing. When a canister processes a request, it might send out other requests and wait for some of these replies before completing the original request. If an error occurs (the canister “traps”), the canister’s state reverts to what it was right after its last outgoing message. - diff --git a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/what-is-a-principal.md b/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/what-is-a-principal.md deleted file mode 100644 index 902916d..0000000 --- a/.migration/learn-hub/how-does-icp-work/canister-smart-contracts/what-is-a-principal.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -learn_hub_id: 34250491785108 -learn_hub_url: "https://learn.internetcomputer.org/hc/en-us/articles/34250491785108-What-is-a-Principal" -learn_hub_title: "What is a Principal?" -learn_hub_section: "Canister Smart Contracts" -learn_hub_category: "How does ICP work?" -migrated: false ---- - -# What is a Principal? - -The concept of a principal appears at the level of canister smart contracts. In a nutshell, a principal identifies any entity that can call a canister. As both canisters and external users can call canisters, principals include both canister ids and self-authenticating identifiers derived from public keys of users. There are several classes of principals: - - 1. The [Internet Computer Management Canister](https://internetcomputer.org/docs/current/references/ic-interface-spec#ic-management-canister), which is a specific system API that can be called like a canister, uses the fixed principal _aaaaa-aa_. - 2. Canister ids: each canister on ICP is identified by its canister id. - 3. Self-authenticating ids: derived from public keys to identify users. - 4. Derived ids: a class which has been reserved but never implemented. - 5. The anonymous id, _2vxsx-fae:_ used as the identity of the caller for messages that are not signed. - - - -More details can be found in the [relevant section of the interface specification](https://internetcomputer.org/docs/current/references/ic-interface-spec#principal). - diff --git a/docs/concepts/canisters.md b/docs/concepts/canisters.md index cdbe6c4..706ab50 100644 --- a/docs/concepts/canisters.md +++ b/docs/concepts/canisters.md @@ -70,7 +70,7 @@ For a deeper dive, see [Orthogonal persistence](orthogonal-persistence.md). ## Canister IDs and principals -Every canister gets a globally unique **canister ID** when it is created. This ID is a [principal](https://learn.internetcomputer.org/hc/en-us/articles/34250491785108): the same type of identifier used for users: and serves as the canister's address on the network. +Every canister gets a globally unique **canister ID** when it is created. This ID is a [principal](principals.md): the same type of identifier used for users, and serves as the canister's address on the network. To send a message to a canister, you include its canister ID in the message header. The network routes the message to the correct subnet and places it in the canister's input queue for processing. @@ -114,11 +114,22 @@ Under the hood, each canister maintains several components: - **Controllers list**: the set of principals authorized to manage the canister. - **Settings**: configurable parameters like compute allocation, memory allocation, and the freezing threshold (the cycles balance below which the canister stops accepting new messages to avoid running out). +## Inter-canister messaging and error handling + +Canisters communicate by sending **requests** to other canisters and registering a **callback** to be invoked when the callee sends a response. The network guarantees that every request receives a reply: if a callee becomes unreachable or explicitly rejects a call, the Internet Computer synthesizes a reject response and delivers it to the caller's callback. Callbacks are never dropped. + +This bidirectional request/reply model is one way canisters differ from pure actors in classical actor-based systems, which typically use one-way fire-and-forget messages. + +**Trap behavior with outgoing calls:** When a canister processes a message, it may send outgoing requests before completing. Each time a canister sends a request, the network records a commit point. If the canister later traps while awaiting a response, its state reverts to what it was immediately after that last outgoing request was dispatched, not to the beginning of the original incoming message. This means any state changes made after the last outgoing call are rolled back, while changes made before it are preserved. + +This has a practical implication: if a canister modifies state and then makes an inter-canister call in the same message, it must account for the possibility that subsequent code (including the callback handler) will see the state as it was when the call was sent. + ## Next steps - [Cycles](cycles.md): how canisters pay for computation +- [Principals](principals.md): the identity model and canister controllers - [App architecture](app-architecture.md): how canisters fit into application design - [Canister lifecycle](../guides/canister-management/lifecycle.md): practical guide to managing canisters - [Network overview](network-overview.md): the infrastructure canisters run on - + diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 8944cc1..590eda8 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -12,6 +12,7 @@ Understand the ideas behind the Internet Computer before you build on it. These - **[Network Overview](network-overview.md)**: Subnets, nodes, consensus, and boundary nodes. - **[Application Architecture](app-architecture.md)**: How ICP applications are structured: canisters, frontends, and inter-canister communication. - **[Canisters](canisters.md)**: Programs that run WebAssembly, hold state, serve HTTP, and pay for their own compute. +- **[Principals](principals.md)**: The identity model: users, canisters, anonymous calls, and canister control. ## Core capabilities diff --git a/docs/concepts/principals.md b/docs/concepts/principals.md new file mode 100644 index 0000000..f2d303d --- /dev/null +++ b/docs/concepts/principals.md @@ -0,0 +1,72 @@ +--- +title: "Principals" +description: "What principals are on ICP: the identity model, principal classes, canister control, and how authentication works" +--- + +A **principal** is any entity that can authenticate with the Internet Computer and be identified when calling a canister. Principals are the building block of identity and access control on ICP: canisters use them to identify callers, enforce permissions, and determine which entities have control over which resources. + +## Principal classes + +There are four classes of principals on ICP: + +**1. Management canister principal (`aaaaa-aa`):** The IC management canister is a virtual system API that canisters call to perform operations like creating other canisters or changing settings. It does not run at a real canister address; it uses the fixed principal `aaaaa-aa`. Canisters call it with `ic_cdk::management_canister::*` (Rust) or via actor references in Motoko. + +**2. Canister IDs:** Each canister on ICP has a unique principal derived when the canister is created. Canister principals look like `ryjl3-tyaaa-aaaaa-aaaba-cai`. When a canister makes a call to another canister, the callee sees the calling canister's canister ID as the caller principal. + +**3. Self-authenticating IDs:** User identities are derived from public keys using a domain-separated hash. Anyone holding the corresponding private key can authenticate and call canisters under that principal. Self-authenticating principals look like `un4fu-tqaaa-aaaab-qadjq-cai` for Ed25519 keys or similar for ECDSA keys. The [Internet Identity](https://identity.ic0.app/) service manages key-backed identities for end users. + +**4. Anonymous principal (`2vxsx-fae`):** Messages that are not signed use the anonymous principal as their caller identity. Any canister can check whether a caller is anonymous and decide how to handle unsigned requests (for example, allowing public reads but rejecting state changes from anonymous callers). + +A fifth class, **derived IDs**, was reserved in the specification but has never been implemented. + +## How principals are used in practice + +When a user calls a canister, the Internet Computer authenticates the user's signature and passes the corresponding principal as the `caller` to the canister's message handler. Canisters can then make authorization decisions based on the caller: + +``` +Caller is user → self-authenticating principal (derived from their public key) +Caller is another canister → that canister's canister ID +Unsigned request → 2vxsx-fae (anonymous principal) +``` + +This means that from a canister's perspective, all callers are principals. There is no separate "user object" or session token: the principal is the identity. + +## Canister control + +Canisters are managed by their **controllers**: a list of principals (users, other canisters, or DAOs) that have permission to perform management operations on the canister. Controllers can: + +- Upgrade the canister's Wasm module. +- Change canister settings (compute allocation, memory allocation, freezing threshold). +- Start or stop the canister. +- Delete the canister and claim its remaining cycles. +- Add or remove other controllers. + +The control structure can take several forms: + +| Control structure | Who is the controller | Effect | +|---|---|---| +| Centralized | A single developer's principal | Full developer control; standard for development | +| Multi-signature | A multi-signer wallet like [Orbit](https://orbitwallet.io/) | Requires multiple keys to approve changes | +| DAO-governed | An SNS governance canister | Upgrades require a governance proposal | +| No controller | Empty controller list | Immutable canister; code can never be changed | + +When a canister has no controllers, it is **immutable**: no one can modify its code or settings. Users who want to trust that a canister's behavior will never change can verify this on the [ICP Dashboard](https://dashboard.internetcomputer.org). + +## Canister upgrades and stable memory + +When a controller upgrades a canister, the new Wasm module replaces the old one. By default, Wasm heap memory is cleared on upgrade because the new module may have a different memory layout. However, **stable memory is always preserved** across upgrades: it is explicitly managed by the canister (via system API calls) and designed to survive code changes. + +The runtime runs upgrade hooks atomically around the code swap: +1. `pre_upgrade` (or `system func preupgrade` in Motoko): save any heap data to stable memory. +2. New Wasm module is installed. +3. `post_upgrade` (or `system func postupgrade`): read data back from stable memory into the new heap layout. + +If the `pre_upgrade` hook traps, the upgrade is aborted and the canister continues running the old code. If `post_upgrade` traps, the new code is installed but the canister is left in a failed state. + +## Next steps + +- [Canisters](canisters.md): how canisters work, lifecycle, and message types +- [Authentication](../guides/authentication/index.md): integrating Internet Identity and other authentication providers +- [IC Interface Specification: Principals](../references/ic-interface-spec/index.md#principal): the formal specification + + diff --git a/docs/references/glossary.md b/docs/references/glossary.md index e456386..a935008 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -502,11 +502,7 @@ builds upon this functionality. #### principal -A **principal** is an entity that can be authenticated by the [Internet Computer](#internet-computer-protocol-icp). This is the same sense of the -word principal as the [Wikipedia -definition](https://en.wikipedia.org/wiki/Principal-(computer-security)). -Principals that interact with the Internet Computer do so using a -certain [identity](#identity). +A **principal** is an entity that can be authenticated by the [Internet Computer](#internet-computer-protocol-icp). Principals include canister IDs, user identities derived from public keys, and the anonymous principal. See [Principals](../concepts/principals.md) for the full classification and how they are used for access control. #### proposal From 02a69474156050a2adb9d5aebdf7337cf4ee5f55 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Wed, 6 May 2026 18:52:39 +0200 Subject: [PATCH 2/2] fix(concepts): correct principal example and broken auth link in principals.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace canister-format self-authenticating principal example with correct 29-byte user principal format - Fix broken Next steps link: authentication/index.md → authentication/internet-identity.md --- docs/concepts/principals.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/principals.md b/docs/concepts/principals.md index f2d303d..2bbde9d 100644 --- a/docs/concepts/principals.md +++ b/docs/concepts/principals.md @@ -13,7 +13,7 @@ There are four classes of principals on ICP: **2. Canister IDs:** Each canister on ICP has a unique principal derived when the canister is created. Canister principals look like `ryjl3-tyaaa-aaaaa-aaaba-cai`. When a canister makes a call to another canister, the callee sees the calling canister's canister ID as the caller principal. -**3. Self-authenticating IDs:** User identities are derived from public keys using a domain-separated hash. Anyone holding the corresponding private key can authenticate and call canisters under that principal. Self-authenticating principals look like `un4fu-tqaaa-aaaab-qadjq-cai` for Ed25519 keys or similar for ECDSA keys. The [Internet Identity](https://identity.ic0.app/) service manages key-backed identities for end users. +**3. Self-authenticating IDs:** User identities are derived from public keys using a domain-separated hash. Anyone holding the corresponding private key can authenticate and call canisters under that principal. Self-authenticating principals look like `o2ivq-5dsbb-hhfso-w2o5v-7qiaq-g4fbm-6qhhb-xbj6w-szpxa-lflfa-mae` for Ed25519 keys or similar for ECDSA keys. The [Internet Identity](https://identity.ic0.app/) service manages key-backed identities for end users. **4. Anonymous principal (`2vxsx-fae`):** Messages that are not signed use the anonymous principal as their caller identity. Any canister can check whether a caller is anonymous and decide how to handle unsigned requests (for example, allowing public reads but rejecting state changes from anonymous callers). @@ -66,7 +66,7 @@ If the `pre_upgrade` hook traps, the upgrade is aborted and the canister continu ## Next steps - [Canisters](canisters.md): how canisters work, lifecycle, and message types -- [Authentication](../guides/authentication/index.md): integrating Internet Identity and other authentication providers +- [Authentication](../guides/authentication/internet-identity.md): integrating Internet Identity and other authentication providers - [IC Interface Specification: Principals](../references/ic-interface-spec/index.md#principal): the formal specification