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..70a2bce 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. @@ -90,7 +90,13 @@ Installing uploads a Wasm module to the canister and runs its initialization log ### Upgrade -Upgrading replaces the canister's Wasm module while preserving stable memory. The system runs a pre-upgrade hook (to save heap data to stable memory if needed), swaps the Wasm, then runs a post-upgrade hook (to restore data). +Upgrading replaces the canister's Wasm module while preserving stable memory. The runtime executes three steps atomically: + +1. `pre_upgrade` (or `system func preupgrade` in Motoko): save any heap data to stable memory before the code swap. +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 `pre_upgrade` 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. If a canister ensures all persistent data is always in stable memory, steps 1 and 3 can be left empty. ### Stop and delete @@ -102,7 +108,16 @@ For step-by-step CLI commands, see [Canister lifecycle management](../guides/can Controllers are principals (users or other canisters) that have permission to manage a canister: upgrade its code, change its settings, stop it, or delete it. -If a canister has **no controllers**, it is immutable: no one can change its code or settings. This is a strong guarantee for users who want to verify that a canister's behavior will never change. +The control structure can take several forms: + +| Control structure | Who is the controller | Effect | +|---|---|---| +| Centralized | A single developer's principal | Full developer control; standard during development | +| Multi-signature | A multi-signer wallet like [Orbit](https://orbitwallet.io/) | Requires multiple keys to approve any change | +| SNS-governed | A Service Nervous System (SNS) governance canister | Upgrades require a governance proposal voted on by asset holders | +| No controller | Empty controller list | Immutable canister; code can never be changed | + +If a canister has **no controllers**, it is immutable: no one can change its code or settings. This is a strong trust guarantee for users. Immutability can be verified on the [ICP Dashboard](https://dashboard.internetcomputer.org). ## Canister internals @@ -114,11 +129,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 caller authentication - [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 5605ccc..df991bf 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -13,6 +13,7 @@ Understand the ideas behind the Internet Computer before you build on it. These - **[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. - **[Protocol Stack](protocol/index.md)**: The four-layer architecture (peer-to-peer, consensus, message routing, execution) and protocol internals including performance benchmarks. +- **[Principals](principals.md)**: The identity model: who can call a canister, and how caller identity works. ## Core capabilities diff --git a/docs/concepts/principals.md b/docs/concepts/principals.md new file mode 100644 index 0000000..940b681 --- /dev/null +++ b/docs/concepts/principals.md @@ -0,0 +1,40 @@ +--- +title: "Principals" +description: "What principals are on ICP: the five principal classes and how caller identity works in practice" +--- + +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 + +ICP defines five principal classes, though one (derived IDs) has never been implemented: + +**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 `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). + +**5. Derived IDs:** Reserved in the specification but never 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. + +## Next steps + +- [Canisters](canisters.md): how canisters work, controllers, lifecycle, and message types +- [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 + + diff --git a/docs/references/glossary.md b/docs/references/glossary.md index ff690ff..48f43bb 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -522,11 +522,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 diff --git a/sidebar.mjs b/sidebar.mjs index afb9122..daf3ef7 100644 --- a/sidebar.mjs +++ b/sidebar.mjs @@ -79,6 +79,7 @@ export const sidebar = [ items: [ { slug: "concepts/network-overview" }, { slug: "concepts/canisters" }, + { slug: "concepts/principals" }, { slug: "concepts/app-architecture" }, { slug: "concepts/node-infrastructure" }, { slug: "concepts/edge-infrastructure" },