diff --git a/.docs-plan/decisions.md b/.docs-plan/decisions.md index ccd21c43..2b531621 100644 --- a/.docs-plan/decisions.md +++ b/.docs-plan/decisions.md @@ -4,6 +4,34 @@ Record decisions that constrain future work — things an agent needs to know th --- +## 2026-05-06: Learn Hub migration — structure, staging, and sequencing + +**Context:** `learn.internetcomputer.org` (a Zendesk Help Center with ~86 articles) is being retired. Developer-relevant content must move into this docs site before the site goes down. Issues #187 and #190 document the full gap analysis. About 27 articles are end-user content (NNS dapp UI, wallet flows, network stats, vision/history) and are explicitly out of scope for developer docs. + +**Decision:** + +1. **`concepts/` subdirectory structure.** The flat 14-file layout cannot absorb ~20 additional pages cleanly. Add two subdirectories: + - `docs/concepts/protocol/` — six protocol-layer pages (consensus, P2P, message routing, execution, state sync, overview) + - `docs/concepts/chain-fusion/` — per-chain architecture pages; the existing `concepts/chain-fusion.md` moves to `concepts/chain-fusion/index.md` + - All other new pages stay flat under `docs/concepts/` (node-infrastructure, edge-infrastructure, evolution-scaling, certified-data, principals, tokenomics, token-ledgers, sns-framework) + +2. **Source staging.** All Learn Hub articles are committed as raw Markdown into `.migration/learn-hub/`, preserving the original category/section folder structure, before any content PRs are opened. Each batch PR reads from the staging files, writes proper docs pages, and deletes the staging files in the same commit. When `.migration/learn-hub/` is empty, the directory is removed and the migration is done. Each migrated page uses `` — no ongoing sync relationship. PR sync recommendation: `hand-written`. + +3. **End-user articles are out of scope.** All articles under "What is ICP?" (marketing/vision), "How can I use ICP? / Governance" (NNS dapp UI flows), "How can I use ICP? / Tokens & wallets" (quill/wallet how-tos), and "How can I use ICP? / Network stats" are not migrated into developer docs. Their disposition (NNS dapp help, IC dashboard help, marketing site) is handled outside this repo. + +4. **Batched PRs.** One `infra/learn-hub-migration-prep` PR does structural setup (staging files, decisions, navigation map, sidebar config, CLAUDE.md rule updates). Then 9 content PRs (`docs/`) migrate topic batches. See `.docs-plan/learn-hub-navigation.md` for the full batch-to-file mapping. + +5. **CLAUDE.md rule retirement.** Two rules reference Learn Hub and must be updated once all batch PRs are merged: + - The "never duplicate Learn Hub" line in the "Never" section must drop the Learn Hub reference. + - The "link to Learn Hub or explain inline" line in the "Never link to old docs" decision (2026-03-13 below) must be replaced with an instruction to link internally. + After the final batch PR merges, open a follow-up `infra/` PR to make these two edits. + +**Rationale:** Staging files in `.migration/learn-hub/` give every agent a stable, repo-local source to read before writing — consistent with the `.sources/` discipline for all other upstream content. Deleting staging files in the same PR as the content write makes progress unambiguous and prevents the staging directory from drifting out of sync. Subdirectories in `concepts/` are needed for the sidebar to remain navigable; two subdirs (not five) keeps the nesting shallow. + +**When to revisit:** Once `.migration/learn-hub/` is deleted in the final content PR, update this entry to "fully reflected in codebase" and remove it. + +--- + ## 2026-04-27: CLI and language tabs are always separate **Context:** Some pages were mixing CLI commands into the same `` group as Motoko and Rust code. Other pages (e.g. `cycles-management.mdx`, `lifecycle.mdx`) kept CLI as standalone blocks with language tabs appearing separately. The mixed approach creates an awkward tab for users who just want a quick CLI command. diff --git a/.docs-plan/migration-plan.md b/.docs-plan/migration-plan.md index 2f251f15..92926e5b 100644 --- a/.docs-plan/migration-plan.md +++ b/.docs-plan/migration-plan.md @@ -397,3 +397,23 @@ languages/rust/index.md - **All icp-cli commands, flags, and installation instructions must be verified** against the icp-cli repo source (`dfinity/icp-cli`, `docs/reference/cli.md`). Never guess CLI syntax — fetch with: `gh api repos/dfinity/icp-cli/contents/docs/reference/cli.md --jq '.content' | base64 -d` - Each stub page contains ``, ``, and `` HTML comments — read these before writing. - After completing a page, open a PR with a `## Sync recommendation` section and link it to the corresponding GitHub Issue. + +--- + +## Learn Hub migration batches + +Nine content PRs to migrate learn.internetcomputer.org articles into `docs/`. Source staging files are in `.migration/learn-hub/`. Full article-to-file mapping and cross-link instructions: `.docs-plan/learn-hub-navigation.md`. Per-batch agent workflow: `.docs-plan/learn-hub-migration.md`. + +To claim a batch: check `git ls-remote origin docs/concepts-*` — branch exists means claimed, open PR against `infra/learn-hub-migration-prep` means in progress, branch gone (merged) means done. No GitHub Issues needed. Full workflow: `.docs-plan/learn-hub-migration.md`. + +| Batch | Branch | Target files | Effort | Status | +|---|---|---|---|---| +| 1 — Protocol stack | `docs/concepts-protocol-stack` | `concepts/protocol/index.md`, `consensus.md`, `peer-to-peer.md`, `message-routing.md`, `execution.md`, `state-synchronization.md` | Large | open | +| 2 — Node infrastructure | `docs/concepts-node-infrastructure` | `concepts/node-infrastructure.md` | Medium | open | +| 3 — Edge infrastructure | `docs/concepts-edge-infrastructure` | `concepts/edge-infrastructure.md` | Medium | open | +| 4 — Evolution & scaling | `docs/concepts-evolution-scaling` | `concepts/evolution-scaling.md` | Small–medium | open | +| 5 — Chain Fusion deep dives | `docs/concepts-chain-fusion-deep-dives` | `concepts/chain-fusion/index.md` (moved), `bitcoin.md`, `ethereum.md`, `solana.md`, `dogecoin.md`, `exchange-rate-canister.md`, `chain-key-tokens.md` | Large | open | +| 6 — Cryptography deep dives | `docs/concepts-cryptography-deep-dives` | `concepts/certified-data.md`, expand `concepts/chain-key-cryptography.md` | Medium | open | +| 7 — Governance deep dives | `docs/concepts-governance-deep-dives` | expand `concepts/governance.md`, `concepts/sns-framework.md`, `references/nns-proposal-types.md`, `references/sns-dao-settings.md` | Large | open (do batch 8 first) | +| 8 — Tokens & ledgers | `docs/concepts-tokens-ledgers` | `concepts/tokenomics.md`, `concepts/token-ledgers.md`, expand `concepts/cycles.md` | Medium | open | +| 9 — Canister concept fillers | `docs/concepts-canister-fillers` | `concepts/principals.md`, expand `concepts/canisters.md` | Medium | open | diff --git a/AGENTS.md b/AGENTS.md index 7f7dfca8..29954278 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -134,14 +134,14 @@ git checkout main - Reference `dfx` — it is deprecated and banned - Use `mo:base` imports in Motoko code examples — use `mo:core` instead. Critical replacements: `Buffer` → `List`, `HashMap`/`TrieMap`/`Trie`/`RBTree` → `Map`, `Deque` → `Queue`, `OrderedMap` → `pure/Map`, `OrderedSet` → `pure/Set` - Create `.mdx` files without a clear need for interactive components — default to `.md` -- Duplicate content that lives in external docs (icp-cli, JS SDK, icskills, Learn Hub) +- Duplicate content that lives in external docs (icp-cli, JS SDK, icskills) - Edit synced files directly (`docs/languages/motoko/`, `docs/guides/tools/migrating-from-dfx.md`) - Nest sidebar items more than 3 levels deep - Skip reading source material before writing a page - Write code snippets from memory — find and adapt from actual upstream code in `.sources/` - Modify the rationale or context of existing decisions in `.docs-plan/decisions.md` — you may remove entries that are fully reflected in the current codebase but never alter reasoning behind active decisions - Add `Co-Authored-By` or any AI attribution to commits or PR descriptions -- Link to `internetcomputer.org/docs/` — that site is retired. For internal pages use relative paths, not absolute `docs.internetcomputer.org/...` URLs. Link to Learn Hub or explain inline for external content. +- Link to `internetcomputer.org/docs/` — that site is retired. For internal pages use relative paths, not absolute `docs.internetcomputer.org/...` URLs. Explain inline or link to `docs/concepts/` for protocol-level background; do not link to `learn.internetcomputer.org` (Learn Hub has been retired; its content is now in this site under `docs/concepts/`). - Link to internal pages that don't exist — every `[text](path.md)` must resolve to an actual file. Run `ls ` before linking. Links to `.mdx` pages use `.md` extension (Astro resolves both). - Link to a page without a section anchor when the surrounding context refers to a specific topic covered by a subsection — always check the target file's headings and include `#anchor` when a more precise destination exists. Verify anchors by grepping headings: `grep "^## \|^### " `. Anchor slugs: lowercase, spaces → `-`, special chars stripped. - Link to `https://cli.internetcomputer.org/` (bare root) — all CLI doc pages are under a versioned path. Use `https://cli.internetcomputer.org/0.2/` (current slug; verify with `cat .sources/icp-cli/docs-site/versions.json`) and confirm the path exists in `.sources/icp-cli/docs/.md`. For command-specific links add a section anchor from `.sources/icp-cli/docs/reference/cli.md` (e.g. `#icp-canister-logs`, `#icp-canister-settings-update`, `#icp-cycles`). When bumping icp-cli to a new minor version, follow the "Link adaptation for `icp-cli`" checklist in "Bumping submodules". diff --git a/docs/concepts/app-architecture.md b/docs/concepts/app-architecture.md index 868e6c67..a7aa6d53 100644 --- a/docs/concepts/app-architecture.md +++ b/docs/concepts/app-architecture.md @@ -1,5 +1,5 @@ --- -title: "Application Architecture" +title: "Application architecture" description: "How ICP applications are structured: canisters, frontends, and inter-canister communication" sidebar: order: 3 @@ -28,14 +28,16 @@ This flow replaces the traditional web stack. There is no separate web server, a | Concern | Traditional web app | ICP application | |---------|-------------------|-----------------| -| **Compute** | Application server (Node, Django, etc.) | Backend canister (Wasm) | -| **Storage** | Database (Postgres, MongoDB, etc.) | Canister stable memory (up to 500 GiB) | -| **Frontend hosting** | CDN + static file server | Asset canister | -| **Authentication** | OAuth provider or custom auth | [Internet Identity](../guides/authentication/internet-identity.md) (passkey-based) | -| **Scheduled tasks** | Cron jobs, worker queues | Canister timers | +| **Compute** | Application server (Node, Django, etc.) | [Backend canister](canisters.md) (Wasm) | +| **Storage** | Database (Postgres, MongoDB, etc.) | [Canister stable memory](orthogonal-persistence.md) (up to 500 GiB) | +| **Frontend hosting** | CDN + static file server | [Asset canister](../guides/frontends/asset-canister.md) | +| **Authentication** | OAuth provider or custom auth | [Internet Identity](../guides/authentication/internet-identity.md) (passkey or OAuth)\* | +| **Scheduled tasks** | Cron jobs, worker queues | [Canister timers](timers.md) | | **External API calls** | Server-side HTTP requests | [HTTPS outcalls](https-outcalls.md) | | **Infrastructure management** | You manage servers, scaling, uptime | The network handles replication and availability | +\* With Internet Identity, users authenticate using a passkey or an OAuth provider (Google, Apple, etc.). Either way, each app receives a unique, app-specific principal: your canister never sees the OAuth credential or any cross-app identifier. This gives stronger privacy guarantees than traditional OAuth flows. + The key difference: ICP applications are self-contained. You deploy code and data to canisters, and the network provides compute, storage, and serving. There is no infrastructure to provision or maintain. ## Architectural patterns @@ -71,7 +73,7 @@ For maximum throughput, distribute canisters across multiple [subnets](network-o ## Data storage -Canisters store data in heap memory during execution and can persist data across upgrades using [stable memory](../guides/backends/data-persistence.md#store-data-durably): there is no external database. Libraries provide familiar data-structure abstractions on top of raw stable memory: +Canisters store data in heap memory during execution and can persist data across upgrades using [stable memory](orthogonal-persistence.md#stable-memory): there is no external database. Libraries provide familiar data-structure abstractions on top of raw stable memory: - **Motoko:** the [`core` standard library](https://mops.one/core/docs) includes persistent data structures designed for upgrade-safe storage. - **Rust:** [`ic-stable-structures`](https://docs.rs/ic-stable-structures/latest/ic_stable_structures/) provides `StableBTreeMap` and other structures for stable memory. @@ -84,15 +86,16 @@ Not every ICP application needs the default asset canister. Your options: - **Asset canister**: the standard approach. Deploy your built frontend (React, Svelte, vanilla JS, etc.) to an asset canister that serves it over HTTP. See [Asset canister](../guides/frontends/asset-canister.md). - **Framework-specific canister**: use a framework like Juno that provides a more opinionated hosting solution on ICP. -- **Offchain frontend**: host your frontend on traditional infrastructure (Vercel, Netlify, etc.) and call ICP canisters from JavaScript using [`@icp-sdk/core/agent`](https://js.icp.build). Useful during migration or when you need features that asset canisters don't support. +- **Offchain frontend**: host your frontend on traditional infrastructure (Vercel, Netlify, etc.) and call ICP canisters from JavaScript using [`@icp-sdk/core/agent`](https://js.icp.build/core/latest/libs/agent). Useful during migration or when you need features that asset canisters don't support. - **No frontend**: backend-only canisters that expose a Candid API for other canisters or CLI tools to call. ## Choosing an architecture +Start with a [single canister](#single-canister): it is the right choice for most applications. Work through these questions only if your needs grow: + | Question | If yes | If no | |----------|--------|-------| -| Start here | [Single canister](#single-canister): recommended for most applications | - | -| Does the app have a web UI? | Add an [asset canister](#the-default-two-canister-model) | Backend-only canister | +| Does the app have a web UI? | Add an [asset canister](#frontend-options) | Backend-only canister | | Do you need separation of concerns or hit platform limits? | [Canister-per-service](#canister-per-service) | Stay with a single canister | | Do you need to scale beyond one subnet? | [Canister-per-subnet](#canister-per-subnet) | Stay on one subnet | diff --git a/docs/concepts/canisters.md b/docs/concepts/canisters.md index cdbe6c46..da844c97 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,11 +90,17 @@ 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 -Stopping a canister prevents it from accepting new messages while letting in-flight messages complete. Once stopped, a canister can be deleted to reclaim its resources and remaining cycles. +Stopping a canister prevents it from accepting new messages while letting in-flight messages complete. Once stopped, a canister can be deleted to reclaim its resources and remaining [cycles](cycles.md). For step-by-step CLI commands, see [Canister lifecycle management](../guides/canister-management/lifecycle.md). @@ -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/certified-data.md b/docs/concepts/certified-data.md new file mode 100644 index 00000000..3ae8703a --- /dev/null +++ b/docs/concepts/certified-data.md @@ -0,0 +1,60 @@ +--- +title: "Certified data" +description: "How ICP enables clients to verify query responses with a single public key check" +sidebar: + order: 11 +--- + +Query calls on ICP return results immediately without going through consensus. This means the response comes from a single replica, and a client cannot inherently distinguish a legitimate response from a fabricated one. Certified data solves this: by embedding cryptographic certificates in query responses, canisters can prove that their response reflects state that was committed through consensus, without the client needing to replay any historical state. + +## The verification problem + +Traditional verification approaches require significant client-side work. Bitcoin's Simplified Payment Verification downloads and validates block headers. Ethereum's light clients maintain a chain of committee hashes and verify Merkle proofs against the state root. Both approaches require ongoing synchronization and are impractical for mobile or web applications that need fast, lightweight verification. + +ICP takes a different approach: instead of requiring clients to track any chain state, the protocol produces a certificate that can be verified with a single signature check against a **single, stable public key** (the Internet Computer's root public key). This key never changes (it was fixed at genesis and is embedded in ICP client libraries), so any client can embed it and immediately verify any certificate it receives. + +## How certificates are produced + +Each subnet holds a threshold BLS signing key. The corresponding subnet public key is registered on the NNS and derivable from the IC root public key. At each consensus round, the subnet computes a **certified state tree**: a hash tree representing the replicated state of all canisters on that subnet, then signs the root hash of this tree with its threshold BLS key. + +The signed root is included in the subnet's **certified state**, which is available to every replica. When a canister wants to certify a response, it embeds a piece of certified state in the response, along with a Merkle path (witness) proving that the certified piece is included under the signed root. + +The result is a certificate that carries: +- the subnet's threshold BLS signature over the state tree root +- a chain of NNS signatures linking the subnet public key back to the IC root key +- a witness (Merkle path) from the signed root to the specific canister value + +Verifying this chain of signatures requires only the IC root public key. No block header downloads, no committee tracking, no ongoing synchronization. + +## Certified variables + +The interface through which canisters participate in this mechanism is **certified variables**: + +- During an **update call** (which goes through consensus), the canister calls `certified_data_set` with a 32-byte value. The subnet includes this value in its certified state at the end of the consensus round. +- During a **query call**, the canister reads back the certificate (the subnet's signature over the certified state tree) and returns it to the caller along with the canister's response. + +The 32-byte limitation is not a problem in practice. Applications use standard data structures like [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree) to commit to arbitrarily large amounts of data in a single 32-byte root hash. The canister stores the full data structure locally and returns a Merkle witness (a path from the root to the requested value) alongside the certificate in each query response. The client verifies both the certificate signature and the witness together. + +This pattern allows canisters to provide both fast responses (query, no consensus delay) and cryptographic authentication, a combination that most distributed systems cannot offer without full state replay. + +## Applications + +Certified data is used throughout ICP for exactly this reason: + +- **Certified variables in canisters.** Any canister can certify its state for client verification. See the [Certified variables guide](../guides/backends/certified-variables.md) for how to implement this. +- **Certified assets.** The asset canister uses certified variables to produce certified HTTP responses. When a browser fetches a page served by an ICP canister, the HTTP gateway verifies the certificate before serving the response, so the browser sees only content that was committed through consensus. +- **Internet Identity.** The Internet Identity service certifies its delegations, so clients can verify that an authentication delegation is authentic without trusting the individual replica that served the query. + +## Relationship to chain-key cryptography + +Certified data is one of the core applications of [chain-key cryptography](chain-key-cryptography.md). The threshold BLS signature property that makes certified data possible is the same one that enables fast response verification at the top level: a single subnet public key is enough to verify any response from that subnet, because the private key is never held by any single node and the signature is produced collectively by the subnet's nodes through threshold BLS. + +The unique-signature property of BLS is also essential here: for a given message and key, exactly one valid BLS signature exists. This means no subset of nodes can produce a different certificate for the same state, even if they collude. + +## Next steps + +- [Certified variables guide](../guides/backends/certified-variables.md): implement certified responses in a canister +- [Chain-key cryptography](chain-key-cryptography.md): the threshold BLS signatures that power this system +- [Network overview](network-overview.md): how subnet nodes produce the certified state tree + + diff --git a/docs/concepts/chain-fusion/bitcoin.md b/docs/concepts/chain-fusion/bitcoin.md new file mode 100644 index 00000000..a5c8b021 --- /dev/null +++ b/docs/concepts/chain-fusion/bitcoin.md @@ -0,0 +1,146 @@ +--- +title: "Bitcoin integration" +description: "How ICP connects to Bitcoin natively: the adapter, the Bitcoin canister, the checker canister, and ckBTC" +--- + +ICP's Bitcoin integration lets canisters hold Bitcoin addresses, query balances and UTXOs, and sign and broadcast Bitcoin transactions, all without bridges or custodians. This page covers the protocol architecture: the Bitcoin adapter, the Bitcoin canister, the Bitcoin checker canister, and chain-key Bitcoin (ckBTC). + +## Architecture + +The integration has two layers: + +**Protocol layer.** ICP nodes run a _Bitcoin adapter_, a process separate from the replica that speaks the Bitcoin peer-to-peer protocol. The adapter connects to Bitcoin nodes, downloads blocks, and relays pending transactions. It keeps the replica informed about the latest Bitcoin state. Inside the replica, the _Bitcoin canister_ (a canister running on a dedicated system subnet) processes blocks from the adapter, maintains the UTXO set for all Bitcoin addresses, and exposes a low-level API to other canisters. + +**Signing layer.** Each canister can derive its own Bitcoin addresses through [chain-key signatures](../chain-key-cryptography.md). Because Bitcoin addresses are tied to ECDSA or Schnorr public keys, and the protocol can produce threshold signatures for those keys, a canister can authorize Bitcoin transactions without any node ever holding the full private key. + +Together, these two layers give a canister the ability to receive bitcoin, check its balance, construct transactions, sign them, and broadcast them to the Bitcoin network. + +![Bitcoin integration architecture: a canister calls the Bitcoin canister through the ICP protocol stack, while the Bitcoin adapter connects to the Bitcoin peer-to-peer network](/concepts/chain-fusion/bitcoin-architecture.png) + +## Bitcoin canister API + +The Bitcoin canister exposes endpoints accessible directly by other canisters: + +- `bitcoin_get_balance`: returns the balance of any Bitcoin address. +- `bitcoin_get_utxos`: returns the unspent transaction outputs (UTXOs) for a given address. This is the primary input when constructing a Bitcoin transaction. +- `bitcoin_get_current_fee_percentiles`: returns recent fee rates so a canister can estimate an appropriate miner fee. +- `bitcoin_send_transaction`: broadcasts a signed transaction to the Bitcoin network via the adapter. +- `bitcoin_get_block_headers`: returns raw block headers for a range of heights. +- `get_blockchain_info`: returns current chain state including tip height, block hash, timestamp, difficulty, and UTXO count. + +A typical flow for a canister spending bitcoin is: fetch UTXOs for its address, select inputs, build the transaction, call `sign_with_ecdsa` (or `sign_with_schnorr` for Taproot) for each input, then call `bitcoin_send_transaction`. + +```plantuml +participant "Your Canister" as Canister +participant "Bitcoin Canister" as BC +participant "Chain-Key Signing" as CKS + +Canister -> BC: bitcoin_get_utxos(address, filter) +BC --> Canister: utxos + +Canister -> BC: bitcoin_get_current_fee_percentiles +BC --> Canister: fee_percentiles + +note over Canister: select inputs, build transaction + +loop for each transaction input + Canister -> CKS: sign_with_ecdsa(tx_input) + CKS --> Canister: signature +end + +Canister -> BC: bitcoin_send_transaction(signed_tx) +BC --> Canister: ok +``` + +For canister IDs, cycle costs, and the full interface specification, see [Bitcoin canisters](../../references/protocol-canisters.md#bitcoin-canisters). + +## Bitcoin checker canister + +The Bitcoin checker canister (`oltsj-fqaaa-aaaar-qal5q-cai`) screens Bitcoin addresses and transactions against the [OFAC Specially Designated Nationals (SDN) list](https://sanctionslist.ofac.treas.gov/Home/SdnList). It is used by ckBTC and any canister that wants to avoid handling funds associated with sanctioned activity. + +Two primary endpoints are available: + +- `check_address`: checks a single Bitcoin address against the SDN list. This is a simple lookup with no cycle cost. +- `check_transaction`: checks all input addresses of a transaction. The canister fetches the transaction and each of its inputs via HTTPS outcalls, derives the input addresses, and checks each one against the SDN list. Because of the HTTPS outcalls, at least 40 billion cycles must be attached; unused cycles are refunded. `check_transaction_str` accepts the transaction ID as a string instead of a blob. + +Both endpoints return `Passed` or `Failed`. The canister itself is controlled by the NNS, so its SDN list can only be updated via a governance proposal. + +![Bitcoin checker canister flow: the ckBTC minter calls the checker canister, which queries Bitcoin explorers and cross-references the OFAC SDN list before returning a pass or fail result](/concepts/chain-fusion/bitcoin-checker-flow.png) + +## Chain-key Bitcoin (ckBTC) + +ckBTC is an asset on ICP backed 1:1 by real bitcoin. 1 ckBTC can always be redeemed for 1 BTC and vice versa. Unlike wrapped assets, ckBTC relies on no third-party custodian: the bitcoin is held by a canister-controlled address on the Bitcoin network, and the minting and burning happen entirely onchain. + +ckBTC transactions settle in seconds with minimal fees, making it practical for high-frequency or low-value transfers that would be uneconomical on Bitcoin directly. + +![ckBTC system architecture: the ckBTC minter handles BTC deposits and withdrawals, the ckBTC ledger records balances, the Bitcoin canister provides UTXO data, and the Bitcoin checker canister screens addresses against the OFAC list](/concepts/chain-fusion/ckbtc-architecture.png) + +Two canisters run on the [pzp6e subnet](https://dashboard.internetcomputer.org/subnet/pzp6e-ekpqk-3c5x7-2h6so-njoeq-mt45d-h3h6c-q3mxf-vpeez-fez7a-iae), both controlled by the NNS root canister. The **ledger** is an [ICRC-1/ICRC-2](../../references/icrc-standards.md) compliant ledger that records all ckBTC balances and handles transfers. The **minter** manages the BTC side: it controls Bitcoin addresses, tracks UTXOs, triggers minting when deposits arrive, and signs and submits Bitcoin transactions when users withdraw. + +For canister IDs, minter parameters, and endpoint reference, see [ckBTC minter](../../references/protocol-canisters.md#ckbtc-minter) and [Chain-Key Token Canister IDs](../../references/chain-key-canister-ids.md#ckbtc). + +### Converting BTC to ckBTC + +```plantuml +actor User +participant "ckBTC Minter" as Minter +participant "Bitcoin Checker" as KYT +participant "ckBTC Ledger" as Ledger +participant "Bitcoin Network" as BTC + +User -> Minter: get_btc_address(owner, subaccount) +Minter --> User: btc_address +User -> BTC: send BTC to btc_address +note right of BTC: 4 confirmations required +User -> Minter: update_balance(owner, subaccount) +Minter -> KYT: check UTXO +KYT --> Minter: ok +Minter -> Ledger: mint ckBTC (amount - kyt_fee) +Minter --> User: MintedUtxos +``` + +1. The user calls `get_btc_address` on the minter to receive a deposit address (a P2WPKH address) tied to their principal. +2. The user sends bitcoin to that address on the Bitcoin network. +3. After 4 confirmations, the user calls `update_balance` on the minter. +4. The minter fetches UTXOs for the deposit address via `bitcoin_get_utxos` and checks each new UTXO with the Bitcoin checker canister. UTXOs that pass the check are minted as ckBTC into the user's ledger account (minus a KYT fee). UTXOs that fail the check are quarantined. + +The 4-confirmation requirement protects against Bitcoin chain reorganizations. + +### Converting ckBTC to BTC + +```plantuml +actor User +participant "ckBTC Ledger" as Ledger +participant "ckBTC Minter" as Minter +participant "Bitcoin Checker" as KYT +participant "Bitcoin Network" as BTC + +User -> Ledger: icrc2_approve(spender=minter, amount) +User -> Minter: retrieve_btc_with_approval(btc_address, amount) +Minter -> KYT: check destination address +KYT --> Minter: ok +Minter -> Ledger: icrc2_transfer_from(user, minter, amount) +Minter --> User: block_index +note right of Minter: processed asynchronously +Minter -> BTC: submit signed transaction +``` + +The recommended flow uses ICRC-2 approval: + +1. The user calls `icrc2_approve` on the ckBTC ledger, authorizing the minter to withdraw the desired amount. +2. The user calls `retrieve_btc_with_approval` on the minter, specifying the amount and destination Bitcoin address. +3. The minter checks the destination address with the Bitcoin checker canister. If it passes, the minter burns the ckBTC from the user's account and queues a Bitcoin withdrawal. +4. The minter periodically batches pending requests, selects UTXOs, builds a Bitcoin transaction, signs each input using threshold ECDSA, and submits via `bitcoin_send_transaction`. + +Requests are batched to reduce Bitcoin miner fees. For the minimum withdrawal amount, fee formula, and UTXO consolidation behavior, see [ckBTC minter](../../references/protocol-canisters.md#ckbtc-minter). + +## Next steps + +- [Bitcoin guide](../../guides/chain-fusion/bitcoin.md): build Bitcoin transactions from a canister, with code and development setup +- [Dogecoin integration](dogecoin.md): Bitcoin fork integration using the same architecture +- [Chain Fusion overview](index.md): integration patterns and supported chains +- [Chain-key cryptography](../chain-key-cryptography.md): threshold ECDSA and Schnorr signing +- [Protocol canisters reference](../../references/protocol-canisters.md#bitcoin-canisters): canister IDs, cycle costs, and API details +- [Chain-Key Token Canister IDs](../../references/chain-key-canister-ids.md#ckbtc): full ckBTC canister ID table including index and testnet + + diff --git a/docs/concepts/chain-fusion/chain-key-tokens.md b/docs/concepts/chain-fusion/chain-key-tokens.md new file mode 100644 index 00000000..44a0a2bd --- /dev/null +++ b/docs/concepts/chain-fusion/chain-key-tokens.md @@ -0,0 +1,71 @@ +--- +title: "Chain-key tokens" +description: "Trustless 1:1 representations of external chain assets on ICP" +--- + +Chain-key tokens are ICP-native assets backed 1:1 by assets native to another chain. ckBTC represents bitcoin, ckETH represents ether, ckUSDC represents USDC on Ethereum, and so on. Each is fully backed by the underlying asset (held in a canister-controlled address on the origin chain), and all minting and burning happens entirely onchain, with no third-party custodian. + +## Why chain-key tokens instead of wrapped assets + +Traditional wrapped assets depend on an offchain custodian that holds the underlying asset and instructs a contract to mint or burn the wrapped version. If the custodian is compromised, hacked, or goes out of business, the backing can be lost entirely. Additionally, nothing prevents a dishonest custodian from using the custodied assets for other purposes, risking a depeg. + +Chain-key tokens eliminate the custodian. The underlying assets are held by a minter canister at a network address derived from a chain-key key, an address no single party controls. Minting and burning are triggered by verifiable onchain events (confirmed Bitcoin UTXOs, Ethereum event logs), and the minter signs withdrawal transactions using threshold cryptography distributed across a subnet's nodes. + +## Architecture + +Every chain-key token uses a set of canisters: + +1. **Minter**: manages the underlying asset on the origin chain. It controls the deposit address (or Ethereum helper contract), detects incoming deposits, instructs the ledger to mint tokens, and signs and submits withdrawals when tokens are burned. +2. **Ledger**: an ICRC-1/ICRC-2 compliant ledger. It records all balances and executes mint, burn, and transfer operations. +3. **Index**: provides indexed access to ledger transactions, enabling efficient lookup of an account's transaction history. +4. **Archive** (optional): stores historical transaction data that has been offloaded from the ledger to keep it compact. + +All canisters in a chain-key token system are controlled by the NNS, making the asset governance fully decentralized. + +## Minting (getting chain-key tokens) + +The minting process differs slightly by chain: + +**Bitcoin-based tokens (ckBTC, ckDOGE).** The user requests a deposit address from the minter. This is a chain-key ECDSA address controlled by the minter. The user sends the underlying asset to this address on the Bitcoin or Dogecoin network. Once the transaction reaches the required confirmation threshold (4 confirmations for ckBTC), the user calls `update_balance` on the minter. The minter verifies the deposit via the Bitcoin canister and mints the corresponding amount on the ledger. + +**EVM-based tokens (ckETH, ckERC20).** A helper smart contract deployed on Ethereum receives deposits. When a user sends ETH or an ERC-20 asset to the helper contract, it emits an event. The minter periodically queries these event logs via the EVM RPC canister (see [Ethereum integration](ethereum.md)) and mints the corresponding chain-key tokens on the ICP ledger. + +## Burning (redeeming underlying assets) + +All chain-key token redemptions use ICRC-2 approval: + +1. The user calls `icrc2_approve` on the ledger to authorize the minter to withdraw the desired amount. +2. The user calls the minter's withdrawal endpoint (for example, `retrieve_btc_with_approval` for ckBTC). +3. The minter burns the chain-key tokens from the user's account. +4. The minter constructs a transaction on the origin chain, signs it using chain-key cryptography (threshold ECDSA for Bitcoin and Ethereum; threshold Ed25519 for Solana), and submits it. + +For EVM-based tokens, the gas fee on Ethereum must be covered. ckETH acts as the fee currency: when redeeming ckERC20 tokens, the user also approves a small ckETH amount to cover the Ethereum gas cost. + +## Chain-key token security + +The security of a chain-key token rests on two properties: + +- **Supply bound.** The minter never mints more chain-key tokens than the underlying assets it controls. The total ckBTC supply, for example, is always at most equal to the BTC held at minter-controlled Bitcoin addresses. +- **Threshold custody.** The minter's private key is never held by a single party. Withdrawal transactions are signed collectively by the subnet nodes through the chain-key protocol, so a single compromised node cannot authorize unauthorized withdrawals. + +## Deployed assets + +| Asset | Underlying | Origin chain | Integration method | +|---|---|---|---| +| ckBTC | BTC | Bitcoin | Direct | +| ckETH | ETH | Ethereum | EVM RPC canister | +| ckERC20 (ckUSDC, ckUSDT, ...) | ERC-20 assets | Ethereum | EVM RPC canister | +| ckSOL | SOL | Solana | SOL RPC canister | +| ckDOGE | DOGE | Dogecoin | Direct | + +## Next steps + +- [Bitcoin integration](bitcoin.md): ckBTC minter and ledger in detail +- [Ethereum integration](ethereum.md): ckETH and ckERC20 architecture +- [Chain Fusion overview](index.md): the full landscape of ICP crosschain capabilities +- [Chain-key tokens guide](../../guides/digital-assets/chain-key-tokens.md): how to integrate chain-key tokens into an application +- [Chain-key cryptography](../chain-key-cryptography.md): the threshold signing that makes chain-key tokens possible +- [Chain-Key Token Canister IDs](../../references/chain-key-canister-ids.md): minter, ledger, and index IDs for all chain-key tokens +- [Protocol canisters reference](../../references/protocol-canisters.md): minter parameters and endpoints for ckBTC, ckETH, ckDOGE, and ckSOL + + diff --git a/docs/concepts/chain-fusion/dogecoin.md b/docs/concepts/chain-fusion/dogecoin.md new file mode 100644 index 00000000..869b42fc --- /dev/null +++ b/docs/concepts/chain-fusion/dogecoin.md @@ -0,0 +1,57 @@ +--- +title: "Dogecoin integration" +description: "How ICP connects to Dogecoin using the same architecture as the Bitcoin integration" +--- + +ICP supports a native Dogecoin integration that works the same way as the [Bitcoin integration](bitcoin.md). Because Dogecoin is a Bitcoin fork, it reuses the same two-component architecture: a dedicated adapter that communicates with the Dogecoin network, and a Dogecoin canister that maintains the current chain state and exposes a query-and-send API to other canisters. + +## Architecture + +The _Dogecoin adapter_ is a process that runs alongside the ICP replica on each node. It speaks the Dogecoin peer-to-peer protocol, syncs blocks from the Dogecoin network, and relays transactions. The _Dogecoin canister_ ([source](https://github.com/dfinity/dogecoin-canister)) is a canister running on a system subnet that consumes blocks from the adapter, maintains the UTXO set, and exposes endpoints for balance queries, UTXO retrieval, fee estimation, and transaction submission. + +Canister-controlled Dogecoin addresses are derived from chain-key ECDSA public keys, just as in the Bitcoin integration. Transactions are signed using the management canister's `sign_with_ecdsa` API and broadcast to the Dogecoin network through the adapter. + +![Dogecoin integration architecture: a canister calls the Dogecoin canister through the ICP protocol stack, while the Dogecoin adapter connects to the Dogecoin peer-to-peer network](/concepts/chain-fusion/dogecoin-architecture.png) + +## Chain-key DOGE (ckDOGE) + +ckDOGE is the chain-key token representing Dogecoin on ICP, backed 1:1 by real DOGE held in a canister-controlled address. The minter-plus-ledger architecture is the same as [ckBTC](bitcoin.md#chain-key-bitcoin-ckbtc): users deposit DOGE to a minter-controlled address, the minter mints ckDOGE on the ledger, and withdrawals trigger an onchain Dogecoin transaction signed with threshold ECDSA. + +### Depositing DOGE (DOGE to ckDOGE) + +```plantuml +actor User +participant "ckDOGE Minter" as Minter +participant "Dogecoin Network" as DOGE + +User -> Minter: get_doge_address(account) +Minter --> User: doge_address +User -> DOGE: send DOGE to doge_address +User -> Minter: update_balance(account) +Minter --> User: ckDOGE minted to ICRC-1 account +``` + +### Withdrawing DOGE (ckDOGE to DOGE) + +```plantuml +actor User +participant "ckDOGE Ledger" as Ledger +participant "ckDOGE Minter" as Minter +participant "Dogecoin Network" as DOGE + +User -> Ledger: icrc2_approve(spender=minter, amount) +User -> Minter: retrieve_doge_with_approval(doge_address, amount) +Minter -> Ledger: icrc2_transfer_from(user, minter, amount) +Minter -> DOGE: send DOGE to doge_address +``` + +## Next steps + +- [Bitcoin integration](bitcoin.md): detailed description of the shared adapter and canister architecture +- [Dogecoin canister documentation](https://dfinity.github.io/dogecoin-canister/) +- [Dogecoin guide](../../guides/chain-fusion/dogecoin.md): code examples and canister API +- [Chain Fusion overview](index.md): integration patterns and supported chains +- [Dogecoin canister reference](../../references/protocol-canisters.md#dogecoin-canister): API endpoints +- [Chain-Key Token Canister IDs: ckDOGE](../../references/chain-key-canister-ids.md#ckdoge): ckDOGE minter and ledger IDs + + diff --git a/docs/concepts/chain-fusion/ethereum.md b/docs/concepts/chain-fusion/ethereum.md new file mode 100644 index 00000000..0318f315 --- /dev/null +++ b/docs/concepts/chain-fusion/ethereum.md @@ -0,0 +1,108 @@ +--- +title: "Ethereum integration" +description: "How ICP connects to Ethereum and EVM chains via HTTPS outcalls, chain-key ECDSA, and the EVM RPC canister" +--- + +Canisters on ICP can interact with Ethereum and any EVM-compatible chain (Polygon, Avalanche, Arbitrum, Base, Optimism, and others) without bridges or trusted intermediaries. The integration combines two ICP capabilities: [HTTPS outcalls](../https-outcalls.md) to read chain state and [chain-key ECDSA signatures](../chain-key-cryptography.md) to authorize transactions. + +## How it works + +**Reading Ethereum state.** Canisters query Ethereum via JSON-RPC, the same API used by standard Ethereum clients. Because HTTPS outcalls involve all subnet replicas independently fetching the URL and reaching consensus on the response, the result has strong integrity guarantees. Rather than making raw HTTPS outcalls directly, most canisters use the EVM RPC canister, which provides a typed Candid interface and handles multi-provider redundancy automatically. + +**Signing Ethereum transactions.** Each canister can derive an Ethereum address from its chain-key ECDSA public key. To authorize a transaction, the canister calls `sign_with_ecdsa` on the management canister, receives a threshold signature produced by the subnet nodes collectively, and includes the signature in the serialized transaction before submitting it. + +**Submitting Ethereum transactions.** The signed transaction is submitted via the EVM RPC canister's `eth_sendRawTransaction` endpoint, which relays it to multiple JSON-RPC providers for broadcast. + +This flow (query, sign, submit) lets canisters call any Ethereum smart contract, hold ETH or ERC-20 assets, and participate in DeFi protocols entirely from onchain ICP code. + +## EVM RPC canister + +The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) is a system-level canister that acts as a gateway between ICP canisters and Ethereum JSON-RPC APIs. It is controlled by the NNS, so its behavior cannot be changed by any single party. For supported chains, built-in providers, and cycle costs, see [EVM RPC canister](../../references/protocol-canisters.md#evm-rpc-canister). + +```plantuml +left to right direction + +package "Internet Computer" { + component "Your Canister" as UC + component "EVM RPC Canister" as EVM +} + +package "JSON-RPC Providers" { + component "Provider 1" as P1 + component "Provider 2" as P2 + component "Provider N" as PN +} + +package "Ethereum" { + component "Smart contracts" as SC +} + +UC <--> EVM +EVM --> P1 +EVM --> P2 +EVM --> PN +P1 --> SC +P2 --> SC +PN --> SC +``` + +### Multi-provider architecture + +```plantuml +participant "Your Canister" as Canister +participant "EVM RPC Canister" as EVM +participant "Provider 1" as P1 +participant "Provider 2" as P2 +participant "Provider N" as PN + +Canister -> EVM: eth_getBlockByNumber(chain, args) + cycles +EVM -> P1: JSON-RPC (HTTPS outcall) +EVM -> P2: JSON-RPC (HTTPS outcall) +EVM -> PN: JSON-RPC (HTTPS outcall) +P1 --> EVM: response +P2 --> EVM: response +PN --> EVM: response +note right of EVM: consensus check (≥2/3 nodes agree) +EVM --> Canister: Consistent(result) + refund excess cycles +``` + +For each Candid-RPC method (such as `eth_getTransactionReceipt` or `eth_getBlockByNumber`), the EVM RPC canister sends the request to at least three independent JSON-RPC providers by default and compares the results. Supported providers include [CloudFlare](https://www.cloudflare.com/), [Alchemy](https://www.alchemy.com/), [Ankr](https://www.ankr.com/), and [BlockPI](https://blockpi.io/). + +Results are returned in one of two forms: + +- **Consistent**: all queried providers returned the same result. This is the expected case for finalized data. +- **Inconsistent**: providers returned different results. The caller receives the full set of results and can decide how to handle the discrepancy (for example, by waiting for more confirmations or querying additional providers). + +Callers can override the defaults: specifying a different number of providers, listing concrete providers to use, or setting a minimum agreement threshold. + +### Available methods + +The EVM RPC canister supports the standard JSON-RPC Ethereum API, including: + +- `eth_getBlockByNumber`, `eth_getBlockByHash`: block data +- `eth_getTransactionCount`, `eth_getTransactionByHash`, `eth_getTransactionReceipt`: transaction data +- `eth_getLogs`: event logs (used to detect deposits for chain-key tokens) +- `eth_feeHistory`, `eth_gasPrice`: fee estimation +- `eth_sendRawTransaction`: broadcast a signed transaction +- `eth_call`: call a smart contract read function + +Beyond Ethereum mainnet, the canister also has partial support for Polygon, Avalanche, and other popular EVM networks. + +## Chain-key Ether and ERC-20 tokens + +ckETH and ckERC20 tokens (such as ckUSDC and ckUSDT) are chain-key tokens backed 1:1 by assets on Ethereum. They follow the same architecture as ckBTC (a minter canister plus an ICRC-1/ICRC-2 ledger canister) but use a different deposit mechanism. + +**Deposits.** Because ICP cannot observe Ethereum state directly (unlike Bitcoin, which uses a native adapter), ckETH uses a helper smart contract deployed on Ethereum. Users send ETH or ERC-20 assets to this helper contract, which emits an event. The ckETH minter periodically queries the event log via the EVM RPC canister to discover deposits and mints the corresponding chain-key tokens. + +For full minting, redemption, and security model details, see [Chain-key tokens](chain-key-tokens.md). + +## Next steps + +- [Ethereum guide](../../guides/chain-fusion/ethereum.md): code examples for reading state and sending transactions +- [Chain Fusion overview](index.md): integration patterns and supported chains +- [HTTPS outcalls](../https-outcalls.md): how canisters reach external HTTP endpoints +- [Chain-key cryptography](../chain-key-cryptography.md): threshold ECDSA signing +- [Chain-key tokens](chain-key-tokens.md): ckETH and ckERC20 architecture +- [Chain-Key Token Canister IDs](../../references/chain-key-canister-ids.md#cketh): ckETH minter, ledger, and index IDs + + diff --git a/docs/concepts/chain-fusion/exchange-rate-canister.md b/docs/concepts/chain-fusion/exchange-rate-canister.md new file mode 100644 index 00000000..59a50ff9 --- /dev/null +++ b/docs/concepts/chain-fusion/exchange-rate-canister.md @@ -0,0 +1,45 @@ +--- +title: "Exchange rate canister" +description: "Oracle for cryptocurrency and fiat exchange rates running as a system canister on ICP" +--- + +The exchange rate canister (XRC) is a system canister that provides exchange rates to other canisters. It runs on the [uzr34 system subnet](https://dashboard.internetcomputer.org/subnet/uzr34-akd3s-xrdag-3ql62-ocgoh-ld2ao-tamcv-54e7j-krwgb-2gm4z-oqe) and uses [HTTPS outcalls](../https-outcalls.md) to fetch real-time and historical price data from major exchanges and forex data providers. + +The canister ID is `uf6dk-hyaaa-aaaaq-qaaaq-cai`. + +The NNS cycle minting canister uses the XRC to convert ICP to cycles at the XDR-pegged rate. Application canisters can also call the XRC directly to build financial features such as decentralized exchanges, payment systems, and portfolio tools. + +## Supported rate types + +The XRC handles three combinations of asset class: + +- **Cryptocurrency / fiat**: for example, `ICP/USD`, `BTC/EUR`. The XRC fetches live crypto rates and combines them with its cached forex data. +- **Cryptocurrency / cryptocurrency**: for example, `BTC/ICP`. Each asset is independently quoted against USDT, and the cross rate is derived from those two results. +- **Fiat / fiat**: for example, `USD/EUR`. Served entirely from periodically cached forex data at minimal cycle cost. + +## How rates are computed + +![Exchange rate canister data flow: the XRC pulls daily forex rates from forex providers and real-time crypto rates from exchanges, then returns the median rate and metadata to the requesting canister](/concepts/chain-fusion/exchange-rate-canister-flow.png) + +When a cryptocurrency rate is not in the cache, the XRC queries all supported exchanges via HTTPS outcalls to get the asset's price against USDT. It collects candlestick data for the requested one-minute interval across exchanges, then returns the **median** of all received rates. The median makes the result resistant to outliers from any single exchange and cannot be manipulated by a minority of data sources. + +For cryptocurrency/cryptocurrency pairs such as BTC/ICP, the XRC derives the result from independent BTC/USDT and ICP/USDT rates using a cross-product approach before taking the median, rather than requiring BTC/ICP to be directly traded. + +For fiat currencies, the XRC downloads daily forex rates from forex data providers on a fixed schedule. USD/USDT is derived by taking the median of rates for several stablecoins against USDT, based on the assumption that at least half of the included stablecoins maintain their USD peg at any given time. + +If the XRC receives largely inconsistent rates across exchanges, it returns an `InconsistentRatesReceived` error rather than returning a potentially unreliable result. + +## Cycle cost + +Every request requires 1 billion cycles attached upfront. Unused cycles are refunded after the call. The actual cost depends on whether the result is served from cache and what asset classes are involved. For the full cost breakdown, see [Exchange rate canister (XRC)](../../references/protocol-canisters.md#exchange-rate-canister-xrc). + +Because cycles must be attached to an inter-canister call, you can only call the XRC from canister code, not directly from the CLI. For how to do this in Rust and Motoko, see the [Fetch exchange rates guide](../../guides/chain-fusion/exchange-rates.md). + +## Next steps + +- [Fetch exchange rates](../../guides/chain-fusion/exchange-rates.md): how to call the XRC from your canister in Rust and Motoko +- [Exchange rate canister reference](../../references/protocol-canisters.md#exchange-rate-canister-xrc): canister ID, full Candid interface, cycle cost table, and data sources +- [HTTPS outcalls](../https-outcalls.md): how the XRC fetches external data +- [Chain Fusion overview](index.md): integration patterns and supported chains + + diff --git a/docs/concepts/chain-fusion.md b/docs/concepts/chain-fusion/index.md similarity index 52% rename from docs/concepts/chain-fusion.md rename to docs/concepts/chain-fusion/index.md index a746c8f5..e6c896ea 100644 --- a/docs/concepts/chain-fusion.md +++ b/docs/concepts/chain-fusion/index.md @@ -5,20 +5,20 @@ sidebar: order: 10 --- -Chain Fusion is ICP's approach to cross-chain interoperability. Instead of relying on bridges or oracles, canisters interact with other blockchains directly: they can read state, hold assets, and sign and submit transactions on Bitcoin, Ethereum, Solana, and dozens of other chains. All of this runs onchain with the same trust assumptions as the Internet Computer itself. +Chain Fusion is ICP's approach to crosschain interoperability. Instead of relying on bridges or oracles, canisters interact with other networks directly: they can read state, hold assets, and sign and submit transactions on Bitcoin, Ethereum, Solana, and dozens of other chains. All of this runs onchain with the same trust assumptions as the Internet Computer itself. -The foundation is [chain-key cryptography](chain-key-cryptography.md). Each canister can derive keys for external signature schemes (ECDSA and Schnorr) and request threshold signatures from the protocol. This means a canister can control a Bitcoin address, an Ethereum account, or a Solana wallet: without any single node ever holding the private key. +The foundation is [chain-key cryptography](../chain-key-cryptography.md). Each canister can derive keys for external signature schemes (ECDSA and Schnorr) and request threshold signatures from the protocol. This means a canister can control a Bitcoin address, an Ethereum account, or a Solana wallet: without any single node ever holding the private key. ## Why Chain Fusion matters -Most cross-chain solutions introduce a trusted intermediary: a bridge, a multisig, or an oracle network. If that intermediary is compromised, funds are at risk. ICP eliminates this layer entirely. +Most crosschain solutions introduce a trusted intermediary: a bridge, a multisig, or an oracle network. If that intermediary is compromised, funds are at risk. ICP eliminates this layer entirely. A canister interacting with Bitcoin or Ethereum has no external dependency beyond the target chain itself. The signing happens inside the protocol through a threshold cryptographic ceremony distributed across subnet nodes. This gives developers several advantages: -- **No bridges.** Canisters hold assets directly on external chains. There is no wrapped token that can depeg, no bridge contract that can be exploited. -- **No oracles.** Canisters can read external chain state themselves: either through a direct protocol integration (Bitcoin) or by querying RPC providers via [HTTPS outcalls](https-outcalls.md). -- **Full autonomy.** Canisters can schedule cross-chain actions using [timers](../guides/backends/timers.md), enabling use cases like automated trading, periodic liquidations, or cronjob services: all without external triggers. -- **Familiar UX.** Because ICP has low-cost computation and [canisters pay for their own cycles](cycles.md), users can interact with cross-chain apps through a standard browser without installing a wallet. +- **No bridges.** Canisters hold assets directly on external chains. There is no wrapped asset that can depeg, no bridge contract that can be exploited. +- **No oracles.** Canisters can read external chain state themselves: either through a direct protocol integration (Bitcoin) or by querying RPC providers via [HTTPS outcalls](../https-outcalls.md). +- **Full autonomy.** Canisters can schedule crosschain actions using [timers](../../guides/backends/timers.md), enabling use cases like automated trading, periodic liquidations, or cronjob services: all without external triggers. +- **Familiar UX.** Because ICP has low-cost computation and [canisters pay for their own cycles](../cycles.md), users can interact with crosschain apps through a standard browser without installing a wallet. ## How it works @@ -26,7 +26,7 @@ Chain Fusion combines three protocol-level capabilities: ### 1. Chain-key signatures -Canisters request threshold ECDSA or Schnorr signatures from the management canister. The protocol derives a unique key for each canister and signs messages without ever reconstructing the private key. This lets canisters control addresses on any blockchain that uses a supported signature scheme. +Canisters request threshold ECDSA or Schnorr signatures from the management canister. The protocol derives a unique key for each canister and signs messages without ever reconstructing the private key. This lets canisters control addresses on any chain that uses a supported signature scheme. Two schemes are available: @@ -36,21 +36,21 @@ Two schemes are available: | Threshold Schnorr (`bip340secp256k1`) | Bitcoin Taproot, Ordinals | | Threshold Schnorr (`ed25519`) | Solana, TON, Polkadot, Cardano, NEAR, Stellar | -See [Chain-key cryptography](chain-key-cryptography.md) for details on the threshold signing protocols, key derivation, and deployed keys. +See [Chain-key cryptography](../chain-key-cryptography.md) for details on the threshold signing protocols, key derivation, and deployed keys. ### 2. Reading external chain state A canister needs to read the state of an external chain to verify events, check balances, or monitor smart contracts. ICP supports two models: -- **Direct integration.** The protocol runs a native adapter that connects to the external chain's peer-to-peer network. Bitcoin uses this model: ICP nodes run a Bitcoin adapter that syncs blocks directly, so canisters can query UTXOs and submit transactions through the management canister's Bitcoin API without any intermediary. +- **Direct integration.** The protocol runs a native adapter that connects to the external chain's peer-to-peer network. Bitcoin uses this model: ICP nodes run a Bitcoin adapter that syncs blocks directly, so canisters can query UTXOs and submit transactions through the Bitcoin canister API without any intermediary. -- **RPC integration.** For chains without a direct integration, canisters use [HTTPS outcalls](https-outcalls.md) to query RPC providers. The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) provides a typed Candid interface for Ethereum and EVM-compatible chains. It sends each request to at least three independent RPC providers and returns either a `Consistent` result (all providers agree) or an `Inconsistent` result that the caller can handle. Solana has a similar dedicated canister (SOL RPC). For other chains, canisters can make raw HTTPS outcalls to any JSON-RPC endpoint. +- **RPC integration.** For chains without a direct integration, canisters use [HTTPS outcalls](../https-outcalls.md) to query RPC providers. The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) provides a typed Candid interface for Ethereum and EVM-compatible chains. It sends each request to at least three independent RPC providers and returns either a `Consistent` result (all providers agree) or an `Inconsistent` result that the caller can handle. Solana has a similar dedicated canister (SOL RPC). For other chains, canisters can make raw HTTPS outcalls to any JSON-RPC endpoint. ### 3. Submitting transactions Once a canister has signed a transaction, it needs to submit it to the target chain. The submission path depends on the integration model: -- **Bitcoin:** The signed transaction is submitted through the management canister's `bitcoin_send_transaction` API, which broadcasts it via the Bitcoin adapter. +- **Bitcoin:** The signed transaction is submitted through the Bitcoin canister's `bitcoin_send_transaction` API, which broadcasts it via the Bitcoin adapter. - **Ethereum and EVM chains:** The signed transaction is submitted via the EVM RPC canister's `eth_sendRawTransaction` endpoint, which relays it to RPC providers. - **Other chains:** The canister submits the transaction by making an HTTPS outcall to the chain's RPC endpoint. @@ -68,15 +68,15 @@ Direct integration provides the strongest trust guarantees. The only assumption ## Chain-key tokens -Chain-key tokens are digital twins of native assets from other blockchains (for example, ckBTC for Bitcoin and ckETH for Ethereum). Each token is backed 1:1 by the native asset, which is held in a canister-controlled address on the source chain. Minting and burning happen entirely onchain. No bridge, no custodian. +Chain-key tokens are ICP-native assets backed 1:1 by assets native to another chain (for example, ckBTC for Bitcoin and ckETH for Ethereum). Each is held in a canister-controlled address on the source chain. Minting and burning happen entirely onchain. No bridge, no custodian. -These tokens implement the [ICRC-2](../guides/digital-assets/ledgers.md) token standard, so they can be transferred and traded within the ICP ecosystem with the same speed and cost as any other ICP token. When a user wants to redeem the underlying asset, the minter canister signs and submits a withdrawal transaction on the source chain. +These tokens implement the [ICRC-2](../../guides/digital-assets/ledgers.md#approve-and-transfer-from-icrc-2) standard, so they can be transferred and traded within the ICP ecosystem with the same speed and cost as any other ICP asset. When a user wants to redeem the underlying asset, the minter canister signs and submits a withdrawal transaction on the source chain. -For details on integrating with chain-key tokens, see the [Chain-key tokens guide](../guides/digital-assets/chain-key-tokens.md). +For details on chain-key token architecture, see [Chain-key tokens](chain-key-tokens.md). For integration guides, see the [Chain-key tokens guide](../../guides/digital-assets/chain-key-tokens.md). ## Supported chains -Any blockchain whose transactions use ECDSA (secp256k1), Schnorr (BIP340 over secp256k1), or Ed25519 signatures can be integrated with ICP. The following table lists chains with established integrations or community-built tooling: +Any chain whose transactions use ECDSA (secp256k1), Schnorr (BIP340 over secp256k1), or Ed25519 signatures can be integrated with ICP. The following table lists chains with established integrations or community-built tooling: | Chain | Signature scheme | Integration method | Chain-key token | |-------|-----------------|-------------------|-----------------| @@ -101,10 +101,10 @@ This is not exhaustive. If a chain uses a supported signature scheme and has RPC Several reusable canisters and protocol APIs are available for building Chain Fusion applications: -- **Bitcoin API.** The management canister exposes `bitcoin_get_utxos`, `bitcoin_get_balance`, and `bitcoin_send_transaction`: a direct protocol-level integration with no intermediary. See [Bitcoin integration](../guides/chain-fusion/bitcoin.md). -- **EVM RPC canister** (`7hfb6-caaaa-aaaar-qadga-cai`). A canister providing a typed Candid interface for Ethereum and EVM-compatible chains. Queries multiple RPC providers and returns consensus results. See [Ethereum integration](../guides/chain-fusion/ethereum.md). -- **SOL RPC canister.** A similar canister for Solana, providing typed access to Solana's JSON-RPC API. See [Solana integration](../guides/chain-fusion/solana.md). -- **Chain-key tokens.** Minter and ledger canisters that implement ckBTC, ckETH, and ckERC20: trustless 1:1 representations of external assets on ICP. See [Chain-key tokens](../guides/digital-assets/chain-key-tokens.md). +- **Bitcoin API.** The Bitcoin canister exposes `bitcoin_get_utxos`, `bitcoin_get_balance`, and `bitcoin_send_transaction`: a direct protocol-level integration with no intermediary. See [Bitcoin integration](bitcoin.md) and the [Bitcoin guide](../../guides/chain-fusion/bitcoin.md). +- **EVM RPC canister** (`7hfb6-caaaa-aaaar-qadga-cai`). A canister providing a typed Candid interface for Ethereum and EVM-compatible chains. Queries multiple RPC providers and returns consensus results. See [Ethereum integration](ethereum.md) and the [Ethereum guide](../../guides/chain-fusion/ethereum.md). +- **SOL RPC canister.** A similar canister for Solana, providing typed access to Solana's JSON-RPC API. See [Solana integration](solana.md) and the [Solana guide](../../guides/chain-fusion/solana.md). +- **Chain-key tokens.** Minter and ledger canisters that implement ckBTC, ckETH, and ckERC20: trustless 1:1 representations of external assets on ICP. See [Chain-key tokens](chain-key-tokens.md) and the [integration guide](../../guides/digital-assets/chain-key-tokens.md). - **Chain Fusion Signer.** A reusable canister that exposes threshold signature APIs directly to web apps and CLI users, with cycle payments via ICRC-2 approval. [OISY Wallet](https://oisy.com) is a prominent production example: a multichain wallet built on ICP that uses the Chain Fusion Signer to manage keys for Bitcoin, Ethereum, and other chains. See the [chain-fusion-signer repository](https://github.com/dfinity/chain-fusion-signer). ## Example use cases @@ -113,16 +113,20 @@ Chain Fusion enables application patterns that are difficult or impossible with - **Trustless cronjob service.** A canister monitors an Ethereum contract via the EVM RPC canister and triggers loan liquidations or batch settlements automatically using timers. No Gelato or Chainlink Keepers needed. - **Multichain wallet.** A single canister controls addresses on Bitcoin, Ethereum, and Solana simultaneously. Users interact through a web frontend served from ICP without installing chain-specific wallets. -- **Tamperproof frontend.** An immutable or DAO-governed frontend for an Ethereum smart contract, hosted on ICP as a certified asset. Users interact with the Ethereum contract through the ICP-hosted UI. -- **Cross-chain lending.** A lending protocol that accepts Bitcoin as collateral (held in a canister-controlled BTC address) and issues stablecoins as ICRC-2 tokens. +- **Tamperproof frontend.** An immutable or community-governed frontend for an Ethereum smart contract, hosted on ICP as a certified asset. Users interact with the Ethereum contract through the ICP-hosted UI. +- **Crosschain lending.** A lending protocol that accepts Bitcoin as collateral (held in a canister-controlled BTC address) and issues stablecoins as ICRC-2 assets. - **Data relay.** A canister fetches real-world data via HTTPS outcalls and posts it to a smart contract on another chain: replacing centralized oracle networks. ## Next steps -- [Bitcoin integration](../guides/chain-fusion/bitcoin.md): build with BTC on ICP -- [Ethereum integration](../guides/chain-fusion/ethereum.md): interact with Ethereum and EVM chains -- [Chain-key tokens](../guides/digital-assets/chain-key-tokens.md): ckBTC, ckETH, and ckERC20 -- [Chain-key cryptography](chain-key-cryptography.md): the threshold signing protocols behind Chain Fusion -- [HTTPS outcalls](https-outcalls.md): make HTTP requests from canisters - - +- [Bitcoin integration](bitcoin.md): how the Bitcoin adapter and ckBTC work +- [Ethereum integration](ethereum.md): Ethereum, EVM chains, and the EVM RPC canister +- [Solana integration](solana.md): the SOL RPC canister +- [Chain-key tokens](chain-key-tokens.md): architecture of trustless crosschain assets +- [Exchange rate canister](exchange-rate-canister.md): onchain oracle for asset prices +- [Bitcoin guide](../../guides/chain-fusion/bitcoin.md): build with BTC on ICP +- [Ethereum guide](../../guides/chain-fusion/ethereum.md): interact with Ethereum and EVM chains +- [Chain-key cryptography](../chain-key-cryptography.md): the threshold signing protocols behind Chain Fusion +- [HTTPS outcalls](../https-outcalls.md): make HTTP requests from canisters + + diff --git a/docs/concepts/chain-fusion/solana.md b/docs/concepts/chain-fusion/solana.md new file mode 100644 index 00000000..fc3e98fa --- /dev/null +++ b/docs/concepts/chain-fusion/solana.md @@ -0,0 +1,108 @@ +--- +title: "Solana integration" +description: "How canisters interact with Solana via the SOL RPC canister" +--- + +Canisters on ICP can query and interact with the Solana network through the SOL RPC canister. The architecture mirrors the [Ethereum integration](ethereum.md): [HTTPS outcalls](../https-outcalls.md) are used to query Solana's JSON-RPC API, and [chain-key Schnorr signatures (Ed25519)](../chain-key-cryptography.md) enable canisters to sign Solana transactions. + +## SOL RPC canister + +The [SOL RPC canister](https://github.com/dfinity/sol-rpc-canister) is a system-level canister that acts as a gateway between ICP canisters and Solana's JSON-RPC API. Like the EVM RPC canister, it is controlled by the NNS and uses multiple independent JSON-RPC providers to ensure responses are not sourced from a single centralized party. + +Supported providers include [Alchemy](https://www.alchemy.com/), [Ankr](https://www.ankr.com/), [Chainstack](https://chainstack.com/), [dRPC](https://drpc.org/), [Helius](https://www.helius.dev/), and [PublicNode](https://publicnode.com/). + +Each request is forwarded to multiple providers. If providers return consistent results, that response is passed back to the calling canister. The NNS controls which providers are registered and how the canister behaves, so no single entity can alter its operation. + +```plantuml +left to right direction + +package "Internet Computer" { + component "Your Canister" as UC + component "SOL RPC Canister" as SolRpc +} + +package "JSON-RPC Providers" { + component "Provider 1" as P1 + component "Provider 2" as P2 + component "Provider N" as PN +} + +package "Solana" { + component "Programs" as SC +} + +UC <--> SolRpc +SolRpc --> P1 +SolRpc --> P2 +SolRpc --> PN +P1 --> SC +P2 --> SC +PN --> SC +``` + +```plantuml +participant "Your Canister" as Canister +participant "SOL RPC Canister" as SolRpc +participant "Solana Providers" as Providers +participant "Solana" as SOL + +Canister -> SolRpc: request(json_rpc, max_response_bytes) + cycles +SolRpc -> Providers: HTTPS outcalls to multiple providers +Providers --> SolRpc: aggregated responses +SolRpc --> Canister: result + refund excess cycles +``` + +## Signing Solana transactions + +Solana uses Ed25519 signatures. Canisters can derive Ed25519 public keys and request threshold Schnorr signatures via the management canister's `schnorr_public_key` and `sign_with_schnorr` API (using the `ed25519` algorithm variant). This gives each canister its own Solana wallet address, with signing performed collectively by subnet nodes without reconstructing the private key. + +## Chain-key SOL (ckSOL) + +ckSOL is the chain-key token representing SOL on ICP. Like ckETH, it is backed 1:1 by SOL held in a canister-controlled Solana address. The minter canister monitors Solana deposits via the SOL RPC canister and mints ICRC-1/ICRC-2 compliant ckSOL tokens on ICP. Withdrawals follow the same pattern: burn ckSOL, sign a Solana transfer using chain-key Ed25519, and broadcast via the SOL RPC canister. + +### Depositing SOL (SOL to ckSOL) + +```plantuml +actor User +participant "ckSOL Minter" as Minter +participant "ckSOL Ledger" as Ledger +participant "SOL RPC Canister" as SolRpc +participant "Solana" as SOL + +User -> Minter: get_deposit_address(owner, subaccount) +Minter --> User: deposit_address +User -> SOL: transfer SOL to deposit_address +User -> Minter: process_deposit(owner, subaccount, tx_signature) +Minter -> SolRpc: fetch & verify transaction +Minter -> Ledger: mint ckSOL (amount - deposit_fee) +Minter --> User: Minted { block_index, minted_amount } +``` + +### Withdrawing SOL (ckSOL to SOL) + +```plantuml +actor User +participant "ckSOL Minter" as Minter +participant "ckSOL Ledger" as Ledger +participant "Solana" as SOL + +User -> Ledger: icrc2_approve(spender=minter, amount) +User -> Minter: withdraw(sol_address, amount) +Minter -> Ledger: burn via icrc2_transfer_from(user, amount) +Minter --> User: burn_block_index +note right of Minter: processed asynchronously +Minter -> SOL: submit SOL transfer (chain-key Ed25519) +User -> Minter: withdrawal_status(burn_block_index) +Minter --> User: TxFinalized +``` + +## Next steps + +- [Solana guide](../../guides/chain-fusion/solana.md): code examples for interacting with Solana +- [Chain Fusion overview](index.md): integration patterns and supported chains +- [Ethereum integration](ethereum.md): the EVM RPC canister for comparison +- [Chain-key cryptography](../chain-key-cryptography.md): Ed25519 threshold Schnorr signing +- [SOL RPC canister reference](../../references/protocol-canisters.md#sol-rpc-canister): canister ID and provider list +- [Chain-Key Token Canister IDs: ckSOL](../../references/chain-key-canister-ids.md#cksol): ckSOL minter and ledger IDs + + diff --git a/docs/concepts/chain-key-cryptography.md b/docs/concepts/chain-key-cryptography.md index bcc916dd..e47875f0 100644 --- a/docs/concepts/chain-key-cryptography.md +++ b/docs/concepts/chain-key-cryptography.md @@ -1,22 +1,23 @@ --- -title: "Chain-Key Cryptography" -description: "Threshold signatures that enable cross-chain integration, fast verification, and chain evolution" +title: "Chain-key cryptography" +description: "Threshold signatures that enable crosschain integration, fast verification, and chain evolution" sidebar: order: 9 --- -Chain-key cryptography is a set of threshold cryptographic protocols that underpin the Internet Computer. Instead of any single node holding a private key, keys are split into shares distributed across the nodes of a [subnet](network-overview.md). Nodes collaboratively sign messages without ever reconstructing the full key: and this single capability enables everything from fast response verification to canisters signing transactions on Bitcoin, Ethereum, and dozens of other blockchains. +Chain-key cryptography is a set of threshold cryptographic protocols that underpin the Internet Computer. Instead of any single node holding a private key, keys are split into shares distributed across the nodes of a [subnet](network-overview.md). Nodes collaboratively sign messages without ever reconstructing the full key: and this single capability enables everything from fast response verification to canisters signing transactions on Bitcoin, Ethereum, and dozens of other chains. ## Why threshold cryptography matters -On most blockchains, verifying state requires replaying transactions or trusting a full node. On ICP, verifying a response means checking **one signature against one public key**: regardless of how many nodes produced it. This is possible because each subnet holds a threshold BLS key: any sufficiently large subset of nodes can produce a valid signature, but no smaller group can forge one. +On traditional distributed networks, verifying state requires replaying transactions or trusting a full node. On ICP, verifying a response means checking **one signature against one public key**: regardless of how many nodes produced it. This is possible because each subnet holds a threshold BLS key: any sufficiently large subset of nodes can produce a valid signature, but no smaller group can forge one. This design has several consequences for developers: - **Fast verification.** Clients verify subnet responses with a single public key check. There is no need to download block headers or maintain a light client. -- **Certified data.** Canisters can set certified variables that the subnet signs at each block. Query responses that include these certificates are cryptographically authenticated, bridging the gap between fast queries and trusted updates. See [Certified variables](../guides/backends/certified-variables.md). +- **Certified data.** Canisters can set certified variables that the subnet signs at each block. Query responses that include these certificates are cryptographically authenticated, bridging the gap between fast queries and trusted updates. See [Certified data](certified-data.md) for the conceptual explanation and [Certified variables](../guides/backends/certified-variables.md) for the implementation guide. - **Verifiable randomness.** The threshold BLS scheme produces unique signatures: for a given message and key, only one valid signature exists. ICP exploits this property to generate unpredictable, unbiased random numbers that canisters can consume. See [Verifiable randomness](verifiable-randomness.md). -- **Cross-chain signing.** Canisters can request threshold ECDSA and Schnorr signatures, giving them the ability to control addresses and sign transactions on external blockchains. This is the foundation of [Chain Fusion](chain-fusion.md). +- **Crosschain signing.** Canisters can request threshold ECDSA and Schnorr signatures, giving them the ability to control addresses and sign transactions on external chains. This is the foundation of [Chain Fusion](chain-fusion/index.md). +- **Onchain encryption.** VetKeys extend threshold cryptography to enable canisters to derive encryption keys on behalf of users, making onchain encryption practical. See [VetKeys](vetkeys.md). ## Core protocols @@ -24,7 +25,7 @@ Chain-key cryptography is not a single algorithm but a protocol suite. The main ### Distributed key generation (DKG) -Before a subnet can sign anything, its nodes must collectively generate a key whose shares are distributed among them. ICP uses a novel DKG protocol that works over an **asynchronous network** and tolerates up to one-third of nodes being faulty. The same protocol handles **key resharing**: transferring key material to a new set of nodes when subnet membership changes: without ever reconstructing the private key. Resharing also runs periodically within a subnet to defend against adaptive attackers: each resharing invalidates all previously obtained shares, so compromising nodes over time does not help an adversary accumulate enough shares to forge signatures. +Before a subnet can sign anything, its nodes must collectively generate a key whose shares are distributed among them. ICP uses a [novel DKG protocol](https://eprint.iacr.org/2021/339) that works over an **asynchronous network** and tolerates up to one-third of nodes being faulty. The same protocol handles **key resharing**: transferring key material to a new set of nodes when subnet membership changes (for example, during node rotation), without ever reconstructing the private key. Resharing ensures that shares held by removed nodes become useless, so the subnet's signing ability is preserved across membership changes while old shares cannot be exploited. ### Threshold BLS signatures @@ -37,7 +38,7 @@ BLS was chosen for two properties: ### Chain-key signatures (threshold ECDSA and Schnorr) -Chain-key signatures extend threshold cryptography beyond ICP's internal operations. They let canisters hold keys for external signature schemes and sign arbitrary messages, which means canisters can control accounts on other blockchains. +Chain-key signatures extend threshold cryptography beyond ICP's internal operations. They let canisters hold keys for external signature schemes and sign arbitrary messages, which means canisters can control accounts on other chains. Two signature schemes are supported, with the Schnorr API offering two algorithm variants: @@ -54,6 +55,14 @@ Each scheme is backed by a pair of management canister methods: See the [Management canister reference](../references/management-canister.md#chain-key-signing) for the full API, and the [IC interface specification](../references/ic-interface-spec/index.md) for the authoritative protocol-level details. +#### Why threshold ECDSA is harder than threshold BLS + +Threshold signing for BLS is straightforward because BLS signature shares can be combined non-interactively: each node signs independently and the shares are aggregated with no further communication. ECDSA has no such property; producing a threshold ECDSA signature requires a multi-round interactive protocol among the signing nodes. + +Existing threshold ECDSA protocols in academic literature all assume either a synchronous network (messages must arrive within a bounded time) or offer no robustness against node crashes. Neither assumption is acceptable for ICP: security and liveness must hold over an asynchronous network with up to one-third of nodes faulty. ICP implements a novel threshold ECDSA protocol that is both asynchronous and robust, with formal security proofs published in [protocol design](https://eprint.iacr.org/2022/506) and [security analysis](https://eprint.iacr.org/2021/1330) papers. + +Threshold Schnorr (including Ed25519) protocols are simplified variants of the ECDSA signing protocol. They inherit the same asynchronous-network and robustness properties. + ### Key derivation A small number of **master keys** are deployed across the network: one per signature scheme. From each master key, the protocol derives a unique **canister root key** for every canister using the canister's principal as input. From the root key, canisters can derive an unlimited number of child keys by providing a `derivation_path` in API calls. @@ -62,9 +71,9 @@ For ECDSA and BIP340, key derivation uses a generalized form of [BIP-32](https:/ Derivation is transparent: it happens inside the protocol as part of the signing and public-key-retrieval APIs. You provide a derivation path and the protocol handles the rest. -Because the derivation algorithm is deterministic and uses only public parameters (the master public key, the canister principal, and the derivation path), public key derivation can also be performed **offline**: no management canister call or network connection required. This is useful for building explorers, dashboards, or address-derivation tools that need a canister's public key or blockchain address without a live ICP connection. See the [offline key derivation guide](../guides/chain-fusion/offline-key-derivation.md) for TypeScript and Rust libraries. +Because the derivation algorithm is deterministic and uses only public parameters (the master public key, the canister principal, and the derivation path), public key derivation can also be performed **offline**: no management canister call or network connection required. This is useful for building explorers, dashboards, or address-derivation tools that need a canister's public key or network address without a live ICP connection. See the [offline key derivation guide](../guides/chain-fusion/offline-key-derivation.md) for TypeScript and Rust libraries. - + ### Pre-signatures @@ -74,7 +83,7 @@ Under high load, pre-signatures may be temporarily exhausted and signing request ## Deployed keys -The following master keys are deployed at the time of writing. The NNS can add new keys or change subnet assignments via proposals, so consult the [IC dashboard](https://dashboard.internetcomputer.org) for the current state. +The following master keys are deployed at the time of writing. The Network Nervous System (NNS) can add new keys or change subnet assignments via proposals, so consult the [IC dashboard](https://dashboard.internetcomputer.org) for the current state. | Key ID | Scheme | Purpose | Signing subnet | |--------|--------|---------|----------------| @@ -91,7 +100,7 @@ For signing costs, see [Cycles costs](../references/cycles-costs.md). ## Supported chains -Any blockchain whose transaction authentication uses ECDSA (secp256k1) or Schnorr signatures (BIP340 over secp256k1, or Ed25519) can be integrated with ICP through chain-key signatures. For the full list of supported chains with integration methods and chain-key tokens, see [Chain Fusion: Supported chains](chain-fusion.md#supported-chains). +Any chain whose transaction authentication uses ECDSA (secp256k1) or Schnorr signatures (BIP340 over secp256k1, or Ed25519) can be integrated with ICP through chain-key signatures. For the full list of supported chains with integration methods and chain-key tokens, see [Chain Fusion: Supported chains](chain-fusion/index.md#supported-chains). ## Chain evolution @@ -99,13 +108,14 @@ The same threshold cryptographic infrastructure that enables signing also enable Combined with the NNS governance system, this enables **autonomous protocol upgrades**: the NNS approves an upgrade, the orchestrator on each node downloads the new replica software, and the subnet transitions at the next epoch boundary: all while preserving canister state and maintaining the same public key. -For more on how upgrades work at the protocol level, see the [Chain Evolution](https://learn.internetcomputer.org/hc/en-us/articles/34210120121748) article on the Learn Hub. +For more on how upgrades work at the protocol level, see [Chain evolution](evolution-scaling.md#chain-evolution). ## Next steps -- [Chain Fusion](chain-fusion.md): how canisters use chain-key signatures to interact with other blockchains +- [Chain Fusion](chain-fusion/index.md): how canisters use chain-key signatures to interact with other chains +- [Certified data](certified-data.md): how the subnet's threshold BLS key enables certified query responses - [Ethereum integration](../guides/chain-fusion/ethereum.md): using threshold ECDSA with Ethereum and EVM chains - [VetKeys](vetkeys.md): a related cryptographic primitive for onchain encryption - [Management canister reference](../references/management-canister.md): the threshold signing API - + diff --git a/docs/concepts/cycles.md b/docs/concepts/cycles.md index 58aae026..885fbf1c 100644 --- a/docs/concepts/cycles.md +++ b/docs/concepts/cycles.md @@ -61,6 +61,41 @@ When a canister allocates new storage bytes on a subnet that is more than 750 Gi Every canister is replicated across all nodes on its subnet. Costs scale with subnet size: a 34-node subnet charges `34/13` times the base rate compared to a 13-node subnet. Choosing a 13-node subnet minimizes cost; 34-node subnets offer higher replication and security for sensitive workloads. +## How charging works + +Each resource category is metered and charged differently: + +**Memory** is charged at regular intervals (not every consensus round). The protocol tracks total memory in use and deducts from the canister's cycle balance periodically. + +**Computation** is charged at the time the instructions execute. ICP counts the number of WebAssembly instructions processed while handling a message. There is an upper bound on instructions per consensus round. If a message exceeds this limit, execution is paused and resumes in the next round; the cycles consumed each round are charged at round end. This is the mechanism behind deterministic time slicing. + +**Messaging** costs are charged to the sending canister. Ingress messages (user to canister) are charged to the receiving canister. Each inter-canister call has a fixed base cost plus a per-byte variable cost. The calling canister also prepays the maximum-size reply cost upfront; if the actual reply is smaller, the difference is refunded. + +**Special features** (HTTPS outcalls, threshold signatures, Bitcoin API calls) charge the calling canister an additional amount on top of standard messaging costs. These features require extra protocol-level work and are priced accordingly. + +## Cycles ledger + +The **cycles ledger** (`um5iw-rqaaa-aaaaq-qaaba-cai`) is an NNS-controlled canister on the uzr34 system subnet that provides a shared cycles balance for principals. It complies with the ICRC-1, ICRC-2, and ICRC-3 standards, so cycles can be transferred, approved, and spent using the same interfaces as any other token. An accompanying index canister (`ul4oc-4iaaa-aaaaq-qaabq-cai`) runs on the same subnet. + +The cycles ledger replaces the old cycles wallet model: instead of each developer deploying and managing their own cycles wallet canister, everyone shares the same ledger. Cycles are credited to a principal ID and subaccount just like any ICRC token. + +![Cycles ledger architecture: the ledger interacts with the CMC and user canisters to provide deposit, withdraw, and canister creation](/concepts/cycles/cycles-ledger-architecture.png) + +Key operations: + +- **`deposit`**: credits attached cycles to a given account (principal + optional subaccount). Minimum 100M cycles must be attached; the 100M cycle fee is deducted. +- **`withdraw`**: sends cycles to a canister. The cycles are removed from the sender's ledger balance. +- **`withdraw_from`**: same as `withdraw`, but uses an ICRC-2 approval to draw from a different account. +- **`create_canister`**: creates a new canister funded from the caller's cycles ledger balance. Delegates to the CMC, which handles subnet placement. +- **`create_canister_from`**: same as `create_canister`, but uses an ICRC-2 approval to draw funds from a different account. + +Every state-changing operation (each block created) costs 100M cycles as a fee. The full interface specification is available in the [cycles ledger reference](../references/system-canisters.md#cycles-ledger). + +The cycles ledger does not support calling arbitrary canisters with cycles attached, because open call contexts can cause the ledger to become stuck. Two patterns address this: + +- **Top up the target canister first**: if you control the canister, transfer cycles to it using `withdraw` or `icp canister top-up`, then let the canister attach cycles internally from its own balance. This is the preferred pattern for canisters you deploy and control. +- **Proxy canister**: if you need to call a canister method with cycles attached from the CLI or an external agent, deploy a proxy canister using the [`proxy` template](https://github.com/dfinity/icp-cli-templates/tree/main/proxy) and route the call through it. See [Calling canisters that require cycles](../guides/canister-management/cycles-management.md#calling-canisters-that-require-cycles) for the how-to. + ## Developer responsibility **Topping up**: canisters burn cycles continuously for storage and on every update call. Developers must monitor balances and keep canisters funded. A canister that runs out of cycles freezes immediately and stops responding to all calls. @@ -83,7 +118,9 @@ The tradeoff is that developers must forecast and fund usage upfront rather than ## Related - [Cycles Management](../guides/canister-management/cycles-management.md): how to check balances, top up canisters, and set freezing thresholds +- [Calling canisters that require cycles](../guides/canister-management/cycles-management.md#calling-canisters-that-require-cycles): proxy canister pattern for attaching cycles from the CLI +- [Cycles ledger reference](../references/system-canisters.md#cycles-ledger): canister IDs, interface specification, and CMC integration - [Cycles Costs Reference](../references/cycles-costs.md): exact cost tables for all operations - [Canisters](./canisters.md): canisters as the paying entity for compute and storage - + diff --git a/docs/concepts/edge-infrastructure.md b/docs/concepts/edge-infrastructure.md new file mode 100644 index 00000000..41478a88 --- /dev/null +++ b/docs/concepts/edge-infrastructure.md @@ -0,0 +1,75 @@ +--- +title: "Edge infrastructure" +description: "How requests reach ICP canisters: API boundary nodes, HTTP gateways, the HTTP Gateway Protocol, and asset certification." +--- + +The Internet Computer extends the internet beyond connecting devices and networks: it runs applications in a tamperproof manner. For a browser or an API client to interact with a canister, requests must travel through the ICP edge infrastructure, which translates standard HTTP into ICP's canister call protocol, routes calls to the right subnet, and certifies responses before they reach the client. + +The edge infrastructure has two main components: + +- **API boundary nodes** handle IC API requests (query and update calls) and route them to the correct subnet. +- **HTTP gateways** translate standard HTTP requests from browsers and other clients into IC API calls and translate responses back into HTTP. + +![ICP edge infrastructure: browsers connect through HTTP gateways and API boundary nodes to subnet replicas](/concepts/edge-infrastructure/edge-infrastructure.png) + +## API boundary nodes + +API boundary nodes are the globally distributed public interface of the Internet Computer. They receive IC API requests and route them to nodes on the appropriate subnet, providing seamless access to canisters without relying on centralized infrastructure. + +Beyond routing, API boundary nodes perform several additional functions: + +- **Dynamic routing.** They continuously monitor the network topology and adapt routing accordingly as subnets are added, removed, or reconfigured. +- **Load balancing.** Traffic is distributed across replica nodes to optimize performance. +- **Caching.** Some query responses are cached to reduce latency for frequently accessed data. +- **Security enforcement.** API boundary nodes implement safeguards that protect both themselves and the core protocol from abuse. + +API boundary nodes are an integral part of the network, governed by the Network Nervous System (NNS). Any addition, removal, or upgrade of API boundary nodes requires an NNS proposal, ensuring transparency. They run on hardware owned by independent node providers, similar to replica nodes. + +All API boundary nodes run a service called `ic-boundary`. The network uses a single VM image for both replica and API boundary nodes: the orchestrator component on each node determines its role by launching either `ic-replica` or `ic-boundary`. + +Around 20 API boundary nodes are currently deployed worldwide. An up-to-date list is available on the [IC dashboard](https://dashboard.internetcomputer.org/nodes?s=100&type=ApiBoundary). + +## HTTP gateways + +HTTP gateways translate standard HTTP requests into IC API calls and forward them to API boundary nodes. Because of this translation layer, browsers and other HTTP clients can access canisters directly without installing any special software. For example, a website fully hosted on ICP is accessible in any browser through a normal HTTPS URL. + +The HTTP Gateway Protocol (defined in the [HTTP Gateway Protocol Specification](../references/http-gateway-spec.md)) specifies exactly how this translation works. HTTP gateways are not part of ICP itself and can be operated by anyone. This open model encourages a diverse set of gateways, enhancing redundancy and availability. + +## HTTP Gateway Protocol + +When a browser opens a URL hosted by a canister, the following happens: + +1. The browser makes a normal HTTPS request to the domain (for example, `https://.icp0.io`). It has no awareness that the site runs on ICP. +2. The HTTP gateway receives the request and translates it into a query call to the canister's `http_request` method, placing the path, headers, and body into the call payload. +3. An API boundary node receives the IC API call and forwards it to a replica on the subnet that hosts the target canister. +4. The canister executes the `http_request` query, constructs an HTTP response (status, headers, body), and returns it. +5. The HTTP gateway receives the canister's response, verifies the certificate (see Asset certification below), and constructs a standard HTTP response. +6. The browser receives the HTTP response and renders the page. + +Canisters that serve HTTP must implement the Canister HTTP Interface defined in the HTTP Gateway Protocol Specification. The main implementation of the protocol is the [ic-http-gateway library](https://github.com/dfinity/ic-http-gateway-protocol/tree/main/packages/ic-http-gateway-protocol). + +## Asset certification + +When a canister responds to a query call via the HTTP gateway, a single replica node handles the request. The client cannot rely solely on that node's response, since a compromised node could return tampered content. + +ICP solves this through **asset certification**: a mechanism for canisters to prove in advance that a response is genuine. It works as follows: + +- The ICP network maintains a public key at the network level. Each subnet also has its own public key, which is certified by the NNS using the network key. +- When a subnet responds to a message, the response includes a certificate chain: the subnet's signature on the response and the NNS certificate on the subnet's key. Any client can verify this chain using only the ICP network's public key. +- Because generating a subnet certificate requires agreement from at least two thirds of the subnet's nodes (using [chain-key cryptography](chain-key-cryptography.md#threshold-bls-signatures)), a certified response represents network-level consensus, not a single node's assertion. +- Query calls do not go through consensus and are not automatically certified. To serve certified query responses, canisters use **certified variables**: the canister stores a certificate for a piece of data in the replicated state during an update call. Any user can later retrieve both the data and its certificate via a query call and verify the certificate independently. +- For web assets (HTML, CSS, JavaScript, images), canisters can certify all assets upfront. The asset canister provided by DFINITY handles this automatically: developers specify a folder of assets and the asset canister manages and certifies them. + +When the HTTP gateway receives a canister response that includes a certificate, it verifies the certificate before passing the response to the client. This is what makes ICP-hosted web content verifiable end-to-end without trusting any single node. + +For practical guidance on certifying canister responses, see [Certified variables](../guides/backends/certified-variables.md). + +## Further reading + +- [HTTP Gateway Protocol Specification](../references/http-gateway-spec.md): detailed protocol definition +- [ic-http-gateway library](https://github.com/dfinity/ic-http-gateway-protocol/tree/main/packages/ic-http-gateway-protocol): the main implementation of the HTTP Gateway Protocol +- [response-verification](https://github.com/dfinity/response-verification): libraries for certifying canister responses to work with the HTTP gateway protocol +- [Certified variables guide](../guides/backends/certified-variables.md): how to certify canister responses +- [Chain-key cryptography](chain-key-cryptography.md): the signature mechanism underlying certification + + diff --git a/docs/concepts/evolution-scaling.md b/docs/concepts/evolution-scaling.md new file mode 100644 index 00000000..c8e39a54 --- /dev/null +++ b/docs/concepts/evolution-scaling.md @@ -0,0 +1,110 @@ +--- +title: "Evolution & scaling" +description: "How ICP scales horizontally through subnet creation, maintains liveness under node failures, and upgrades its protocol without forks." +--- + +The Internet Computer is designed to adapt to changing demands. When more resources are needed, new subnets can be added, expanding capacity horizontally. When nodes fail, the protocol continues making progress and recovers automatically. When the protocol itself needs to improve, upgrades roll out without forks and with minimal downtime. All of this happens under governance by the Network Nervous System (NNS). + +## Fault tolerance + +In any large-scale distributed system, individual nodes will fail due to hardware outages, network issues, or attacks. ICP is fault-tolerant: the protocol continues making progress as long as fewer than one third of the nodes in a subnet are faulty (including Byzantine failures, where nodes behave arbitrarily rather than simply going offline). + +When a node fails, the subnet continues producing blocks. The failed node can recover automatically using the state synchronization protocol. The consensus protocol is divided into epochs, each comprising several hundred consensus rounds. At the start of each epoch, all nodes create a checkpoint and a catch-up package (CUP). A CUP contains the replicated state hash and enough context for any node to resume consensus from that point. The CUP is signed by at least two thirds of the subnet's nodes. + +When a failed or newly joined node comes back online, it: + +1. Listens for CUP messages from peers. +2. Validates the CUP (verifying the threshold signature). +3. If the CUP's state hash differs from its local state, initiates state sync to download the checkpoint. +4. After syncing the checkpoint, replays the blocks produced since that CUP. +5. Rejoins consensus normally. + +If a node consistently lags behind or fails repeatedly, an NNS proposal can be submitted to replace it with a spare node. + +### Subnet recovery + +In rare cases an entire subnet can get stuck: for example, if more than one third of its nodes fail simultaneously, or if a software bug causes non-deterministic execution. In this case, the nodes cannot collectively produce a valid CUP, so automatic recovery is not possible. + +Recovery requires community action: a recovery coordinator manually creates a CUP at the highest certified block height, then submits an NNS proposal containing it. If the community approves, the NNS stores the CUP in its registry. Each node's orchestrator process detects the new CUP and restarts the replica using it, resuming from the certified state. + +This governance-gated recovery process applies to regular subnets. The NNS subnet itself requires coordinated action by all NNS node providers to restart manually. + +### NNS canister failures + +The NNS is itself a set of canisters: root, governance, ledger, registry, and others. If one of these canisters fails due to a software bug, it can be upgraded by submitting an NNS proposal. + +Each NNS canister has a controller that can upgrade it. The lifeline canister controls the root canister; the root canister controls all other NNS canisters. To upgrade a failed NNS canister, a proposal is submitted to call the root or lifeline canister's upgrade method. If the governance canister is still functioning, this proposal follows the normal voting process. If the majority of voters approve, the failed canister is upgraded with new WebAssembly code. + +For details on the NNS canister hierarchy, see [System canisters](../references/system-canisters.md). + +### NNS subnet failures + +In the worst case, the subnet hosting the NNS canisters itself can fail. Because NNS governance is unavailable, the normal recovery process cannot be used. Instead, all node providers who contributed a node to the NNS subnet must manually coordinate: each provider creates a CUP and restarts their node using it. + +## Subnet creation + +ICP scales horizontally by creating new subnets. Each subnet hosts thousands of canisters and processes messages independently. Adding a subnet adds proportional capacity to the network: more canisters, more storage, more throughput. + +![ICP nodes divided into subnets, each running an independent consensus protocol](/concepts/evolution-scaling/add-new-subnet.webp) + +Subnets on the Internet Computer communicate using cross-subnet (XNet) messaging. A canister on any subnet can send asynchronous messages to any canister on any other subnet. XNet messages are included in the receiving subnet's consensus blocks and authenticated using [chain-key cryptography](chain-key-cryptography.md). This loosely coupled architecture means newly created subnets can immediately exchange messages with all existing subnets, without a central bottleneck. + +### How a new subnet is created + +![NNS proposal to create a new subnet](/concepts/evolution-scaling/new-subnet-proposal.webp) + +1. **Onboard nodes.** New nodes must be onboarded to the network first. A node provider installs IC-OS, and the node's orchestrator registers with the NNS. The node is then available as a spare. + +2. **Submit a proposal.** Anyone can submit an NNS proposal specifying which spare nodes should form the new subnet. The proposal includes the subnet configuration: the node list, protocol version, and other parameters. + +3. **Community vote.** Anyone who has staked ICP can vote on the proposal. If a majority approve, the NNS registry canister records the new subnet configuration and instructs the NNS subnet to generate the initial cryptographic key material for the subnet using chain-key cryptography. + +4. **Subnet genesis.** Each selected node's orchestrator sees the new subnet record in the registry, downloads the correct replica software, and starts the replica with the genesis catch-up package. The nodes form the subnet and begin accepting messages. + +## Chain evolution + +ICP upgrades its protocol approximately once per week, driven by NNS governance. These upgrades can change anything: fix bugs, add features, update algorithms, or alter the underlying technology. They are applied without forks and with minimal downtime, and the full state of all canisters is preserved across upgrades. + +### How protocol upgrades work + +The NNS registry stores the complete configuration of the Internet Computer, including the replica version each subnet should run. A version change in the registry triggers the upgrade process. + +![The NNS registry implements versioning: each configuration change creates a new version](/concepts/evolution-scaling/registry-versions.webp) + +Upgrades roll out on a per-subnet basis. Within a subnet, all nodes must switch to the new protocol version simultaneously to avoid a fork. This coordination is achieved using epochs: + +- The consensus protocol divides time into epochs, each several hundred rounds long. +- The first block of each epoch is a summary block containing the configuration (including replica version and cryptographic key material) for both the current epoch and the next one. Nodes therefore know the upcoming version from the start of the current epoch, not at the last moment. +- If the registry indicates a new replica version for the upcoming epoch, all nodes download it in advance. + +![Protocol upgrade happens at epoch boundaries; all nodes switch simultaneously](/concepts/evolution-scaling/protocol-transition.webp) + +- At the epoch boundary, the nodes stop processing update calls and produce empty blocks until the summary block is finalized, executed, and the state is certified. Query calls continue normally during this pause. +- All nodes produce a CUP containing the state needed to resume at the new version, signed by more than two thirds of the subnet. +- Each node's orchestrator receives the CUP and starts the new replica software with it as input. + +![The catch-up package (CUP) is handed over to the new replica version](/concepts/evolution-scaling/handing-cup.webp) + +- The new replica resumes consensus immediately from the handed-off state. + +Blocks and consensus artifacts are tagged with the protocol version that produced them. A replica only processes artifacts from its own version, except CUPs (which must be readable by both the pre-upgrade and post-upgrade replica). + +The registry records the desired configuration, not the current running version. A subnet may continue running an older version until the CUP handoff completes. Nodes determine the actual current version by querying peers for the highest valid CUP. + +### Upgrade governance + +![NNS proposal to upgrade a subnet to a new replica version](/concepts/evolution-scaling/upgrade-proposal.webp) + +To trigger a protocol upgrade, anyone submits an NNS proposal to update the registry with a new replica version. ICP token holders who have staked their tokens can vote. If a majority approves, the registry is updated and the upgrade rolls out automatically. No hard fork or manual intervention is needed. + +## Further reading + +- [Chain-key cryptography](chain-key-cryptography.md): the key management underlying subnet creation and XNet messaging +- [System canisters](../references/system-canisters.md): the NNS canister hierarchy, including root, governance, ledger, registry, and lifeline +- [Upgrading the Internet Computer Protocol](https://medium.com/dfinity/upgrading-the-internet-computer-protocol-45bf6424b268): blog post on protocol upgrade design +- [ICP whitepaper, Section 8](https://internetcomputer.org/whitepaper.pdf): technical details on CUP handoff and protocol upgrades +- [Video: Core protocol upgrades (10 min)](https://www.youtube.com/watch?v=mPjiO2bk2lI) +- [Video: State synchronization (20 min)](https://www.youtube.com/watch?v=WaNJINjGleg) +- [Video: Resumption (12 min)](https://www.youtube.com/watch?v=H7HCqonSMFU) + + diff --git a/docs/concepts/governance.md b/docs/concepts/governance.md index ad36b191..9875c4e2 100644 --- a/docs/concepts/governance.md +++ b/docs/concepts/governance.md @@ -1,13 +1,13 @@ --- title: "Governance" -description: "How ICP is governed: the NNS, SNS for app governance, neurons, proposals, and tokenomics fundamentals" +description: "How ICP is governed: the NNS, SNS for app governance, neurons, proposals, and economics fundamentals" sidebar: - order: 13 + order: 14 --- -The Internet Computer Protocol uses two governance systems: the **Network Nervous System (NNS)** governs the protocol itself, and the **Service Nervous System (SNS)** provides a framework for app developers to hand control of their applications to a community-owned DAO. +The Internet Computer Protocol uses two governance systems: the **Network Nervous System (NNS)** governs the protocol itself, and the **Service Nervous System (SNS)** provides a framework for app developers to hand control of their applications to a community-governed SNS. -Understanding both systems is important for developers. NNS proposals can affect canister behavior (for example, proposals that update system canisters or modify subnet configurations). SNS gives developers a standardized path to decentralize their app. +Understanding both systems is important for developers. NNS proposals can affect canister behavior (for example, proposals that update system canisters or modify subnet configurations). SNS gives developers a standardized path to transfer control of their app to a community: once launched, no upgrade or configuration change can happen without a governance proposal voted on by asset holders, so no single party can make unilateral changes. ## The Network Nervous System @@ -19,13 +19,13 @@ Decisions made through the NNS include: - Creating and managing subnets (adding capacity, changing subnet membership) - Setting economic parameters such as the ICP-to-cycles conversion rate - Authorizing new node providers and their hardware -- Creating new SNS DAOs for apps +- Creating new SNS instances for apps -The NNS governance canister (`rrkah-fqaaa-aaaaa-aaaaq-cai`) is the entry point for all proposal submissions and voting. See [system canisters](../references/system-canisters.md) for the full list of NNS canister IDs. +The NNS governance canister (`rrkah-fqaaa-aaaaa-aaaaq-cai`) is the entry point for all proposal submissions and voting. See [system canisters](../references/system-canisters.md) for the full list of NNS-controlled canisters and their IDs. -## ICP tokens and the ledger +## ICP and the ledger -ICP is the native utility token of the Internet Computer. It plays three roles: +ICP is the native digital asset of the Internet Computer. It plays three roles: - **Governance participation**: ICP can be locked into neurons to vote on proposals and earn voting rewards. - **Compute fuel**: ICP can be converted into cycles, which power canister computation and storage. The NNS sets the ICP-to-cycles conversion rate to keep cycle costs stable in fiat terms (anchored to the IMF SDR). @@ -35,20 +35,20 @@ The ICP ledger, hosted within the NNS, records all ICP balances. Each account ha ## Neurons -A neuron is a governance participant created by locking ICP tokens in the NNS governance canister. Neurons are the atomic units of voting power. +A neuron is a governance participant created by locking ICP in the NNS governance canister. Neurons are the atomic units of voting power. **Key neuron attributes:** -- **Stake**: The amount of ICP locked. Minimum stake to submit proposals is 10 ICP with at least 6 months of dissolve delay. +- **Stake**: The amount of ICP locked. The minimum to create a neuron is 1 ICP. To submit or vote on proposals, a neuron needs at least 6 months of dissolve delay. - **Dissolve delay**: A waiting period (up to 8 years) that must expire before locked ICP can be retrieved. Longer dissolve delay grants more voting power. - **Age**: How long the neuron has been non-dissolving. Older neurons earn an age bonus on voting power. - **State**: A neuron is either locked (non-dissolving), dissolving, or dissolved (ready to disburse). -**Voting power formula:** A neuron's voting power scales with its stake, dissolve delay bonus (up to 2x at 8 years), and age bonus (up to 1.25x at 4 years). This design incentivizes long-term alignment with the network. +**Voting power formula:** A neuron's voting power scales with its stake, dissolve delay bonus (up to 2x at 8 years), and age bonus (up to 1.25x at 4 years). This design incentivizes long-term alignment with the network. **Liquid democracy (following):** Neurons can delegate their votes to other neurons on specific proposal topics. A neuron that doesn't vote directly inherits the vote of its followed neurons. This allows passive participation while still counting toward quorum. -**Known neurons** are named neurons registered in the NNS governance canister through a proposal. They act as trusted delegates that other neurons follow. Any neuron that meets the general proposal prerequisite (at least 10 ICP staked with 6 months dissolve delay) and has at least 25 ICP staked can submit a `RegisterKnownNeuron` proposal. +**Known neurons** are named neurons registered in the NNS governance canister through a proposal. They act as trusted delegates that other neurons follow. Any neuron with at least 6 months of dissolve delay and at least 25 ICP staked can submit a `RegisterKnownNeuron` proposal. ## Proposals @@ -68,9 +68,9 @@ An NNS proposal is a governance action submitted by a neuron and voted on by the - *UpgradeNnsCanister* and *UpgradeRootCanister*: Update protocol canisters. May change interfaces developers rely on. - *CreateSubnet* / *AddNodeToSubnet*: Affect where canisters run. - *UpdateCanisterSettings* for NNS canisters: Can change the behavior of system canisters. -- *CreateServiceNervousSystem*: Authorizes a new SNS DAO, launching the decentralization process for an app. +- *CreateServiceNervousSystem*: Authorizes a new SNS, launching the decentralization process for an app. -See [system canisters](../references/system-canisters.md) for the full list of NNS proposal topics and types. +See [NNS proposal types](../references/nns-proposal-types.md) for the full list of NNS proposal topics and their descriptions. ## Voting rewards @@ -78,42 +78,42 @@ Neurons that vote (directly or through following) earn voting rewards. The proto Rewards accumulate as **maturity** rather than ICP directly. Neurons can convert maturity to ICP (with a modulation of ±5% applied to the mint amount) or merge maturity back into their stake to compound future rewards. -The reward rate declines over time as the protocol matures, converging toward a lower floor rate over roughly a decade. See the [ICP tokenomics overview](https://learn.internetcomputer.org/hc/en-us/articles/34090810571284) for details on the reward rate schedule. +The reward rate declines over time as the protocol matures, converging toward a lower floor rate over roughly a decade. See [Network economics](network-economics.md) for details on the reward rate schedule and supply dynamics. ## The Service Nervous System -The SNS is a governance framework that allows app developers to create a community-owned DAO for their application. When an app is governed by an SNS, token holders vote on proposals to upgrade the app's canisters, manage treasury funds, and adjust governance parameters. +The SNS is a governance framework that allows app developers to create a community-governed SNS for their application. When an app is governed by an SNS, asset holders vote on proposals to upgrade the app's canisters, manage treasury funds, and adjust governance parameters. Unlike the NNS, which is a singleton governing the entire protocol, each SNS is a separate set of canisters specific to one app. SNSes live on a dedicated SNS subnet. ### SNS canisters -An SNS consists of six canisters deployed by SNS-W (the SNS Wasm modules canister, `qaa6y-5yaaa-aaaaa-aaafa-cai`): +An SNS consists of five core canisters plus a variable number of archive canisters, all deployed by SNS-W (the SNS Wasm modules canister, `qaa6y-5yaaa-aaaaa-aaafa-cai`): | Canister | Purpose | |----------|---------| | **Governance** | Proposal submission, voting, neuron management | -| **Ledger** | SNS token transfers (ICRC-1 standard) | +| **Ledger** | SNS asset transfers (ICRC-1 standard) | | **Root** | Sole controller of all app canisters post-launch | -| **Swap** | Runs the decentralization swap (ICP for SNS tokens) | +| **Swap** | Runs the decentralization swap (ICP for SNS assets) | | **Index** | Transaction indexing for the SNS ledger | -| **Archive** | Historical transaction storage | +| **Archive** (one or more, spawned as needed) | Historical ledger block storage; new archive canisters are created automatically as the ledger grows | -Once an SNS is live, the SNS Root canister is the sole controller of the app's canisters. Upgrades happen through governance proposals voted on by SNS token holders. +Once an SNS is live, the SNS Root canister is the sole controller of the app's canisters. Upgrades happen through governance proposals voted on by SNS asset holders. -### Token economics +### Initial asset allocation -Each SNS has its own governance token. The initial token distribution is defined in the SNS configuration file and includes: +Each SNS has its own governance digital asset. The initial distribution is defined in the SNS configuration file and includes: -- **Developer neurons**: Tokens allocated to the original developers and seed funders, typically with vesting periods and dissolve delays to signal long-term commitment. -- **Treasury**: Tokens owned by the SNS governance canister, spendable by DAO proposal. -- **Swap allocation**: Tokens sold during the decentralization swap in exchange for ICP. +- **Developer neurons**: Assets allocated to the original developers and seed funders, typically with vesting periods and dissolve delays to signal long-term commitment. +- **Treasury**: Assets owned by the SNS governance canister, spendable by governance proposal. +- **Swap allocation**: Assets sold during the decentralization swap in exchange for ICP. -The SNS ledger implements the ICRC-1 token standard. SNS neurons work similarly to NNS neurons: stake governs voting power, dissolve delay grants a bonus (up to 2x at the configured maximum), and age grants an additional bonus. +The SNS ledger implements the ICRC-1 standard. SNS neurons work similarly to NNS neurons: stake governs voting power, dissolve delay grants a bonus (up to 2x at the configured maximum), and age grants an additional bonus. ### The decentralization swap -The decentralization swap is the mechanism by which SNS tokens are distributed to the public. Participants send ICP to the SNS Swap canister during the swap window; when the swap closes, the exchange rate is determined and participants receive SNS tokens in a basket of neurons with vesting schedules. +The decentralization swap is the mechanism by which SNS assets are distributed to the public. Participants send ICP to the SNS Swap canister during the swap window; when the swap closes, the exchange rate is determined and participants receive SNS assets in a basket of neurons with vesting schedules. The swap has minimum and maximum ICP participation thresholds. If the minimum is not reached, the swap fails: all ICP is refunded and control of the app returns to the original developers (via the fallback controllers defined in the configuration). If the maximum is reached before the end time, the swap closes early. @@ -126,7 +126,7 @@ SNS governance mirrors the NNS design but is customized per app: | Aspect | NNS | SNS | |--------|-----|-----| | What it governs | Protocol and network | A specific app | -| Token | ICP | Project-specific ICRC-1 token | +| Digital asset | ICP | Project-specific ICRC-1 asset | | Governance canisters | Singleton on NNS subnet | Per-app on SNS subnet | | Launch authority | N/A (pre-existing) | NNS must approve creation | | Proposal types | Protocol updates, subnet management, economics | App upgrades, treasury transfers, parameter changes | @@ -136,17 +136,81 @@ SNS governance mirrors the NNS design but is customized per app: When an app is governed by an SNS, the original developers no longer have direct control. Key implications: - **Upgrades require proposals**: All changes to app canisters must go through SNS governance votes. Development slows down compared to centralized control. -- **Treasury spending requires votes**: Any use of DAO funds requires a governance proposal. +- **Treasury spending requires votes**: Any use of SNS treasury funds requires a governance proposal. - **Upgrade path is transparent**: Community members can verify new canister wasm modules before voting. Reproducible builds allow independent verification. -- **Responsibility is distributed**: Post-launch, the development team typically continues leading the project but must engage the token-holding community for major decisions. -- **Custom proposals**: Apps can register custom proposal types (generic functions) that allow the DAO to call specific canister methods, enabling fine-grained governance without unrestricted code upgrades. +- **Responsibility is distributed**: Post-launch, the development team typically continues leading the project but must engage the community of asset holders for major decisions. +- **Custom proposals**: Apps can register custom proposal types (generic functions) that allow the SNS to call specific canister methods, enabling fine-grained governance without unrestricted code upgrades. -Developers preparing for an SNS launch should ensure their codebase is stable, open-sourced, and reproducibly buildable before the decentralization swap. The NNS community votes on the creation proposal and expects evidence of product-market fit, sound tokenomics, and a realistic roadmap. +Developers preparing for an SNS launch should ensure their codebase is stable, open-sourced, and reproducibly buildable before the decentralization swap. The NNS community votes on the creation proposal and expects evidence of product-market fit, sound asset economics, and a realistic roadmap. + +## Neuron hotkeys + +A neuron's **controller** is the principal with full authority over the neuron. A controller can perform any operation: increase dissolve delay, start or stop dissolving, disburse the stake, and more. Because the private key of the controller principal must be kept highly secure (typically in cold storage), neurons can also have **hotkeys**: additional principals with a limited permission set. + +Hotkeys can: +- Vote on proposals (directly or by confirming following). +- Set or change following rules. +- Submit proposals. +- Read all neuron fields, including non-public information. + +Hotkeys cannot modify the stake, change the dissolve delay, or disburse the neuron. Up to 15 hotkeys are allowed per neuron. A common pattern is to set a hardware wallet as the controller and use a software wallet as a hotkey for day-to-day voting. + +## Following rules in detail + +When a neuron follows a group of other neurons on a topic, it casts its vote once a threshold in the followee group is reached: + +- It votes **adopt** if more than half of the followees vote yes. +- It votes **reject** if at least half of the followees vote no. +- It casts no vote if neither threshold is met. + +A neuron can follow at most 15 neurons per topic. A **catch-all** following rule covers topics with no explicit setting, but does not apply to the *SNS & Community Fund* and *Governance* topics, which must be explicitly configured. + +**Periodic confirmation:** A neuron that never votes directly, sets following, or confirms following must do one of those actions at least once every 6 months. If it fails to do so, voting power is linearly reduced over the following month until it reaches zero, and all following settings are reset. This prevents inactive neurons from accumulating rewards without genuine participation. + +## Voting thresholds and proposal decision + +NNS proposals can be decided two ways: + +- **Absolute majority (at any time):** If more than half of the total voting power recorded at proposal creation votes yes, the proposal is immediately adopted. Likewise, a no absolute majority immediately rejects it. +- **Simple majority at deadline:** When the voting period ends (4 to 8 days, depending on wait-for-quiet), the proposal passes if the yes vote constitutes both a simple majority of cast votes and at least 3% of the total voting power. If the 3% quorum is not met, the proposal is rejected even if a majority of participants voted yes. + +The 3% quorum prevents low-turnout proposals from passing on a handful of votes. + +## Maturity operations + +Maturity accumulated from voting rewards is not transferable and is not immediately liquid. Neuron holders have three options: + +- **Disburse (previously: spawn):** Start a 7-day process that burns the maturity and mints new ICP. The exact amount is subject to maturity modulation: the mint multiplier is computed from 30-day moving averages of the ICP/XDR conversion rate over the preceding 4 weeks, bounded to ±5%. This introduces a small amount of uncertainty (the maturity modulation can move ±1.25% from one week to the next) that discourages timing the market. +- **Stake maturity:** Add maturity to the neuron's staked balance, increasing its voting power immediately. Staked maturity is locked alongside the ICP stake and converts back to unstaked maturity when the neuron dissolves. +- **Auto-stake maturity:** Automatically stake all new maturity as it accrues, compounding voting power without manual intervention. + +## Voting rewards formula + +The NNS distributes rewards daily from a reward pool. The annualized pool size as a percentage of total ICP supply follows this schedule: + +- For years 0–8 after genesis: `R(t) = 5% + 5% × [(G + 8y − t) / 8y]²` +- After year 8: `R(t) = 5%` + +where G is the genesis timestamp and t is the current time. This quadratic decline starts at approximately 10% in year 1 and converges to 5%. The daily pool is `total_supply × R(t) / 365.25`. + +Each neuron receives a share of the pool proportional to its voting power multiplied by the fraction of eligible proposals it voted on (weighted by the reward weight of each proposal topic). If no proposals settle on a given day, rewards roll over to the next distribution. + +## The Neurons' Fund + +The Neurons' Fund (NF) is a mechanism that allows NNS neurons to allocate maturity toward the decentralization swaps of new SNS instances. Participation is opt-in: a neuron holder can join or leave the NF at any time. + +When an SNS swap runs, NF contributions scale with direct participation through a matching function. NF neurons receive SNS neurons in return, with the same hotkeys copied so that holders can vote in the new SNS governance without exposing their cold-storage keys. + +**Note:** The Neurons' Fund was temporarily disabled by [NNS proposal 135970](https://dashboard.internetcomputer.org/proposal/135970). The design described above reflects the intended behavior when it is re-enabled; details may change. ## Next steps - [Launch an SNS](../guides/governance/launching.md): step-by-step guide to decentralizing your app - [Manage a live SNS](../guides/governance/managing.md): proposals, upgrades, and treasury management after launch -- [System canisters reference](../references/system-canisters.md): NNS canister IDs and interfaces +- [SNS framework](sns-framework.md): detailed architecture, neurons, proposals, and reward scheme +- [NNS proposal types reference](../references/nns-proposal-types.md): all proposal topics and types +- [System canisters reference](../references/system-canisters.md): NNS-controlled canisters, their IDs, and interfaces +- [IC Dashboard SNS API](../references/ic-dashboard-api.md#sns-api): query SNS governance data, neuron details, and proposal history programmatically +- [IC Dashboard IC API](../references/ic-dashboard-api.md#ic-api): query NNS proposal data, neuron metrics, and governance statistics - + diff --git a/docs/concepts/https-outcalls.md b/docs/concepts/https-outcalls.md index e34c663a..94324524 100644 --- a/docs/concepts/https-outcalls.md +++ b/docs/concepts/https-outcalls.md @@ -1,5 +1,5 @@ --- -title: "HTTPS Outcalls" +title: "HTTPS outcalls" description: "How canisters call external APIs and web services directly, without oracles or intermediaries." sidebar: order: 8 @@ -86,7 +86,7 @@ For exact pricing formulas, see the [cycles costs reference](../references/cycle - **No streaming or WebSocket.** Outcalls are single request-response pairs. Long-lived connections are not supported. - **~30-second timeout.** If the external server doesn't respond in time, the call fails. - **Rate limiting.** All canisters on a subnet share the same IPv6 prefixes. If many canisters on the same subnet call the same server, they share its rate limit quota. Using API keys with per-key quotas mitigates this. -- **Shared API keys are visible to all replicas.** An API key stored in canister state is readable by every replica. A compromised replica could use the key to make entirely different, unauthorized requests to the external service: not just replay the canister's intended request. [TEE-enabled subnets](https://learn.internetcomputer.org/hc/en-us/articles/46124920595988-Trusted-Execution-Environments) mitigate this by running replicas in hardware-enforced enclaves, preventing node operators from reading canister memory. Consider deploying canisters that store sensitive credentials on a TEE-enabled subnet. +- **Shared API keys are visible to all replicas.** An API key stored in canister state is readable by every replica. A compromised replica could use the key to make entirely different, unauthorized requests to the external service: not just replay the canister's intended request. [TEE-enabled subnets](node-infrastructure.md#trusted-execution-environments) mitigate this by running replicas in hardware-enforced enclaves, preventing node operators from reading canister memory. Consider deploying canisters that store sensitive credentials on a TEE-enabled subnet. ## HTTPS outcalls vs. oracles @@ -111,6 +111,4 @@ One extension is under consideration that may affect architecture decisions: - [HTTPS outcalls guide](../guides/backends/https-outcalls.md): practical how-to with code examples in Motoko and Rust - [Chain Fusion: Ethereum integration](../guides/chain-fusion/ethereum.md): uses HTTPS outcalls via the EVM RPC canister - [Cycles costs reference](../references/cycles-costs.md): detailed pricing formulas -- [Learn Hub: HTTPS Outcalls](https://learn.internetcomputer.org/hc/en-us/articles/34211194553492): additional learning material - diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 8944cc1c..8b1977a8 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -7,27 +7,54 @@ sidebar: Understand the ideas behind the Internet Computer before you build on it. These explanations cover architecture, capabilities, and design decisions that shape how you write ICP applications. -## Architecture +## Network -- **[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. +- **[Overview](network-overview.md)**: Subnets, nodes, consensus, and boundary nodes. +- **[Node infrastructure](node-infrastructure.md)**: How ICP nodes are structured: IC-OS, virtual machine isolation, and Trusted Execution Environments. +- **[Edge infrastructure](edge-infrastructure.md)**: How requests reach ICP canisters: API boundary nodes, HTTP gateways, and asset certification. +- **[Evolution & scaling](evolution-scaling.md)**: How ICP scales horizontally through subnet creation and upgrades its protocol without forks. + +## Protocol Stack + +- **[Overview](protocol/index.md)**: The four-layer architecture and how the layers interact. +- **[Peer-to-peer](protocol/peer-to-peer.md)**: How replicas discover each other and exchange artifacts. +- **[Consensus](protocol/consensus.md)**: How subnets agree on the order of messages. +- **[Message routing](protocol/message-routing.md)**: How messages are delivered to canisters after consensus. +- **[Execution](protocol/execution.md)**: How the Wasm runtime processes messages and manages canister state. +- **[State synchronization](protocol/state-synchronization.md)**: How replicas catch up after falling behind. +- **[Performance](protocol/performance.md)**: Throughput benchmarks and performance characteristics. -## Core capabilities +## Canisters & capabilities +- **[Canisters](canisters.md)**: Programs that run WebAssembly, hold state, serve HTTP, and pay for their own compute. +- **[Principals](principals.md)**: The identity model: who can call a canister, and how caller identity works. +- **[Application architecture](app-architecture.md)**: How ICP applications are structured: canisters, frontends, and inter-canister communication. - **[Cycles](cycles.md)**: How canisters pay for their own compute, storage, and bandwidth, and why users pay nothing. -- **[Orthogonal Persistence](orthogonal-persistence.md)**: How canister memory survives across executions and upgrades without databases. -- **[HTTPS Outcalls](https-outcalls.md)**: How canisters make HTTP requests to external services with consensus on responses. -- **[Verifiable Randomness](verifiable-randomness.md)**: Cryptographically secure random numbers using threshold VRF. +- **[Orthogonal persistence](orthogonal-persistence.md)**: How canister memory survives across executions and upgrades without databases. - **[Timers](timers.md)**: Periodic and one-shot scheduled tasks via the global timer mechanism. +- **[Verifiable randomness](verifiable-randomness.md)**: Cryptographically secure random numbers using threshold VRF. +- **[HTTPS outcalls](https-outcalls.md)**: How canisters make HTTP requests to external services with consensus on responses. -## Cryptography and cross-chain +## Cryptography -- **[Chain-Key Cryptography](chain-key-cryptography.md)**: Threshold signatures that enable cross-chain integration, fast finality, and chain evolution. -- **[Chain Fusion](chain-fusion.md)**: How ICP connects to Bitcoin, Ethereum, Solana, and other blockchains natively. +- **[Chain-key cryptography](chain-key-cryptography.md)**: Threshold signatures that enable cross-chain integration, fast finality, and chain evolution. +- **[Certified data](certified-data.md)**: How canisters certify query responses using the subnet's threshold BLS key. - **[VetKeys](vetkeys.md)**: Verifiable encrypted threshold key derivation for onchain encryption and secret management. -## Trust and governance +## Chain Fusion + +- **[Chain Fusion](chain-fusion/index.md)**: How ICP connects to Bitcoin, Ethereum, Solana, and other blockchains natively. +- **[Bitcoin integration](chain-fusion/bitcoin.md)**: Native Bitcoin support via the Bitcoin canister and chain-key ECDSA. +- **[Ethereum integration](chain-fusion/ethereum.md)**: EVM chain integration via HTTPS outcalls, chain-key ECDSA, and the EVM RPC canister. +- **[Solana integration](chain-fusion/solana.md)**: Solana integration via the SOL RPC canister and chain-key Schnorr signatures. +- **[Dogecoin integration](chain-fusion/dogecoin.md)**: Dogecoin support using the same architecture as Bitcoin integration. +- **[Chain-key tokens](chain-fusion/chain-key-tokens.md)**: Trustless 1:1 representations of external chain assets on ICP (ckBTC, ckETH, and more). +- **[Exchange rate canister](chain-fusion/exchange-rate-canister.md)**: On-chain oracle for cryptocurrency and fiat exchange rates. + +## Trust & governance -- **[Security Model](security.md)**: Canister isolation, trust boundaries, and the threat model for app developers. - **[Governance](governance.md)**: The NNS, SNS for app governance, neurons, and proposals. +- **[SNS framework](sns-framework.md)**: How the Service Nervous System works: architecture, launch process, neurons, and governance. +- **[Network economics](network-economics.md)**: ICP native asset uses, voting rewards, supply dynamics, and SNS asset configuration. +- **[Ledgers](ledgers.md)**: How ICRC and ICP ledgers work, address formats, and scaling architecture. +- **[Security model](security.md)**: Canister isolation, trust boundaries, and the threat model for app developers. diff --git a/docs/concepts/ledgers.md b/docs/concepts/ledgers.md new file mode 100644 index 00000000..dbc9f46e --- /dev/null +++ b/docs/concepts/ledgers.md @@ -0,0 +1,75 @@ +--- +title: "Ledgers" +description: "How ledgers work on ICP: the ICP ledger, ICRC ledgers, addresses, transactions, archives, and fees" +sidebar: + order: 14 +--- + +Every digital asset on ICP is managed by a **ledger canister**: a canister that records ownership and permanently logs every transfer and balance change. This page explains how ledgers are structured, how they scale, and what the different address formats mean. + +## What a ledger canister does + +A ledger canister is the authoritative source of truth for an asset. It: + +- Records the current balance of every account. +- Logs every transfer, mint, and burn operation in an append-only transaction history. +- Validates and executes transfer requests. +- Enforces transaction fees. + +Unlike a traditional bank, ledger canisters are publicly readable: anyone can query transaction history through explorers and verify balances independently. + +There is no single global ledger on ICP. Each asset is managed by its own ledger canister, deployed and governed by whoever controls that canister. ICP has its own ledger. Every [ICRC](../references/icrc-standards.md)-standard asset has its own ledger. [Chain-key tokens](chain-fusion/index.md#chain-key-tokens) such as ckBTC and ckETH each have their own ledger canisters. + +## Two ledger designs + +ICP has two ledger designs in common use, each with a different address format. + +### ICP ledger + +The ICP ledger manages the native ICP asset. It uses an address format called an **AccountIdentifier**: a 32-byte hash derived from a principal ID and an optional subaccount. AccountIdentifiers are displayed as 64-character hex strings. + +### ICRC ledgers + +Most fungible assets on ICP (including chain-key tokens like ckBTC and ckETH) use the ICRC standard. ICRC ledgers use a two-part account format: + +- **Principal**: the identity of the holder (a user principal or canister principal). +- **Subaccount** (optional): a 32-byte value that lets a single principal manage many internal accounts. + +This model gives wallets and services flexibility: a single canister can track individual user balances in separate subaccounts without deploying a separate canister per user. + +The [ICRC](../references/icrc-standards.md) standard defines a family of interfaces. ICRC-1 covers basic transfers. ICRC-2 adds approval and transfer-from semantics (like ERC-20 allowances). ICRC-3 standardizes the transaction log format. All DFINITY-maintained asset ledgers implement at least ICRC-1 and ICRC-2. See [Digital assets guide](../guides/digital-assets/ledgers.md) for the API. + +## How transactions are recorded + +Ledgers maintain an append-only transaction log. Every transfer, mint, and burn creates a new block at the end of the log. Blocks are never removed or rewritten, making the history fully auditable. + +Each block contains the operation type, the accounts involved, the amount, the timestamp, and an optional memo. This log is the basis for wallet balance displays and explorer history views. + +## Scaling with archives and index canisters + +As a ledger accumulates transactions, its storage grows. Two additional components manage this growth: + +**Archive canisters.** Older transaction blocks are moved out of the main ledger canister into archive canisters. This lets the ledger scale well beyond a single canister's storage limit and across subnet boundaries. From a user's perspective, the history remains fully accessible through explorers and tooling; archiving is an internal implementation detail. + +**Index canisters.** Most deployed ledgers have a companion index canister that organizes transaction data by account address. Wallets and explorers query the index to retrieve the transaction history for a specific account without scanning every block in the ledger. The index does not change any balances or create new transactions; it is purely a read-optimized view over the ledger's history. + +Together: the ledger records the truth, archives extend storage capacity, and the index makes retrieval fast. + +## Transaction fees + +Most transfers incur a small fee. The sender pays the fee when initiating a transfer. Depending on how the ledger is configured, fees are either: +- **Burned**: removed from the total supply permanently, creating deflationary pressure. +- **Collected**: sent to a designated fee account (as the ICP ledger does for the NNS). + +Fees are typically small and fixed (for example, the ICP transfer fee is 0.0001 ICP; the ckBTC transfer fee is 10 satoshi). Because cycle costs are stable in XDR terms, transaction fees in cycles-denominated contexts remain predictable even as ICP's market price changes. + +## Next steps + +- [Digital assets guide](../guides/digital-assets/ledgers.md): ICRC-1/2 API usage, transfer examples, balance queries +- [Network economics](network-economics.md): how ICP and SNS assets are economically designed +- [Cycles](cycles.md): cycles as the computational fuel that ledger canisters and other canisters consume +- [Chain-key tokens](chain-fusion/index.md#chain-key-tokens): ckBTC, ckETH, and other 1:1 backed asset ledgers +- [IC Dashboard ICRC API](../references/ic-dashboard-api.md#icrc-api): query token balances and transaction history for ICRC assets programmatically +- [IC Dashboard Ledger API](../references/ic-dashboard-api.md#ledger-api): query ICP ledger accounts and transaction history programmatically + + diff --git a/docs/concepts/network-economics.md b/docs/concepts/network-economics.md new file mode 100644 index 00000000..5e1e84c8 --- /dev/null +++ b/docs/concepts/network-economics.md @@ -0,0 +1,73 @@ +--- +title: "Network economics" +description: "How the Internet Computer's economic model works: ICP uses, governance rewards, supply dynamics, and SNS asset configuration" +sidebar: + order: 13 +--- + +ICP's economic model is built around two native assets: **ICP** and **cycles**. They serve distinct purposes: ICP is a governance and value transfer digital asset; cycles are a stable-cost computational fuel that canisters consume to run. This separation keeps developer costs predictable regardless of ICP market price. + +## ICP uses + +ICP has four protocol-level uses: + +**1. Governance participation.** ICP holders stake ICP to create [neurons](governance.md#neurons) in the Network Nervous System (NNS) governance system. Neurons vote on proposals and earn voting rewards in return. Staking longer increases voting power and rewards, creating an incentive for long-term alignment with the network. + +**2. Cycle conversion.** ICP can be burned to mint cycles through the Cycles Minting Canister (CMC). Cycles are pegged to the XDR basket of currencies at a rate of 1 trillion cycles = 1 XDR. This means developer infrastructure costs are stable in fiat terms even as ICP's market price changes. See [Cycles](cycles.md) for details. + +**3. Node provider rewards.** Nodes that run the Internet Computer are owned by independent node providers. These providers are compensated in newly minted ICP. Rewards are specified in XDR and converted to ICP based on a 30-day moving average exchange rate, so providers receive stable real-world compensation regardless of price fluctuations. The Cycles Minting Canister (CMC) fetches the ICP/XDR rate every 5 minutes from the [exchange rate canister](chain-fusion/exchange-rate-canister.md#how-rates-are-computed), which aggregates rates from external sources. It uses the start-of-day rates for the past 30 days to compute the moving average. The current conversion rate is available on the [ICP dashboard](https://dashboard.internetcomputer.org/network) and from the [CMC metrics endpoint](https://rkp4c-7iaaa-aaaaa-aaaca-cai.raw.icp0.io/metrics). + +**4. SNS decentralization swaps.** Users can commit ICP to participate in the decentralization swap of an SNS. In return they receive the SNS's governance assets at a uniform price. The ICP raised enters the SNS treasury under NNS control and funds future development and operations. + +Beyond these protocol uses, ICP also functions as a medium of exchange: applications built on ICP can accept ICP as payment for subscriptions, digital goods, and services. + +## Governance rewards and maturity + +Any ICP holder can stake ICP in a neuron to participate in NNS governance. Each day the NNS calculates a voting reward pot and distributes it among eligible neurons proportionally to their voting power and participation. + +Reward rate schedule: +- **At genesis:** rewards are calibrated to distribute roughly 10% of total supply per year in annualized terms. +- **Over 8 years:** the rate declines to approximately 5% per year. + +Rewards accumulate as **maturity** within the neuron, not as liquid ICP. Maturity can be converted to ICP (spawning), which at that point triggers the actual minting. This deferred minting means the total supply grows only when neurons choose to realize rewards, giving holders flexibility over when to enter circulation. + +The daily reward amount is fixed (independent of total staked ICP), so lower overall participation means each participant earns a higher share. This self-regulating mechanism incentivizes participation. + +## Supply dynamics + +ICP has both inflationary and deflationary mechanisms: + +**Inflationary:** +- New ICP is minted to pay node provider rewards. +- New ICP is minted when neurons spawn voting rewards as maturity. + +**Deflationary:** +- ICP is burned when converted to cycles. +- ICP transaction fees are burned. +- Failed NNS proposals result in a small fee charged to the proposing neuron. + +![ICP supply dynamics: governance rewards and node provider rewards increase supply; cycle conversion and transaction fees reduce it](/concepts/network-economics/deflation-inflation.png) + +The net effect on supply depends on market conditions: when cycle demand is high (more computation), more ICP is burned. When governance participation is high, more ICP is minted. The [NNS dashboard](https://dashboard.internetcomputer.org/governance) shows live estimates of supply, staking, and annualized voting rewards. + +## SNS economics + +Each SNS deploys its own governance asset alongside its canister, with an economics configuration set at launch. The mechanics are similar to the NNS: staking for voting power, configurable voting reward minting, transaction fee burning, and a treasury for SNS-controlled spending. + +Key parameters a team configures for their SNS: + +- **Initial asset allocation**: how assets are split between the decentralization swap (community), SNS treasury, seed funders, and the development team. The SNS framework requires that at least as many assets are allocated to the swap as to the seed funders and development team combined. +- **Voting power**: teams can weight voting power by staking duration to encourage long-term commitment. The configuration must prevent the founding team from holding more than 50% of initial voting power. +- **Reward rate**: whether and at what rate the SNS mints new assets for governance participation. +- **Transaction fees**: a per-transfer fee that is burned, creating deflationary pressure. + +SNS economics is entirely configurable and independent of the NNS economic model. Two SNS instances can have very different economic designs. + +## Next steps + +- [Governance](governance.md): NNS neurons, proposals, voting, and the SNS framework +- [Cycles](cycles.md): how cycle costs work and how ICP converts to cycles +- [Ledgers](ledgers.md): how ICP and other asset balances are tracked +- [Launching an SNS](../guides/governance/launching.md): the decentralization swap process + + diff --git a/docs/concepts/network-overview.md b/docs/concepts/network-overview.md index 1100c297..1362c19c 100644 --- a/docs/concepts/network-overview.md +++ b/docs/concepts/network-overview.md @@ -1,5 +1,5 @@ --- -title: "Network Overview" +title: "Network overview" description: "How the Internet Computer works: subnets, nodes, consensus, and boundary nodes" sidebar: order: 1 @@ -26,7 +26,7 @@ For details on subnet types and how to choose one, see [Subnet types](../referen ## Nodes -Each physical machine in the network is a **node**. Nodes run software called the **replica**, which implements the ICP protocol stack: consensus, message routing, execution, and state management. +Each physical machine in the network is a **node**. Nodes run software called the **replica**, which implements the ICP [protocol stack](protocol/index.md): peer-to-peer, consensus, message routing, and execution. Nodes are owned by **node providers**: independent entities who operate the hardware. Node providers are voted into the network by the governance system (NNS) and must meet specific hardware requirements. This process, called **deterministic decentralization**, ensures that subnet membership is diverse across operators, geographies, and jurisdictions. @@ -34,29 +34,20 @@ As a developer, you don't interact with individual nodes directly. The protocol ## Consensus -Each subnet runs a four-phase consensus protocol: +Each subnet runs a consensus protocol that produces one finalized block per round, approximately every 1 second. ICP provides cryptographic (not probabilistic) finality: once your update call returns, the state change is committed. Query calls skip consensus entirely: a single node handles the request, which is why queries are fast but carry weaker authenticity guarantees than update calls. -1. **Block making.** A designated block maker proposes a block of messages to execute. -2. **Notarization.** A threshold of nodes validates and signs the proposed block. -3. **Finalization.** Once a notarized block has no competing blocks, it is finalized. -4. **Execution.** All nodes execute the messages in the finalized block deterministically, reaching the same resulting state. - -This produces one block per round (approximately every 1 second). Update calls achieve the rapid finality described above because there is no need to wait for multiple block confirmations. - -Query calls skip consensus entirely: a single node handles the request and returns its local state, which is why queries are fast (milliseconds) but provide weaker authenticity guarantees than update calls. - -For a deeper dive into the consensus protocol and other protocol internals, see the [Learn Hub](https://learn.internetcomputer.org). +For how the protocol achieves this (block making, notarization, finalization, and the other layers), see [Protocol Stack](protocol/index.md). ## Boundary nodes Boundary nodes are the entry point for all external traffic to ICP. They serve two purposes: 1. **HTTP gateway.** When a user's browser requests `https://.icp0.io`, a boundary node translates that HTTP request into a canister message, routes it to the correct subnet, and returns the response. -2. **API endpoint.** Agent libraries (like [`@icp-sdk/core/agent`](https://js.icp.build) in JavaScript) send ingress messages to boundary nodes, which forward them to the target canister's subnet. +2. **API endpoint.** Agent libraries (like [`@icp-sdk/core/agent`](https://js.icp.build/core/latest/libs/agent) in JavaScript) send ingress messages to boundary nodes, which forward them to the target canister's subnet. Boundary nodes also cache query responses and provide TLS termination. They are not part of consensus and cannot modify canister state: they are routing infrastructure. -From a developer's perspective, boundary nodes are mostly transparent. You interact with them through the standard agent libraries or icp-cli, and they handle the routing. The main thing to be aware of is that query responses pass through a boundary node, which is why [certified variables](../guides/backends/certified-variables.md) exist for applications that need authenticated query results. +From a developer's perspective, boundary nodes are mostly transparent. You interact with them through the standard agent libraries or icp-cli, and they handle the routing. The main thing to be aware of is that query responses pass through a boundary node, which is why [certified variables](certified-data.md#certified-variables) exist for applications that need authenticated query results. ## How it all fits together @@ -64,7 +55,7 @@ Here is the path of a typical request: 1. A user's browser sends an HTTPS request to a boundary node. 2. The boundary node looks up which subnet hosts the target canister and forwards the message. -3. For update calls: the subnet's consensus protocol includes the message in a block, all nodes execute it, and the subnet signs the response. For query calls: a single node executes the call and returns the result: query responses are not threshold-signed by the subnet, so they should be treated as unverified unless the canister uses [certified variables](../guides/backends/certified-variables.md). +3. For update calls: the subnet's consensus protocol includes the message in a block, all nodes execute it, and the subnet signs the response. For query calls: a single node executes the call and returns the result: query responses are not threshold-signed by the subnet, so they should be treated as unverified unless the canister uses [certified variables](certified-data.md#certified-variables). 4. The boundary node returns the response to the user. The entire flow (from user request to signed response) completes within the finality window described above for updates, and under 100 milliseconds for queries. diff --git a/docs/concepts/node-infrastructure.md b/docs/concepts/node-infrastructure.md new file mode 100644 index 00000000..bfcb53d7 --- /dev/null +++ b/docs/concepts/node-infrastructure.md @@ -0,0 +1,186 @@ +--- +title: "Node infrastructure" +description: "How ICP nodes are structured: the IC-OS operating system stack, virtual machine isolation, and Trusted Execution Environments." +--- + +Every node in the Internet Computer network runs **IC-OS**: a custom operating system stack based on Ubuntu Linux and designed specifically for ICP. IC-OS provides a consistent, secure execution environment across all nodes regardless of the underlying hardware, which is a prerequisite for the deterministic execution that consensus requires. + +## IC-OS: three operating systems in one + +IC-OS is not a single operating system but a layered stack of three systems, each with a distinct role. + +### SetupOS + +SetupOS is used once: when initializing a new node for the first time. A [node provider](../references/glossary.md#node-provider) boots from a USB drive containing SetupOS, which automatically: + +- Verifies that the hardware meets ICP node requirements +- Tests network connectivity +- Installs HostOS and GuestOS onto the machine +- Configures the node with its identity and initial cryptographic keys + +After setup completes, the machine reboots into HostOS. SetupOS is not used again unless the node needs to be re-provisioned from scratch. + +### HostOS + +HostOS runs directly on the physical hardware. Its sole purpose is to configure and run the GuestOS virtual machine. It: + +- Launches the GuestOS virtual machine +- Manages hardware resource allocation +- Handles GuestOS upgrades pushed by the [Network Nervous System (NNS)](../references/glossary.md#network-nervous-system-nns) +- Provides a security boundary between the physical hardware and the ICP software stack + +HostOS is intentionally minimal. It treats the GuestOS as an untrusted process running in a virtual machine, which limits what a compromised GuestOS can do to the host and what the host can do to the guest. + +### GuestOS + +GuestOS runs inside a virtual machine on top of HostOS. This is where the ICP software actually executes. GuestOS: + +- Runs the [replica](../references/glossary.md#replica) process and the orchestrator (implementing the four-layer protocol stack) +- Executes canisters and manages their state +- Participates in consensus with other nodes in the subnet +- Manages cryptographic key material and threshold signature operations + +Running GuestOS in a virtual machine ensures every node presents the same software environment to the replica, regardless of the underlying hardware. It also enables the Trusted Execution Environment (TEE) protection described below. + +## Trusted Execution Environments + +Running the GuestOS inside a virtual machine provides logical isolation from the host, but a sophisticated attacker with physical access to a node could historically inspect or tamper with GuestOS memory by compromising the HostOS or hypervisor. + +Trusted Execution Environments (TEEs) address this by enforcing hardware-level isolation between a virtual machine and its host. Even if the HostOS or hypervisor is compromised, the confidentiality and integrity of GuestOS memory and state are preserved. TEE-enabled nodes are being rolled out across the network as hardware is upgraded. + +ICP uses AMD's **Secure Encrypted Virtualization with Secure Nested Paging (SEV-SNP)** as its TEE technology. SEV-SNP provides four capabilities that together make it possible to trust a GuestOS running on a potentially compromised host: + +1. **Memory encryption**: protection of GuestOS memory from unauthorized reads or writes by the host +2. **VM launch measurements**: cryptographic fingerprints that capture how the VM was initialized +3. **Attestation reports**: verifiable evidence that a VM is running inside a genuine SEV-SNP TEE with a specific configuration +4. **Sealing keys**: hardware-derived keys that allow data to be securely encrypted for persistent storage + +![Securing the Internet Computer with Trusted Execution Environments](/concepts/node-infrastructure/tee-overview.jpg) + +### Memory encryption + +SEV-SNP encrypts all memory pages of the GuestOS virtual machine using keys protected by the CPU's secure processor. A host that gains full control of the machine can only read encrypted blobs from the GuestOS memory: canister state, cryptographic key shares, and other sensitive runtime data remain confidential. + +### VM launch measurements + +A VM launch measurement is a cryptographic fingerprint of the GuestOS at the moment it starts. The SEV-SNP secure processor computes this measurement from the CPU model and firmware, the guest kernel, the initial ramdisk, and the kernel command-line parameters. Any single-byte change to the GuestOS software or configuration produces a different measurement. + +The kernel command-line parameters included in the measurement contain, among other things, the expected hash of the root filesystem, which is verified during early boot. Any modification to the GuestOS (whether in code, configuration, or filesystem contents) therefore leads to a different launch measurement. + +For each GuestOS release, the expected launch measurement can be computed in advance and published as part of the release. Nodes running the same GuestOS version produce identical measurements, which provides a basis for verifying that a node is running approved software. + +### Attestation reports + +An attestation report is a signed document produced by the SEV-SNP secure processor. It contains the VM's launch measurement and the CPU's unique hardware identifier, signed by AMD's root of trust. This gives any verifier (whether another node or an external party) the ability to confirm that: + +- The VM is running inside a genuine SEV-SNP TEE +- The specific software and configuration that were loaded match an approved GuestOS release + +![SEV-SNP attestation report](/concepts/node-infrastructure/tee-attestation-report.svg) + +ICP uses attestation in two ways: + +- **Node-to-node attestation.** Before sensitive data or secrets are shared between nodes, SEV-SNP-enabled nodes attest each other. This is integral to the upgrade process (see below) and will be extended to all network connections as SEV-SNP adoption expands: each node pair attests the other at connection establishment, ensuring secrets are only exchanged with verified nodes. +- **External attestation.** SEV-SNP-equipped nodes expose a dedicated attestation endpoint for external verification. Access is restricted by firewall rules and is only available through API boundary nodes. External parties indirectly attest individual nodes through these API boundary nodes, which in turn verify the nodes they communicate with. + +### Sealing keys + +A sealing key is derived from two inputs: the CPU's unique hardware identifier and the VM's launch measurement. This means: + +- Each node produces a unique sealing key, even for the same GuestOS version +- If the GuestOS changes (for example after an upgrade), the derived key changes and previously encrypted data becomes inaccessible until a secure key handoff completes + +ICP uses sealing keys to encrypt the GuestOS disk partitions that contain sensitive runtime data. This ensures that even if an attacker copies the disk to another machine, the data cannot be decrypted: the sealing key depends on the specific CPU and the exact GuestOS configuration. + +## Disk encryption + +### Partition layout + +Each node maintains two partition sets (A and B). This dual layout allows a new GuestOS version to be prepared in the inactive set while the current version continues running, and enables rollback if an upgrade fails. + +| Partition | Notes | +|---|---| +| EFI | | +| GRUB | | +| config | | +| boot (A) | | +| root (A) | | +| **var (A)** | Encrypted; key derived from VM A's launch measurement | +| boot (B) | | +| root (B) | | +| **var (B)** | Encrypted; key derived from VM B's launch measurement | +| **store** | Encrypted; two keys, one per VM measurement | + +Only partitions holding sensitive data are encrypted. The `var` partitions contain runtime data private to the currently active GuestOS. The `store` partition holds persistent data shared across GuestOS versions. System partitions (`boot`, `root`, `config`) are not encrypted: their contents are not confidential, and root filesystem integrity is covered by the root hash embedded in the kernel command-line, which is part of the VM launch measurement. + +### From traditional disk encryption to sealing-key-based encryption + +ICP nodes have always used disk encryption for data partitions. However, the previous encryption keys were independent of the GuestOS and could in principle be accessed by a malicious GuestOS, leaving a potential attack vector for a highly skilled adversary who could compromise the GuestOS and read the encrypted data. + +With SEV-SNP, LUKS passphrases for each encrypted partition are now derived from the SEV-SNP sealing key using HKDF, giving each partition a unique passphrase tied to both the CPU and the exact GuestOS version. This means only the GuestOS that encrypted a partition can decrypt it, and any change in GuestOS version or hardware prevents access to previously encrypted data. + +![SEV-SNP key derivation](/concepts/node-infrastructure/tee-key-derivation.svg) + +On reboot, the GuestOS requests the sealing key from the SEV-SNP secure processor. As long as the launch measurement has not changed, the same sealing key is returned, allowing the node to decrypt the partitions. If the launch measurement changes (for example after an upgrade), a different sealing key is generated and the encrypted partitions can no longer be accessed. This is where the upgrade process and remote attestation come in. + +## GuestOS upgrades + +When a new GuestOS is approved by the NNS, its attributes (root filesystem hash and launch measurement) are published to the NNS registry, which serves as the source of truth for valid GuestOS versions. A malicious GuestOS cannot participate because it will have no entry in the registry. + +The upgrade then runs the old and new GuestOS instances in parallel: + +1. A proposal to upgrade a subnet or set of nodes is submitted and approved by the ICP community. +2. The new GuestOS image is downloaded into the inactive partition set while the current GuestOS continues running. +3. A temporary **Upgrade VM** boots the new GuestOS. It cannot yet access the encrypted `store` or `var` partitions because its sealing key (derived from the new launch measurement) differs from the current one. +4. The Upgrade VM generates an attestation report containing its launch measurement and sends it to the old GuestOS over a TLS channel. +5. The old GuestOS verifies the attestation report against the NNS registry to confirm the new GuestOS is an approved release. +6. Once verified, the old GuestOS shares the disk encryption key with the Upgrade VM. The Upgrade VM re-encrypts the partitions with a key derived from its own sealing key. +7. Both VMs shut down. The node boots into the upgraded GuestOS, which can now access the data using its own derived key. + +This process ensures that disk access transfers only to a verified, NNS-approved GuestOS version, and repeats for every future upgrade. + +## Emergency recovery + +TEE-enabled GuestOSes are designed to lock everyone out (including node operators) unless a specific, governance-gated recovery process is followed. Recovery is never automatic and always requires an NNS proposal approved by the community. Historically, emergency recoveries have occurred only a few times, and during 2025 not a single one was necessary. + +### Manual rollback + +Manual rollback is the first option when a node fails after an upgrade. The dual partition layout means the previous GuestOS version still resides on the inactive partition set. + +1. The recovery coordinator submits a proposal to the NNS marking the problematic GuestOS version as broken. If approved, nodes refuse to upgrade to that version again even if the subnet record still references it. +2. Node providers switch the active partition set back to the previous version via the HostOS limited console, without touching the GuestOS or breaking TEE guarantees. +3. The previous GuestOS boots and the node resumes normal operation. Once a fixed GuestOS version is released and approved, nodes upgrade to it. + +### Recovery-GuestOS + +When neither partition set boots, manual rollback is insufficient. The encrypted partitions can only be decrypted by a GuestOS with the original launch measurement, so no other GuestOS version can access the data, including a fixed one. + +The Internet Computer solves this with a Recovery-GuestOS: a specially crafted image that keeps the same kernel, initramdisk, and kernel command-line as the broken GuestOS (preserving the launch measurement) while replacing the root filesystem with a fixed version. The table below shows how this differs from a standard upgrade image: + +| | Upgrade image | Recovery image | +|---|---|---| +| Can be reproduced and verified by the community | yes | yes | +| kernel, initrd, kernel command-line | arbitrary | same as in base image | +| Root filesystem hash matches `root_hash` kernel parameter | yes | no | +| Boot partition contains NNS proposal with root filesystem hash | no | yes | + +Because the root hash in the kernel command-line no longer matches the recovery root filesystem, a special override is needed: the `BlessAlternativeGuestOsVersion` NNS proposal. During early boot, if the actual root hash does not match the expected hash in the kernel command-line, the integrity checker looks for this proposal. If present, valid, and listing the specific node's chip ID, the recovery root filesystem is mounted while preserving the original launch measurement, and therefore the same disk encryption key. + +The full process: + +1. The recovery coordinator collects the affected nodes' chip IDs and the base GuestOS launch measurement. +2. A Recovery-GuestOS branch is prepared in the Internet Computer repository. +3. A recovery root filesystem is created, and a `BlessAlternativeGuestOsVersion` proposal is submitted to the NNS with the recovery root filesystem hash, base launch measurement, and list of authorized chip IDs. +4. Once approved, a Recovery-GuestOS upgrade image is built combining the base kernel, initramdisk, kernel command-line, the recovery rootfs, and the signed proposal. +5. Node operators deploy it via the HostOS limited console. +6. During early boot, the integrity checker detects the root hash mismatch, verifies the NNS proposal, confirms the node's measurement and chip ID match, and mounts the recovery root filesystem. +7. The Recovery-GuestOS boots and the node resumes operation, with SEV-SNP privacy guarantees intact. + +Because the integrity checker is part of the initramdisk, a malicious actor cannot tamper with it without changing the SEV-SNP launch measurement, preserving the security of the node. + +## Further reading + +- [Protocol Stack](protocol/index.md): the four-layer architecture (peer-to-peer, consensus, message routing, execution) that runs inside GuestOS +- [Glossary: replica](../references/glossary.md#replica): the replica process that implements the protocol stack + + diff --git a/docs/concepts/orthogonal-persistence.md b/docs/concepts/orthogonal-persistence.md index a135c3ad..92efc58d 100644 --- a/docs/concepts/orthogonal-persistence.md +++ b/docs/concepts/orthogonal-persistence.md @@ -1,5 +1,5 @@ --- -title: "Orthogonal Persistence" +title: "Orthogonal persistence" description: "How canister memory survives across executions and upgrades without databases" sidebar: order: 5 diff --git a/docs/concepts/principals.md b/docs/concepts/principals.md new file mode 100644 index 00000000..940b6817 --- /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/concepts/protocol/consensus.md b/docs/concepts/protocol/consensus.md new file mode 100644 index 00000000..bdbff014 --- /dev/null +++ b/docs/concepts/protocol/consensus.md @@ -0,0 +1,65 @@ +--- +title: "Consensus" +description: "How ICP subnets reach agreement on message ordering through block making, notarization, and finalization." +sidebar: + order: 2 +--- + +The consensus protocol allows every node in a subnet to agree on which messages to process and in what order. Each subnet runs its own independent instance of the protocol. The output of each consensus round is a single finalized block of ordered messages that every node then executes deterministically, producing the same state transition on each. + +ICP's consensus is designed to meet three requirements: + +- **Low latency.** Blocks are finalized in roughly one second, achieving near-instant finality. +- **High throughput.** Many messages can be included in each block. +- **Robustness.** The protocol degrades gracefully under node or network failures, maintaining safety regardless of message delivery timing. + +## Cryptographic finality + +ICP provides cryptographic finality rather than probabilistic finality. Probabilistic finality considers a block final only after enough subsequent blocks have built on top of it. ICP avoids this approach for two reasons: probabilistic finality is a very weak guarantee, and it would substantially increase the time before a message response can be trusted. + +The ICP consensus protocol achieves cryptographic finality while making minimal assumptions about the network. Safety does not depend on any bound on message delivery time (the protocol only assumes an asynchronous network). For a globally distributed network, synchrony is not a realistic assumption. When messages do arrive promptly, the protocol makes progress with good latency. Correctness is always guaranteed regardless of message delays, as long as fewer than one third of subnet nodes are faulty. + +## Consensus rounds + +![Consensus round yields an ordered sequence of messages](/concepts/protocol/consensus_orders_messages.webp) + +The protocol maintains a tree of notarized blocks, with a special genesis block at the root. The protocol proceeds in rounds. Each round adds at least one new notarized block to the tree as a child of a notarized block from the previous round. When things proceed normally, exactly one notarized block is added and it is immediately finalized. Once a block is finalized, all of its ancestors are implicitly finalized. The protocol guarantees a unique chain of finalized blocks. This chain is the output of consensus. + +At a high level, each round has three phases: + +- **Block making.** At least one node (the block maker) proposes a block by broadcasting it to all nodes in the subnet. When things go right there is only one block maker, but sometimes there may be several. +- **Notarization.** For a block to become notarized, at least two thirds of the nodes must validate and support its notarization. +- **Finalization.** For a block to become finalized, at least two thirds of the nodes must support its finalization. A node supports finalization only if it did not support notarization of any other block in that round, which guarantees that a finalized block has no competing notarized block. + +### Block making + +In every round, one or more nodes called [block makers](../../references/glossary.md#block-maker) propose a block. Each block contains a reference to a notarized block from the previous round, ingress messages submitted by users (received directly or via P2P from other nodes), and XNet messages received from other subnets. + +Block makers are selected through a random permutation of subnet nodes, using randomness derived from a [random beacon](../../references/glossary.md#random-beacon) produced by [chain-key cryptography](../chain-key-cryptography.md). The permutation assigns a rank to each node. The lowest-rank node acts as the primary block maker and broadcasts its proposal to all subnet nodes. + +If the primary block maker is faulty or the network is slow and no notarized block appears within a timeout, nodes of increasing rank step in to propose blocks. The protocol guarantees that one block eventually gets notarized in every round. + +![Block maker constructs a new block and broadcasts it to the subnet](/concepts/protocol/block_maker.webp) + +### Notarization + +When a node receives a block proposal, it validates it for syntactic correctness. If valid, the node broadcasts the block along with a notarization share: a BLS multi-signature share. A block becomes notarized when at least two thirds of subnet nodes have submitted notarization shares for it. These shares can be aggregated into a compact notarization. + +If the primary block maker's proposal is notarized within the timeout, a node will not support the notarization of any other block in that round. Otherwise, a node may support notarization of blocks from higher-rank block makers (but only up to the highest rank it has already committed to). + +![Notarization support of increasing-rank block proposals in a round](/concepts/protocol/consensus_notarization.webp) + +### Finalization + +Once a node obtains a notarized block, it will not subsequently support notarization of any other block in that round. If the node had not previously supported notarization of any other block, it also broadcasts a finalization share for this block. A block is finalized when at least two thirds of nodes have submitted finalization shares. + +This rule guarantees that if a block is finalized in a given round, no other notarized block exists in that round: the chain remains unique. + +## Further reading + +- [Protocol Stack](index.md): how consensus fits into the four-layer architecture +- [DFINITY Consensus blog post](https://medium.com/dfinity/achieving-consensus-on-the-internet-computer-ee9fbfbafcbc) +- [Consensus white paper](https://eprint.iacr.org/2021/632.pdf) +- [Extended abstract published at PODC '22](https://assets.ctfassets.net/ywqk17d3hsnp/1Gutwfrd1lMgiUBJZGCdUG/d3ea7730aba0a4b793741681463239f5/podc-2022-cr.pdf) + + diff --git a/docs/concepts/protocol/execution.md b/docs/concepts/protocol/execution.md new file mode 100644 index 00000000..289c2712 --- /dev/null +++ b/docs/concepts/protocol/execution.md @@ -0,0 +1,73 @@ +--- +title: "Execution layer" +description: "How ICP deterministically executes canister code using WebAssembly, deterministic time slicing, and concurrent execution." +sidebar: + order: 4 +--- + +The execution layer is the topmost layer of the ICP core protocol stack. It is responsible for executing canister code after message routing has inducted messages into canister input queues. Code runs in a [WebAssembly](https://webassembly.org/) (Wasm) virtual machine deployed on every subnet node. Wasm bytecode executes deterministically and at near-native speed, both of which are essential properties for a replicated system. + +Execution proceeds deterministically: every honest node on the subnet executes the same messages in the same order and reaches the same resulting state. + +## Replicated execution + +Execution proceeds in rounds. Each round, message routing invokes the execution layer once to process (a subset of) the messages in canister input queues. A round ends either when all queued messages have been executed or when the cycles limit for the round is reached, ensuring bounded round times. + +Executing a message can: + +- Modify memory pages in the canister's state (marking them "dirty") +- Create new messages to other canisters on the same or different subnets +- Generate a response to an ingress message + +Messages to local canisters are queued directly in the target canister's input queue and scheduled for the same or an upcoming round, without going through consensus. Messages to canisters on other subnets are placed into the XNet queue and certified by the subnet at the end of the round. + +## Concurrent execution + +The execution layer is designed to execute multiple canisters concurrently on different CPU cores. This is possible because each canister has its own isolated state and inter-canister communication is asynchronous. Concurrent execution within a subnet, combined with multiple subnets running in parallel, makes ICP scale like a public cloud: by adding more subnets. + +## Deterministic time slicing + +Each execution round is synchronized with block production, which happens roughly once per second. The current per-round instruction limit is approximately 2 billion instructions per canister given present node hardware. + +For longer computations (up to 20 billion instructions, or up to 200 billion for code installation), ICP uses **Deterministic Time Slicing (DTS)**. DTS pauses a long-running computation at the end of a round and resumes it in the next, allowing a task to span multiple rounds without slowing block creation. DTS is automatic and transparent to canisters: no special canister code is needed. + +## Memory handling + +One of the execution layer's key responsibilities is managing canister bytecode and state (collectively: canister memory). The replicated state a subnet can hold is bounded by available SSD storage, not RAM. Available RAM affects performance through access latency, much as it does in traditional systems. + +ICP node machines are equipped with high-end SSD storage and substantial RAM to hold large amounts of replicated canister state and Wasm code. + +Memory pages representing canister state are persisted to SSD automatically by the execution layer. This [**orthogonal persistence**](../orthogonal-persistence.md) frees developers from explicitly managing reads and writes to storage. The full canister state is always available on the heap or in stable memory: + +- **Heap memory** is cleared when canister code is upgraded. State intended to survive upgrades must be moved to stable memory before the upgrade and restored afterward. +- **Stable memory** persists across code upgrades. Large state should be kept in stable memory directly to avoid the cost and risk of copying it back and forth at upgrade time. + +## Random number generation + +Many applications require a secure source of randomness. Generating random numbers naively in a replicated setting destroys determinism, since each node would produce different values. ICP solves this with the **random tape**: a decentralized pseudorandom number generator built using chain-key cryptography. + +Each round, the subnet produces a fresh threshold BLS signature. This signature is unpredictable and uniformly distributed by its nature. It is used as a seed for a cryptographic pseudorandom generator, giving canisters access to a secure, efficient, and verifiable source of randomness. + +## Cycles accounting + +Executing a canister consumes network resources. These resources are paid for with [**cycles**](../../references/glossary.md#cycle). Each canister holds a local cycles account. The canister itself pays for its own storage and computation: users never send cycles with their messages. Ensuring the cycles account is funded is the responsibility of the canister's maintainer (a developer, a team, or a community-governed application). + +When canister Wasm code is installed or upgraded, it is instrumented with instruction-counting code. This allows the exact number of cycles to be charged for each message execution in a fully deterministic way, so every node charges the same amount and replicated state machine properties are preserved. + +Cycles are also charged for: + +- **Storage.** Both Wasm code and canister state are charged per unit of time, similar to cloud storage billing. Prices scale with the subnet's replication factor. +- **Networking.** Receiving ingress messages, sending XNet messages, and making HTTPS outcalls are all charged in cycles. + +## Query execution + +[Query calls](../../references/glossary.md#query) (non-replicated execution) are executed by a single node and return a response synchronously. Unlike update calls, queries cannot change the replicated state of the subnet: they are read operations on one replica. Queries execute concurrently across multiple threads on a single node, and all nodes in the subnet can serve different queries concurrently, so query throughput scales linearly with subnet size. + +The tradeoff is the trust model: a single node executes the query, so a compromised node could return an arbitrary result. For critical data, use update calls (which produce responses certified by the subnet) or [certified variables](../../guides/backends/certified-variables.md). + +## Further reading + +- [Protocol Stack](index.md): how execution fits into the four-layer architecture +- [Usenix ATC paper on the ICP execution environment](https://www.usenix.org/system/files/atc23-arutyunyan.pdf) + + diff --git a/docs/concepts/protocol/index.md b/docs/concepts/protocol/index.md new file mode 100644 index 00000000..81376019 --- /dev/null +++ b/docs/concepts/protocol/index.md @@ -0,0 +1,47 @@ +--- +title: "Protocol stack" +description: "The four-layer architecture that every ICP subnet runs: peer-to-peer, consensus, message routing, and execution." +--- + +The Internet Computer is created by the Internet Computer Protocol (ICP), which gives the network its name. ICP consists of multiple subnets, with each subnet running its own instance of the protocol stack. Each subnet hosts canisters and executes messages sent to them by users or by other canisters (which may be hosted on the same or a different subnet). + +A message addressed to a canister is executed by every node in the corresponding subnet. Execution updates the canister state. To keep state in sync across all nodes, every node must execute the same messages in the same order: fully deterministically. This replicated state machine property is the core of what makes ICP a trustworthy execution environment. + +## Four-layer architecture + +Each node runs a replica process structured in four layers: + +1. [Peer-to-peer](peer-to-peer.md): secure and reliable message broadcast between nodes +2. [Consensus](consensus.md): agreement on which messages to process and in what order +3. [Message routing](message-routing.md): delivery of messages to canister input queues and state certification +4. [Execution](execution.md): deterministic execution of canister code + +![4-layer architecture of the Internet Computer](/concepts/protocol/core_protocol_layers.webp) + +The **peer-to-peer** layer accepts messages from users and exchanges messages between nodes. The **consensus** layer makes all nodes agree on which messages to process and in what order. The **message routing** layer picks up finalized blocks from consensus and routes messages to the appropriate canisters. The **execution** layer deterministically executes canister code on those messages. + +The lower two layers (peer-to-peer and consensus) are responsible for agreeing, each round, on a block of messages. The upper two layers (message routing and execution) deterministically process that block on every node. + +At the start of a round, all honest nodes hold identical state: the replicated state of the subnet, which includes the current state of every canister hosted there. By executing the messages in a finalized block in a completely deterministic way, every node reaches the same resulting state. + +## Cross-subnet messaging + +Canisters communicate with each other regardless of whether they share a subnet. The protocol handles both: + +- **Intra-subnet messages.** Messages between canisters on the same subnet do not go through consensus. They are placed directly into the target canister's input queue and scheduled for execution. This makes local inter-canister calls faster in terms of latency and throughput. +- **Cross-subnet messages (XNet).** Messages to canisters on other subnets flow through the XNet stream. The originating subnet certifies these messages using [chain-key cryptography](../chain-key-cryptography.md), and block makers on the receiving subnet validate the certificate and include the messages in a block. + +## State synchronization + +To allow nodes to efficiently join a running subnet or catch up after downtime, the protocol supports [state synchronization](state-synchronization.md). Rather than replaying every message ever executed, a new or recovering node downloads a recent certified checkpoint and replays only the blocks produced since that checkpoint. + +## Further reading + +- [Peer-to-peer](peer-to-peer.md): Abortable Broadcast and QUIC transport +- [Consensus](consensus.md): block making, notarization, and finalization in detail +- [Message routing](message-routing.md): induction, XNet streaming, and state certification +- [Execution](execution.md): WebAssembly execution, deterministic time slicing, and cycles +- [State synchronization](state-synchronization.md): catch-up packages and incremental sync +- [Performance](performance.md): throughput, latency, and mainnet benchmark figures + + diff --git a/docs/concepts/protocol/message-routing.md b/docs/concepts/protocol/message-routing.md new file mode 100644 index 00000000..7cbf0cf7 --- /dev/null +++ b/docs/concepts/protocol/message-routing.md @@ -0,0 +1,72 @@ +--- +title: "Message routing" +description: "How ICP routes messages between canisters across subnets, certifies subnet state, and enables secure cross-subnet communication." +sidebar: + order: 3 +--- + +Message routing is the lower of the two upper layers of the ICP protocol stack. It sits above consensus and below execution, orchestrating the flow of messages from finalized blocks into canister input queues, triggering execution, routing the resulting inter-canister messages, and certifying subnet state. + +Its responsibilities fall into four areas: + +- **Induction.** Extracting messages from finalized consensus blocks and placing them into canister input queues. +- **Execution invocation.** Triggering the execution layer to process the inducted messages. +- **Message routing.** Forwarding inter-canister messages within the subnet and into outgoing XNet streams for cross-subnet delivery. +- **State certification.** Certifying the subnet's replicated state using [chain-key cryptography](../chain-key-cryptography.md). + +Although the layer is named for message routing, state certification is equally important: it underlies chain-evolution technology and allows nodes to catch up to the current state without replaying all historical blocks. + +## Message processing + +Whenever consensus produces a finalized block, it hands the block to message routing. This marks the transition between the lower and upper halves of the protocol stack: the lower two layers agree on a block, and the upper two layers process it deterministically. + +Message routing extracts [ingress messages](../../references/glossary.md#ingress-message) (submitted by users) and [XNet](../../references/glossary.md#xnet) messages (sent by canisters on other subnets) from the block. Each message is placed into the input queue of its target canister. This process is called **induction**, and all queues together are called the [**induction pool**](../../references/glossary.md#induction-pool). After induction, message routing triggers the execution layer, which schedules and executes messages from the pool. + +Message routing and execution modify subnet state in a deterministic way: every honest node makes the same state changes, preserving the replicated state machine properties of the subnet. + +## Inter-canister messaging + +Executing a canister message can produce new inter-canister messages. How those messages are handled depends on whether the target canister is on the same subnet or a different one. + +### Intra-subnet messages + +Messages to canisters on the same subnet do not go through consensus. Because they deterministically result from an already-agreed message, their execution is also deterministic. The execution layer places these messages directly into the target canister's input queue. This process is transitive: a message can produce more messages, forming a tree of execution. Intra-subnet messages are executed as long as the cycles limit for the round has not been exhausted. Remaining messages are deferred to subsequent rounds. + +Local canister-to-canister messaging is asynchronous. Messages are queued and scheduled rather than synchronously invoked, which is the standard inter-canister semantics on ICP. + +### Cross-subnet messages (XNet) + +Messages to canisters on other subnets are placed into the outgoing XNet stream for the target subnet. At the end of the round, message routing certifies these streams using a Merkle-tree-style data representation and chain-key cryptography. This means every outgoing XNet message is authenticated by the originating subnet's collective signature. + +Block makers on the receiving subnet fetch certified XNet messages during block assembly, validate the certificate against the originating subnet's public key, and include valid messages in a consensus block. The Merkle-tree structure allows partial consumption: a receiving subnet can include some XNet messages from a stream in one round and the rest in a later round, while still validating each message's authenticity. + +## State certification + +The replicated state of a subnet includes all information needed for its operation. Message routing certifies this state in two modes. + +### Per-round certification + +At the end of each round (when all messages have been executed or the cycles limit has been reached), message routing certifies a subset of the state tree: + +- Responses to ingress messages (the ingress history) +- XNet messages queued for other subnets +- Canister metadata (module hashes and certified variables) + +These certified responses can be read and validated against the subnet's public key by users. Each subnet's public key is in turn certified by the [Network Nervous System (NNS)](../../references/glossary.md#network-nervous-system-nns), so a certified response can be verified against a single root of trust: the NNS public key. This provides a powerful alternative to reading transaction logs, as responses are authenticated by the network rather than by a centralized server. + +Per-round state certification enables secure, verifiable inter-subnet communication, which is a core enabler of ICP's scalability across many subnets. + +### Per-checkpoint certification + +Not all state is certified every round. Canister Wasm code and written memory pages are certified only at checkpoints, which are periodic snapshots of the entire replicated state persisted to disk. + +Checkpoints are created roughly every 10 minutes. For each checkpoint, the subnet computes a certification over a Merkle-tree manifest. Certification is incremental: only the pages that changed since the last checkpoint need to be processed, and their changes are propagated up the tree. The root hash of the manifest is signed by the subnet, forming a [**catch-up package**](../../references/glossary.md#catch-up-package-cup) that new or recovering nodes can use to join without replaying the full block history. + +The time to compute a checkpoint certification is linear in the number of changed memory pages, not the total state size. This matters as subnets can hold terabytes of state: a full recertification of that volume at each checkpoint interval would be impractical. + +## Further reading + +- [Protocol Stack](index.md): how message routing fits into the four-layer architecture +- [State synchronization](state-synchronization.md): how catch-up packages are used by joining nodes + + diff --git a/docs/concepts/protocol/peer-to-peer.md b/docs/concepts/protocol/peer-to-peer.md new file mode 100644 index 00000000..869964d3 --- /dev/null +++ b/docs/concepts/protocol/peer-to-peer.md @@ -0,0 +1,33 @@ +--- +title: "Peer-to-peer layer" +description: "How ICP nodes broadcast artifacts and exchange protocol messages using the Abortable Broadcast primitive and QUIC transport." +sidebar: + order: 1 +--- + +The peer-to-peer (P2P) layer is the bottommost layer in the ICP protocol stack. It is responsible for secure and reliable communication between the nodes of a subnet, providing the foundation on which all higher protocol layers depend. + +P2P allows nodes to broadcast artifacts: user inputs to canisters and protocol messages such as block proposals. Its key property is guaranteed message delivery to all required subnet nodes despite varying real-world network conditions and node failures. The P2P layer is used by the [consensus layer](consensus.md) to broadcast artifacts to the other nodes in a subnet. + +## Abortable Broadcast + +At the heart of the P2P layer is the Abortable Broadcast primitive, which is critical for efficient communication in a setting where nodes may fail or act maliciously. With Abortable Broadcast, nodes can explicitly abort the transmission of artifacts they no longer need. This allows the protocol to provide strong delivery guarantees in the presence of network congestion, node or link failures, and backpressure. + +By preserving bandwidth and bounding the size of its data structures, Abortable Broadcast prevents overload from malicious nodes while ensuring delivery of non-aborted artifacts from honest nodes. It resembles a publish/subscribe model with the added ability to abort in-flight messages when needed. + +The P2P layer allows filtering of incoming artifacts: accepting only necessary ones while discarding or delaying others. Crucial artifacts are obtained more quickly than non-essential ones. This reduces the processing load of the layers above P2P. + +## QUIC transport + +The Abortable Broadcast implementation relies on a transport component built on top of [QUIC](https://en.wikipedia.org/wiki/QUIC): a custom RPC library that enables efficient orchestration of multiple higher-level protocols on the same replica. Key features include message multiplexing and caller pushback when packet consumption lags behind packet production. + +## Security + +To prevent denial-of-service attacks, nodes connect only with other nodes in the same subnet. Subnet membership is managed by the [Network Nervous System (NNS)](../../references/glossary.md#network-nervous-system-nns). The NNS registry canister acts as a service discovery mechanism for the P2P layer, enabling encrypted and authenticated communication between nodes through TLS. + +## Further reading + +- [Protocol Stack](index.md): how P2P fits into the four-layer architecture +- [Abortable Broadcast paper](https://arxiv.org/abs/2410.22080) + + diff --git a/docs/concepts/protocol/performance.md b/docs/concepts/protocol/performance.md new file mode 100644 index 00000000..cc194c02 --- /dev/null +++ b/docs/concepts/protocol/performance.md @@ -0,0 +1,123 @@ +--- +title: "Performance" +description: "Throughput, latency, and benchmark figures for ICP subnets: update calls, query calls, MIEPS, and mainnet measurements." +sidebar: + order: 6 +--- + +ICP is designed to run applications at web speed. This page explains the key performance metrics, how the protocol architecture determines them, and the figures measured on mainnet and in synthetic experiments. + +Performance numbers are point-in-time snapshots. Engineers maintaining this page should refresh mainnet figures using the [IC Dashboard APIs](../../references/ic-dashboard-api.md): the `daily_stats` endpoint for throughput and the `metrics` endpoint (`instruction-rate`) for MIEPS. Live network statistics are always available on the [IC dashboard](https://dashboard.internetcomputer.org). + +## Metrics + +Three metrics characterize ICP performance. + +**MIEPS (Millions of Instructions Executed Per Second)** measures raw compute throughput: how many Wasm instructions the network executes per second across all subnets, counting only replicated (update) execution. It is the primary indicator of useful work done by the protocol. A single subnet can execute up to 8 billion instructions per second; with 42 subnets, the theoretical network capacity is approximately 336,000 MIEPS. + +**Throughput** measures how many messages the network processes per second. It is reported separately for update calls (replicated, state-changing) and query calls (non-replicated, read-only), because the two execution modes have fundamentally different scalability properties. + +**Latency** is the time between submitting a call and receiving a response. For update calls this includes the consensus round; for query calls it is dominated by network round-trip time to a single node. + +## Update calls vs query calls + +The most important architectural performance distinction is between the two call types: + +**Update calls** go through consensus. Every node in the subnet executes the call, and the response is certified by the subnet's threshold signature. This guarantees correctness but means latency is bounded by consensus finality: roughly one to two seconds under normal conditions, longer on larger subnets. Update throughput is limited by the subnet's consensus capacity and scales by adding more subnets, not more nodes per subnet. + +**Query calls** bypass consensus. A single node executes the query and returns a result immediately. Latency is dominated by network round-trip time: typically 100–200ms. Because every node can serve queries concurrently and independently, query throughput scales linearly with subnet size. The tradeoff is trust: a single node produces the response, so query results are not subnet-certified unless the canister uses [certified variables](../../guides/backends/certified-variables.md). + +## Mainnet measurements + +The following figures were last measured on **July 1, 2025**. Each value links to the API call that produced it. + +| Metric | Value | Notes | +|--------|-------|-------| +| MIEPS (average) | [64,625](https://ic-api.internetcomputer.org/api/v3/metrics/instruction-rate?step=7200&start=1751328000&end=1751328000&format=json) | Replicated execution only; query calls excluded | +| MIEPS (all-time peak) | [249,524](https://ic-api.internetcomputer.org/api/v3/metrics/instruction-rate?step=7200&start=1736985600&end=1736985600&format=json) | Recorded January 16, 2025 | +| Update call throughput (daily average) | [1,076/s](https://ic-api.internetcomputer.org/api/v3/daily-stats?format=json&start=1751328000&end=1751328000) | | +| Query call throughput (daily average) | [4,023/s](https://ic-api.internetcomputer.org/api/v3/daily-stats?format=json&start=1751328000&end=1751328000) | | +| Update call throughput (all-time peak, 1 min) | [25,621/s](https://ic-api.internetcomputer.org/api/v3/daily-stats/max-update-transactions-per-sec-till-date?format=json&end=1751328000) | | +| Query call throughput (all-time peak, 1 min) | [19,598/s](https://ic-api.internetcomputer.org/api/v3/daily-stats/max-query-transactions-per-sec-till-date?format=json&end=1751328000) | Recorded July 9, 2024 | +| Update call latency (median, via HTTP gateway) | 1.75s | | +| Query call latency (median, via HTTP gateway) | 0.167s | | + +The chart below shows the latency distribution observed at HTTP gateways: + +![Latency distribution for ICP update and query calls, July 2025](/concepts/protocol/perf-latency-mainnet.png) + +Latency varies by subnet size because consensus requires agreement among more nodes on larger subnets: + +| Call type | Subnet | Median latency | +|-----------|--------|----------------| +| Update (counter canister) | Application subnet (13 nodes) | 1.35s | +| Update (ICP ledger transfer) | NNS subnet (40 nodes) | 2.23s | + +## Synthetic benchmarks + +Controlled experiments isolate execution performance from real-world network variability. These experiments use the counter canister (a minimal canister that increments a counter on every message) to measure raw protocol throughput without application overhead. The test subnet had 13 nodes, all in the same data center, with simulated 30ms RTT between nodes. + +### Throughput + +Results from experiments run in **June 2025**: + +| Scenario | Throughput | Notes | +|----------|-----------|-------| +| Update calls, mainnet parameters | 1,200/s (sustained) | Single 13-node test subnet | +| Update calls, tuned parameters | 2,000/s (sustained) | Reduced notary delay, optimized certification timer | +| Update calls (network-wide extrapolation) | 84,000/s | 42 subnets × 2,000/s | +| Query calls per node | 7,025/s | November 2023 experiment | +| Query calls (network-wide extrapolation) | 4,467,900/s | 636 nodes × 7,025/s | + +Tuned parameters include the notary delay, certification timer interval, the hashes-in-blocks optimization, and the in-memory response cache size. Mainnet uses conservative parameters to prioritize stability. + +Throughput is also measured in data volume: a single subnet can sustain approximately **7 MB/s**. See [Stellarator part 3](https://medium.com/dfinity/a-journey-into-stellarator-part-3-6f88881ae4bf) for the detailed analysis. + +### Latency under load + +Latency depends on load and parameter tuning. At throughput saturation, mainnet parameters produce higher latency than tuned parameters; under low load the difference is larger: + +| Parameters | Load | Median latency | +|-----------|------|----------------| +| Mainnet (conservative) | 1,200/s (saturation) | 2.27s | +| Tuned | 2,000/s (saturation) | 1.08s | +| Tuned | 1/s (low load) | 0.52s | + +The chart below shows how latency varies across the full throughput range for both parameter sets (June 2025): + +![Update call latency vs throughput for tuned and mainnet parameters, June 2025](/concepts/protocol/perf-latency-synthetic.png) + +The lower synthetic latencies compared to mainnet reflect the controlled setup: all 13 nodes in one data center with simulated 30ms RTT. On mainnet, inter-node RTT averages 125ms across the full network, which adds to consensus latency. + +## Node network latency + +ICP nodes communicate over the public IPv6 internet without dedicated links. The table below shows round-trip times in milliseconds between nodes in 12 data centers, measured in September 2023. The figures change slowly as network infrastructure matures and remain representative of the inter-regional pattern. + +| | Brussels | Chicago | Dallas | Fremont | Geneva | Ljubljana | Munich | Orlando | Singapore | Stockholm | Tokyo | Zurich | +|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| +| **Brussels** | | 102 | 121 | 143 | 17.65 | 27.4 | 18.35 | 106 | 167 | 36.6 | 223 | 16.07 | +| **Chicago** | 102 | | 24.6 | 59.05 | 118 | 130 | 110 | 49.4 | 249.5 | 117.5 | 152 | 121.5 | +| **Dallas** | 121 | 24.6 | | 53.8 | 132 | 137 | 127 | 37.05 | 276 | 131 | 139 | 129.5 | +| **Fremont** | 143 | 59.05 | 53.8 | | 145 | 156 | 145 | 67.7 | 191 | 161 | 109 | 147 | +| **Geneva** | 17.65 | 118 | 132 | 145 | | 26.95 | 17.9 | 112 | 257.5 | 38.3 | 248 | 16.05 | +| **Ljubljana** | 27.4 | 130 | 137 | 156 | 26.95 | | 17.55 | 123 | 258 | 42 | 235 | 22.1 | +| **Munich** | 18.35 | 110 | 127 | 145 | 17.9 | 17.55 | | 118 | 251 | 37.5 | 246 | 12.35 | +| **Orlando** | 106 | 49.4 | 37.05 | 67.7 | 112 | 123 | 118 | | 250 | 131 | 166 | 111 | +| **Singapore** | 167 | 249.5 | 276 | 191 | 257.5 | 258 | 251 | 250 | | 195.5 | 177 | 200.25 | +| **Stockholm** | 36.6 | 117.5 | 131 | 161 | 38.3 | 42 | 37.5 | 131 | 195.5 | | 260 | 36.9 | +| **Tokyo** | 223 | 152 | 139 | 109 | 248 | 235 | 246 | 166 | 177 | 260 | | 230 | +| **Zurich** | 16.07 | 121.5 | 129.5 | 147 | 16.05 | 22.1 | 12.35 | 111 | 200.25 | 36.9 | 230 | | + +European nodes communicate at 12–42ms RTT. Intercontinental pairs range from 102ms (Brussels–Chicago) to 276ms (Dallas–Singapore). The overall network median is approximately 125ms. + +Network latency is a floor for consensus latency: a consensus round requires multiple message exchanges between all nodes in a subnet. The Tokamak protocol optimizations ([blog post](https://medium.com/dfinity/tokamak-accelerating-the-internet-computer-update-call-lifecycle-f82517472709)) reduced median update call latency significantly by restructuring the consensus message exchange pattern. + +## Further reading + +- [Execution layer](execution.md): WebAssembly execution, DTS, and cycles accounting +- [Consensus](consensus.md): how blocks are proposed, notarized, and finalized +- [IC Dashboard APIs](../../references/ic-dashboard-api.md): REST APIs for querying live network metrics, throughput, and governance data +- [IC dashboard](https://dashboard.internetcomputer.org): live network statistics including per-subnet MIEPS and latency +- [Usenix ATC 2023 paper](https://www.usenix.org/system/files/atc23-arutyunyan.pdf): design and performance measurements of the ICP execution layer + + diff --git a/docs/concepts/protocol/state-synchronization.md b/docs/concepts/protocol/state-synchronization.md new file mode 100644 index 00000000..5e70bfde --- /dev/null +++ b/docs/concepts/protocol/state-synchronization.md @@ -0,0 +1,35 @@ +--- +title: "State synchronization" +description: "How ICP nodes join or re-join a subnet by downloading certified checkpoints instead of replaying the full block history." +sidebar: + order: 5 +--- + +State synchronization allows nodes to join a running subnet or recover from downtime without replaying every message ever executed. Instead, the protocol creates periodic certified checkpoints that capture a complete snapshot of the subnet state. A node that needs to catch up downloads a recent checkpoint and replays only the blocks produced since that checkpoint. + +Checkpoints are certified by the subnet through a signature over a Merkle-tree manifest (see [Message routing: per-checkpoint certification](message-routing.md#per-checkpoint-certification)). They are made available to other nodes via the [peer-to-peer layer](peer-to-peer.md) as part of a [**catch-up package**](../../references/glossary.md#catch-up-package-cup). + +## Joining nodes + +A new node downloads the latest catch-up package, validates it, and then downloads the corresponding state. This involves transferring potentially gigabytes to terabytes of data. The transfer is done efficiently and in parallel from multiple peers: the state is chunked, each chunk is authenticated individually through its hash in the manifest's Merkle tree, and different chunks can be downloaded from different peers simultaneously. This approach is similar to BitTorrent. + +Once the full checkpoint state is downloaded and authenticated, the node replays the blocks produced since that checkpoint to reach the current block height. + +Without state synchronization, joining a busy subnet would be impractical. A node would need to replay every block from the subnet's genesis, potentially amounting to years of CPU computation on a subnet that has been running with high utilization. State synchronization makes this feasible by limiting replay to only recent blocks. + +## Recovering nodes + +A node that was temporarily offline may still hold an older checkpoint. In this case, only the chunks that differ from its local checkpoint need to be downloaded, which can significantly reduce the volume of data transferred. + +The subnet state is organized as a Merkle tree and can reach up to a terabyte in size. A recovering node first requests the children of the root of the state tree from its peers. It then recursively downloads only the subtrees that differ from its local state, skipping the parts it already has. + +This incremental approach ensures that a recovering node transfers the minimum amount of data needed to rejoin the subnet, rather than downloading the full state again. + +![The catching-up replica only syncs the parts of the replicated state that differ from the up-to-date replica](/concepts/protocol/state-sync.webp) + +## Further reading + +- [Message routing](message-routing.md): how checkpoints and state certification work +- [Peer-to-peer](peer-to-peer.md): the broadcast layer used to transfer checkpoint chunks + + diff --git a/docs/concepts/security.md b/docs/concepts/security.md index ef23dff7..459040ee 100644 --- a/docs/concepts/security.md +++ b/docs/concepts/security.md @@ -1,8 +1,8 @@ --- -title: "Security Model" +title: "Security model" description: "The IC security model: canister isolation, trust boundaries, and the threat model for app developers" sidebar: - order: 12 + order: 13 --- The Internet Computer provides strong security guarantees at the protocol level: replicated execution, threshold cryptography, and deterministic state machines. But the protocol cannot prevent bugs in your code. Understanding where the platform's guarantees end and your responsibilities begin is essential for building secure apps. @@ -15,7 +15,7 @@ Canisters execute in two modes, each with different trust properties: **Update calls** go through consensus. Every node on the subnet executes the same code against the same state and must agree on the result. This makes update calls tamper-proof: a single malicious node cannot alter the outcome. The tradeoff is latency (~2 seconds). -**Query calls** run on a single replica. They are fast (~200ms) but the responding replica can return incorrect or fabricated results. Replica-signed queries provide partial mitigation (the replica signs its response), but for data that must be trustworthy, use [certified variables](../guides/backends/certified-variables.md) or update calls. Certified variables work by letting the canister set data that the subnet signs as part of the state tree: clients then verify the subnet's signature to confirm the response hasn't been tampered with. +**Query calls** run on a single replica. They are fast (~200ms) but the responding replica can return incorrect or fabricated results. Replica-signed queries provide partial mitigation (the replica signs its response), but for data that must be trustworthy, use [certified variables](../guides/backends/certified-variables.md) or update calls. Certified variables work by letting the canister set data that the subnet signs as part of the state tree: clients then verify the subnet's signature to confirm the response hasn't been tampered with. See [Certified data](certified-data.md) for how this mechanism works. This distinction is the most important security boundary on the IC. Any data returned by a query call that is not backed by a certificate should be treated as unverified. @@ -87,7 +87,7 @@ See [Upgrade safety](../guides/security/canister-upgrades.md) for patterns that ### Controller risk -Canister controllers can change the code, extract funds, or delete the canister at any time. If a single person or team controls a canister that holds user assets, users must trust that entity completely. For applications where this trust is unacceptable, control can be transferred to a DAO (such as an [SNS](../guides/governance/launching.md)) or the canister can be made immutable by removing all controllers. +Canister controllers can change the code, extract funds, or delete the canister at any time. If a single person or team controls a canister that holds user assets, users must trust that entity completely. For applications where this trust is unacceptable, control can be transferred to an [SNS](../guides/governance/launching.md) or the canister can be made immutable by removing all controllers. Users can verify a canister's controllers through the IC dashboard or by querying the canister's information via a `read_state` request. diff --git a/docs/concepts/sns-framework.md b/docs/concepts/sns-framework.md new file mode 100644 index 00000000..80c3ee06 --- /dev/null +++ b/docs/concepts/sns-framework.md @@ -0,0 +1,134 @@ +--- +title: "SNS framework" +description: "How the Service Nervous System works: framework architecture, launch process, neurons, proposals, and configurable rewards" +--- + +The Service Nervous System (SNS) is a governance framework built into ICP that lets any developer hand control of their application to a community-governed SNS. When an app is governed by an SNS, all upgrades, treasury decisions, and parameter changes require onchain proposals voted on by SNS asset holders. + +For a high-level introduction comparing the NNS and SNS, see [Governance](governance.md#the-service-nervous-system). + +## Framework architecture + +All SNS instances run code that the Network Nervous System (NNS) community has reviewed and approved. The NNS maintains a canister called the **SNS Wasm modules canister (SNS-W)**, `qaa6y-5yaaa-aaaaa-aaafa-cai`, which stores the approved Wasm binaries for each SNS canister. When a new SNS is created, SNS-W deploys the approved code. When NNS voters approve an improved SNS version, it is published to SNS-W and all existing SNS instances can upgrade to it. + +This shared codebase has two benefits. First, NNS voters review the code once and all SNS instances benefit. Second, users who have interacted with one SNS have a reliable intuition for how any other SNS works. + +**Upgrade paths:** An SNS community can upgrade its framework canisters in three ways: +- Submit a proposal to upgrade one step at a time along the NNS-approved upgrade path. +- Submit a proposal targeting a specific version, which automatically applies all intermediate steps in sequence. +- Enable `automatically_advance_target_version` in the SNS settings, causing the SNS to always follow the latest NNS-approved version without a proposal. This is enabled by default for newly launched SNS instances. + +**SNS subnet:** All SNS instances live on a dedicated SNS subnet (`x33ed-h457x-bsgyx-oqxqf-6pzwv-wkhzr-rm2j3-npodi-purzm-n66cg-gae`). Because every canister on that subnet runs NNS-approved SNS code, users can verify an SNS is legitimate simply by confirming it runs on the SNS subnet. + +## The launch process + +Launching an SNS is a one-time process that transfers control of an application from its original developers to a community. + +**Step 1: NNS proposal:** The developer submits a `CreateServiceNervousSystem` proposal to the NNS, specifying the initial digital asset distribution, decentralization swap parameters, initial governance settings, and the canisters to be governed. If the NNS community approves the proposal, the launch proceeds automatically. + +**Step 2: SNS canisters deployed:** The NNS uses SNS-W to deploy a fresh set of SNS canisters. The app's canisters are transferred to SNS Root as their controller. + +**Step 3: Decentralization swap:** A swap window opens where users can send ICP to the SNS Swap canister. At the end of the window (or earlier if the maximum is reached), each contributor receives a proportional share of a fixed SNS asset allocation as staked neurons. The ICP collected becomes the SNS treasury. All swap participants receive a basket of neurons with configurable dissolve delays. + +The swap has a minimum and maximum ICP threshold: +- If the minimum is not met when the window closes, the swap fails: all ICP is refunded and control of the app reverts to the original fallback controllers. +- If the maximum is reached before the window closes, the swap ends early. + +**Optional Neurons' Fund participation:** The launch proposal can request matched funding from the Neurons' Fund, which contributes ICP proportional to direct participation up to a cap. + +After a successful swap, the SNS is fully functional: the community governs the app through the governance canister and no single entity retains privileged control. + +## SNS canisters + +Each SNS consists of five core canisters and a variable number of archive canisters: + +| Canister | Purpose | +|---|---| +| **Governance** | Stores proposals and neurons; executes adopted proposals; calculates voting power and rewards. | +| **Ledger** | ICRC-1 ledger for the SNS's governance asset. | +| **Root** | Sole controller of the governed app canisters; orchestrates canister upgrades. | +| **Swap** | Runs the decentralization swap during launch. | +| **Index** | Organizes ledger transactions by account for wallet and explorer queries. | +| **Archive** (one or more) | Stores historical ledger blocks as the ledger grows. | + +## SNS neurons + +SNS neurons work similarly to NNS neurons, with a few differences: + +**All neurons are public.** Unlike NNS neurons, which can be private, all SNS neurons are fully readable by anyone. This makes vote delegation simpler: any neuron can follow any other. + +**Flexible permissions.** Instead of the NNS's controller/hotkey dichotomy, SNS neurons have a fine-grained permission system. Individual permissions (voting, changing following, managing principals, and others) can be granted to any principal independently. Frontends typically surface this as a simpler "add hotkey" interface, which maps to a specific set of permissions. + +**Configurable voting power.** Each SNS community configures the voting power calculation through its governance settings: +- Minimum dissolve delay to vote (default: 6 months). +- Maximum dissolve delay and the bonus it grants at that maximum (default: 8 years, 2x). +- Maximum age and the bonus it grants at that maximum (default: 4 years, 1.25x). + +**Maturity.** If an SNS activates voting rewards, neurons accumulate maturity that can be disbursed (minted as new assets), staked into the neuron for compounding, or auto-staked. The same maturity modulation mechanism as the NNS applies (±5% based on recent ICP/XDR rate movements). + +## SNS proposals + +SNS proposals follow the same lifecycle as NNS proposals (submission, voting, decision, automatic execution), with two notable differences: **proposal criticality** and **custom proposals**. + +### Critical and non-critical proposals + +SNS proposals are assigned to one of seven built-in topics. Each topic is classified as either critical or non-critical, and the classification determines the voting thresholds and period. + +**Critical topics** (require broader consensus): +| Topic | Description | +|---|---| +| Critical Dapp Operations | Adding or removing governed app canisters, executing critical app logic. | +| DAO Community Settings | Tokenomics and branding changes: token name, symbol, description. | +| Treasury & Asset Management | Moving treasury funds, managing liquidity pools, disbursing SNS-owned neurons. | + +Critical proposals pass only if at least 20% of total voting power votes yes and at least 67% of cast votes are yes. The voting period is 5–10 days (extended by wait-for-quiet for contested votes) and cannot be changed by SNS governance. + +**Non-critical topics** (standard thresholds): +| Topic | Description | +|---|---| +| Application Business Logic | Custom proposals specific to the governed app. | +| Dapp Canister Management | Upgrading registered app canisters and frontend assets. | +| Governance | Community polls with no immediate code effect. | +| SNS Framework Management | Upgrading and managing the SNS framework canisters. | + +Non-critical proposals pass if at least 3% of total voting power votes yes and a simple majority of cast votes is yes. The default voting period is 4–8 days and is configurable per SNS. + +### Built-in proposals + +All SNS instances include a standard set of built-in proposal types: +- Motion proposals for community polls. +- Proposals to change governance settings and SNS metadata. +- Proposals to upgrade the SNS framework canisters. +- Proposals to register or deregister governed app canisters. +- Proposals to transfer treasury funds or mint new assets. + +### Custom proposals + +Each SNS can register **custom proposals** (also called generic proposals) that call a specific method on a canister with specified arguments. This enables app-specific governance: an orchestrator canister upgrade, moderator election, or any other operation the SNS community should control. + +Custom proposals require a validation method: when a custom proposal is submitted, the governance canister calls the validator first, and only proceeds if it succeeds. Custom proposals must be registered through a governance proposal before they can be used, giving the community a chance to audit the function being added. Each custom proposal must be assigned a topic when registered. + +## SNS voting rewards + +Each SNS independently decides whether to enable voting rewards, and if so, what rate to use. The configurable parameters are: + +- **`initial_reward_rate_basis_points` (r\_max):** The starting annualized reward rate as a fraction of total supply. +- **`final_reward_rate_basis_points` (r\_min):** The floor rate after the transition period ends. Set to 0 to stop new issuance after `t_delta`. +- **`reward_rate_transition_duration_seconds` (t\_delta):** How long the transition from r\_max to r\_min takes. + +The formula between `t_start` and `t_start + t_delta` is: `R(t) = r_min + (r_max − r_min) × [(t_start + t_delta − t) / t_delta]²`. After `t_start + t_delta`, the rate is constant at `r_min`. + +![SNS voting rewards: new assets are distributed from the reward pool to voting neurons, while the total supply grows as rewards are distributed](/concepts/sns-framework/rewards-total-supply.png) + +If `VotingRewardsParameters` is not set at all, voting rewards are disabled. + +User rewards (distributing existing treasury assets to active app users) are a separate mechanism: an SNS-controlled canister holds an asset reserve and pays out rewards according to its own logic. + +## Next steps + +- [Governance](governance.md): NNS and SNS overview, including neurons, proposals, and voting rewards +- [SNS settings reference](../references/sns-settings.md): all configurable nervous system parameters +- [Launch an SNS](../guides/governance/launching.md): step-by-step guide to the decentralization process +- [Manage a live SNS](../guides/governance/managing.md): proposals, upgrades, and treasury management after launch + + diff --git a/docs/concepts/verifiable-randomness.md b/docs/concepts/verifiable-randomness.md index 2b801851..c02c92c1 100644 --- a/docs/concepts/verifiable-randomness.md +++ b/docs/concepts/verifiable-randomness.md @@ -1,5 +1,5 @@ --- -title: "Verifiable Randomness" +title: "Verifiable randomness" description: "How ICP generates unpredictable random numbers using a threshold Verifiable Random Function, with no trusted party required" sidebar: order: 7 @@ -7,9 +7,9 @@ sidebar: Generating unpredictable random numbers is a fundamental requirement for many applications: lotteries, games, fair selection, cryptographic protocols, and more. In a system where every node must agree on the same state, this is harder than it sounds. -## Why randomness is hard on deterministic consensus systems +## Why randomness is hard on deterministic consensus protocols -Consensus-based systems execute every transaction deterministically. Each node replays the same operations and must arrive at the same state. This means randomness sources available to normal programs (such as OS entropy (`/dev/urandom`), hardware timers, or per-process seeds) cannot be used directly: they would produce different values on each replica, breaking consensus. +Consensus-based protocols execute every transaction deterministically. Each node replays the same operations and must arrive at the same state. This means randomness sources available to normal programs (such as OS entropy (`/dev/urandom`), hardware timers, or per-process seeds) cannot be used directly: they would produce different values on each replica, breaking consensus. Naive alternatives have well-known weaknesses: diff --git a/docs/concepts/vetkeys.md b/docs/concepts/vetkeys.md index e27d660f..9a961716 100644 --- a/docs/concepts/vetkeys.md +++ b/docs/concepts/vetkeys.md @@ -2,7 +2,7 @@ title: "VetKeys" description: "Verifiable encrypted threshold key derivation for encryption and secret management on ICP" sidebar: - order: 11 + order: 12 --- VetKeys (verifiably encrypted threshold keys) give canisters the ability to derive secret key material on demand, without any node or canister ever seeing the raw key. The protocol that underpins this capability is called vetKD: verifiable encrypted threshold key derivation. diff --git a/docs/getting-started/choose-your-path.md b/docs/getting-started/choose-your-path.md index b7c5af0c..54271c73 100644 --- a/docs/getting-started/choose-your-path.md +++ b/docs/getting-started/choose-your-path.md @@ -1,5 +1,5 @@ --- -title: "Choose Your Path" +title: "Choose your path" description: "Choose your development path based on what you want to build" sidebar: order: 3 @@ -70,7 +70,7 @@ Here is how Ethereum concepts map to ICP: | Fee (user pays) | [Cycles](../concepts/cycles.md) (canister pays) | Users interact for free; developers fund computation | | No HTTP serving | Built-in HTTP serving | Canisters serve web pages directly | | Offchain storage (IPFS, etc.) | Onchain stable memory | Up to 500 GiB per canister, no external storage needed | -| Bridges / oracles | [Chain-key signing](../concepts/chain-fusion.md), [HTTPS outcalls](../guides/backends/https-outcalls.md) | Canisters sign transactions on other chains natively; HTTPS outcalls fetch external data without oracles | +| Bridges / oracles | [Chain-key signing](../concepts/chain-fusion/index.md), [HTTPS outcalls](../guides/backends/https-outcalls.md) | Canisters sign transactions on other chains natively; HTTPS outcalls fetch external data without oracles | | Immutable by default | Upgradeable by default | Canisters can be upgraded while preserving state | The biggest shift: on Ethereum, smart contracts are minimal programs that rely on offchain infrastructure. On ICP, a canister can be an entire application (frontend, backend, database, and scheduled jobs) all onchain. diff --git a/docs/getting-started/project-structure.mdx b/docs/getting-started/project-structure.mdx index 611846c1..efd3eb58 100644 --- a/docs/getting-started/project-structure.mdx +++ b/docs/getting-started/project-structure.mdx @@ -1,5 +1,5 @@ --- -title: "Project Structure" +title: "Project structure" description: "Understand icp.yaml, recipes, binding generation, and the .icp/ directory" sidebar: order: 2 diff --git a/docs/guides/ai-coding-agents.md b/docs/guides/ai-coding-agents.md index 6a6c0ced..7b458caa 100644 --- a/docs/guides/ai-coding-agents.md +++ b/docs/guides/ai-coding-agents.md @@ -1,5 +1,5 @@ --- -title: "AI Coding Agents" +title: "AI coding agents" description: "ICP skills are agent-readable instruction files that teach AI coding agents how to build correctly on the Internet Computer." --- diff --git a/docs/guides/authentication/verifiable-credentials.md b/docs/guides/authentication/verifiable-credentials.md index f41894a0..6030a78f 100644 --- a/docs/guides/authentication/verifiable-credentials.md +++ b/docs/guides/authentication/verifiable-credentials.md @@ -1,5 +1,5 @@ --- -title: "Verifiable Credentials" +title: "Verifiable credentials" description: "Issue and verify credentials on ICP using Internet Identity and the VC protocol: covers issuer and relying party integration patterns." sidebar: order: 2 diff --git a/docs/guides/backends/certified-variables.md b/docs/guides/backends/certified-variables.md index 2fafb614..da8e424f 100644 --- a/docs/guides/backends/certified-variables.md +++ b/docs/guides/backends/certified-variables.md @@ -1,5 +1,5 @@ --- -title: "Certified Variables" +title: "Certified variables" description: "Return verifiable query responses using Merkle trees and certified data" sidebar: order: 5 @@ -7,7 +7,7 @@ sidebar: Query calls on ICP are answered by a single replica without going through consensus. This means a malicious or faulty replica could return fabricated data. **Certified variables** solve this: the [canister](../../concepts/canisters.md) stores a hash in the [subnet's](../../concepts/network-overview.md#subnets) certified state during an update call, and query responses include a certificate signed by the subnet's threshold BLS key, proving the data is authentic. The result is responses that are both fast (no consensus delay) and cryptographically verified. -For a conceptual overview of why query integrity matters, see [Security concepts](../../concepts/security.md). +For a conceptual explanation of how certified data works and why it matters, see [Certified data](../../concepts/certified-data.md). For the security implications, see [Security concepts](../../concepts/security.md). ## How certification works @@ -364,4 +364,4 @@ See [Frontend certification](../../guides/frontends/certification.md) for the as - [IC Interface Specification: Certified Data](../../references/ic-interface-spec/canister-interface.md#system-api-certified-data): the certified data system API - [IC Interface Specification: Certification](../../references/ic-interface-spec/certification.md): certificate format and delegation - + diff --git a/docs/guides/backends/data-persistence.mdx b/docs/guides/backends/data-persistence.mdx index 564edc8d..43312ee2 100644 --- a/docs/guides/backends/data-persistence.mdx +++ b/docs/guides/backends/data-persistence.mdx @@ -1,5 +1,5 @@ --- -title: "Data Persistence" +title: "Data persistence" description: "Store and retrieve data in canisters using stable structures, persistent actors, and upgrade hooks" sidebar: order: 1 diff --git a/docs/guides/backends/https-outcalls.mdx b/docs/guides/backends/https-outcalls.mdx index 971ed7ce..7418e933 100644 --- a/docs/guides/backends/https-outcalls.mdx +++ b/docs/guides/backends/https-outcalls.mdx @@ -1,5 +1,5 @@ --- -title: "HTTPS Outcalls" +title: "HTTPS outcalls" description: "Make HTTP GET and POST requests from canisters to external web APIs" sidebar: order: 2 @@ -146,7 +146,7 @@ For reference, on a 13-node subnet: - Per request byte: 5,200 cycles - Per `max_response_bytes` byte: 10,400 cycles -See [Cycles Costs](../../references/cycles-costs.md#https-outcalls) for the full pricing table. +See [Cycles costs](../../references/cycles-costs.md#https-outcalls) for the full pricing table. ## Limitations and pitfalls @@ -166,6 +166,6 @@ Use the "Full example in ICP Ninja" links above to deploy and test directly in t - [Management canister reference](../../references/management-canister.md#http_request): full `http_request` parameter reference including all fields - [Exchange Rate Canister (XRC)](https://github.com/dfinity/exchange-rate-canister): a production service powered by HTTPS outcalls that fetches digital asset and fiat exchange rates - [Chain Fusion: Ethereum](../chain-fusion/ethereum.md): the EVM RPC canister uses HTTPS outcalls under the hood -- [Cycles Costs](../../references/cycles-costs.md#https-outcalls): outcall pricing details +- [Cycles costs](../../references/cycles-costs.md#https-outcalls): outcall pricing details {/* Upstream: informed by dfinity/portal docs/building-apps/network-features/using-http/https-outcalls/; dfinity/examples send_http_get, send_http_post */} diff --git a/docs/guides/backends/randomness.md b/docs/guides/backends/randomness.md index ec94e8f3..3d7a7dda 100644 --- a/docs/guides/backends/randomness.md +++ b/docs/guides/backends/randomness.md @@ -1,5 +1,5 @@ --- -title: "Verifiable Randomness" +title: "Verifiable randomness" description: "Generate cryptographically secure random numbers in canisters using the management canister's raw_rand API" sidebar: order: 4 diff --git a/docs/guides/canister-calls/calling-from-clients.md b/docs/guides/canister-calls/calling-from-clients.md index b08cf059..0d4888bd 100644 --- a/docs/guides/canister-calls/calling-from-clients.md +++ b/docs/guides/canister-calls/calling-from-clients.md @@ -1,5 +1,5 @@ --- -title: "Calling from Clients" +title: "Calling from clients" description: "Call canister functions from frontends, scripts, and backend services using IC agent libraries" sidebar: order: 4 diff --git a/docs/guides/canister-calls/candid.mdx b/docs/guides/canister-calls/candid.mdx index 94192c60..f89732a5 100644 --- a/docs/guides/canister-calls/candid.mdx +++ b/docs/guides/canister-calls/candid.mdx @@ -1,5 +1,5 @@ --- -title: "Candid Interface" +title: "Candid interface" description: "Define and use Candid interfaces for type-safe canister communication" sidebar: order: 1 diff --git a/docs/guides/canister-calls/inter-canister-calls.mdx b/docs/guides/canister-calls/inter-canister-calls.mdx index f2aab2df..575d4a71 100644 --- a/docs/guides/canister-calls/inter-canister-calls.mdx +++ b/docs/guides/canister-calls/inter-canister-calls.mdx @@ -1,5 +1,5 @@ --- -title: "Inter-canister Calls" +title: "Inter-canister calls" description: "Call functions on other canisters from your canister code" sidebar: order: 2 diff --git a/docs/guides/canister-calls/parallel-inter-canister-calls.mdx b/docs/guides/canister-calls/parallel-inter-canister-calls.mdx index c1ed2fc6..c96b15ae 100644 --- a/docs/guides/canister-calls/parallel-inter-canister-calls.mdx +++ b/docs/guides/canister-calls/parallel-inter-canister-calls.mdx @@ -1,5 +1,5 @@ --- -title: "Parallel Inter-canister Calls" +title: "Parallel inter-canister calls" description: "Execute multiple inter-canister calls concurrently to reduce latency, especially across subnets." sidebar: order: 3 diff --git a/docs/guides/canister-management/cycles-management.mdx b/docs/guides/canister-management/cycles-management.mdx index 71821bc3..129b20c2 100644 --- a/docs/guides/canister-management/cycles-management.mdx +++ b/docs/guides/canister-management/cycles-management.mdx @@ -1,5 +1,5 @@ --- -title: "Cycles Management" +title: "Cycles management" description: "Acquire cycles, monitor canister balances, set freezing thresholds, and deploy to mainnet." sidebar: order: 7 @@ -313,6 +313,87 @@ async fn top_up_canister(canister_id: Principal, amount: u128) { +## Calling canisters that require cycles + +Some canister methods expect cycles to be attached to the call itself. The [cycles ledger](../../concepts/cycles.md#cycles-ledger) cannot forward calls with cycles attached, so you need a different approach depending on whether you are calling from canister code or from the CLI. + +### From canister code + +Attach cycles to an inter-canister call using `Cycles.add` (Motoko) or `msg_cycles_add` (Rust). The called canister receives the cycles as part of the message context and accepts them with `Cycles.accept`: + + + + +```motoko +import Cycles "mo:core/Cycles"; + +persistent actor { + let target = actor ("rrkah-fqaaa-aaaaa-aaaaq-cai") : actor { + someMethod : () -> async (); + }; + + public func callWithCycles() : async () { + Cycles.add(500_000_000); + await target.someMethod(); + }; +} +``` + + + + +```rust +use ic_cdk::update; + +#[update] +async fn call_with_cycles() { + ic_cdk::api::call::msg_cycles_add(500_000_000u64); + let _: () = ic_cdk::call( + candid::Principal::from_text("rrkah-fqaaa-aaaaa-aaaaq-cai").unwrap(), + "someMethod", + (), + ) + .await + .expect("call failed"); +} +``` + + + + +The calling canister uses cycles from its own balance, not from the cycles ledger. Top up the calling canister first using `icp canister top-up` or `icp cycles mint`. + +### From the CLI or an agent + +The CLI cannot attach cycles directly to a canister call. Two approaches address this: + +**Top up the target canister first** (preferred when you control it): transfer cycles to the target canister using `icp canister top-up`, then call the method normally. The canister uses its own balance when the method runs. + +```bash +# Transfer 1T cycles to the target canister +icp canister top-up rrkah-fqaaa-aaaaa-aaaaq-cai --amount 1T -n ic + +# Then call the method as normal +icp canister call rrkah-fqaaa-aaaaa-aaaaq-cai someMethod '()' -n ic +``` + +**Proxy canister** (required when you need to attach cycles to a call and don't control the target): deploy a proxy canister that can forward calls with cycles attached. + +```bash +# Deploy the proxy canister using the provided template +icp new proxy --template proxy +cd proxy +icp deploy -e ic + +# Get the proxy canister ID +export PROXY_ID=$(icp canister status -e ic --id-only proxy) + +# Call any canister through the proxy with cycles attached +icp canister call --proxy "$PROXY_ID" rrkah-fqaaa-aaaaa-aaaaq-cai someMethod '()' -n ic +``` + +The proxy canister template is available at [icp-cli-templates/proxy](https://github.com/dfinity/icp-cli-templates/tree/main/proxy). It deploys the [proxy-canister](https://github.com/dfinity/proxy-canister), which is automatically provisioned on local networks but must be deployed manually on mainnet. + ## Multi-environment deployment For production, use separate environments for staging and production to avoid accidentally affecting live canisters. Configure environments in `icp.yaml`: @@ -412,7 +493,8 @@ icp canister top-up backend --amount 1T -n ic - [Canister settings](settings.md): Freezing threshold, memory allocation, compute allocation - [Canister lifecycle](lifecycle.md): Create, install, upgrade, and delete canisters - [Cycles costs reference](../../references/cycles-costs.md#cost-table): Exact cost tables per operation -- [Cycles](../../concepts/cycles.md): Why canisters pay for execution +- [Cycles](../../concepts/cycles.md): Why canisters pay for execution and how the cycles ledger works +- [Cycles ledger reference](../../references/system-canisters.md#cycles-ledger): Canister IDs and interface specification - [Reproducible builds](reproducible-builds.md): Verify your WASM is trustworthy before deploying - [icp-cli docs](https://cli.internetcomputer.org/0.2/reference/cli#icp-cycles): Full command reference for `icp cycles` and `icp canister top-up` diff --git a/docs/guides/canister-management/large-wasm.md b/docs/guides/canister-management/large-wasm.md index 9380ff03..b1e58983 100644 --- a/docs/guides/canister-management/large-wasm.md +++ b/docs/guides/canister-management/large-wasm.md @@ -1,5 +1,5 @@ --- -title: "Large Wasm Modules" +title: "Large Wasm modules" description: "Deploy canisters that exceed the 2 MiB Wasm limit using chunk store and compression" sidebar: order: 9 diff --git a/docs/guides/canister-management/lifecycle.mdx b/docs/guides/canister-management/lifecycle.mdx index aab923e0..e637c1c0 100644 --- a/docs/guides/canister-management/lifecycle.mdx +++ b/docs/guides/canister-management/lifecycle.mdx @@ -1,5 +1,5 @@ --- -title: "Canister Lifecycle" +title: "Canister lifecycle" description: "Create, deploy, upgrade, and delete canisters using icp-cli" sidebar: order: 1 diff --git a/docs/guides/canister-management/logs.md b/docs/guides/canister-management/logs.md index 1b24b691..ea2972b0 100644 --- a/docs/guides/canister-management/logs.md +++ b/docs/guides/canister-management/logs.md @@ -1,5 +1,5 @@ --- -title: "Canister Logs" +title: "Canister logs" description: "Debug and monitor canisters using the logging API, query statistics, and access log streaming" sidebar: order: 3 diff --git a/docs/guides/canister-management/optimization.md b/docs/guides/canister-management/optimization.md index f6d9777b..b3a7945e 100644 --- a/docs/guides/canister-management/optimization.md +++ b/docs/guides/canister-management/optimization.md @@ -1,5 +1,5 @@ --- -title: "Canister Optimization" +title: "Canister optimization" description: "Reduce Wasm binary size and improve canister performance with ic-wasm, SIMD, performance counters, and memory tuning" sidebar: order: 4 diff --git a/docs/guides/canister-management/reproducible-builds.md b/docs/guides/canister-management/reproducible-builds.md index 9052d044..c8ff89e1 100644 --- a/docs/guides/canister-management/reproducible-builds.md +++ b/docs/guides/canister-management/reproducible-builds.md @@ -1,5 +1,5 @@ --- -title: "Reproducible Builds" +title: "Reproducible builds" description: "Verify that deployed canister Wasm matches the source code using deterministic builds" sidebar: order: 6 diff --git a/docs/guides/canister-management/settings.mdx b/docs/guides/canister-management/settings.mdx index d1adaed5..79bdf837 100644 --- a/docs/guides/canister-management/settings.mdx +++ b/docs/guides/canister-management/settings.mdx @@ -1,5 +1,5 @@ --- -title: "Canister Settings" +title: "Canister settings" description: "Configure controllers, memory limits, freezing threshold, compute allocation, and other canister settings using icp-cli and icp.yaml" sidebar: order: 2 diff --git a/docs/guides/canister-management/snapshots.md b/docs/guides/canister-management/snapshots.md index 828f90c1..ab8002fb 100644 --- a/docs/guides/canister-management/snapshots.md +++ b/docs/guides/canister-management/snapshots.md @@ -1,5 +1,5 @@ --- -title: "Canister Snapshots" +title: "Canister snapshots" description: "Create, restore, and manage canister snapshots for backup and recovery" sidebar: order: 5 diff --git a/docs/guides/canister-management/subnet-selection.md b/docs/guides/canister-management/subnet-selection.md index e17c33a2..b1412c44 100644 --- a/docs/guides/canister-management/subnet-selection.md +++ b/docs/guides/canister-management/subnet-selection.md @@ -1,5 +1,5 @@ --- -title: "Subnet Selection" +title: "Subnet selection" description: "Choose the right subnet for your canister deployment based on geographic, security, and colocation requirements" sidebar: order: 8 diff --git a/docs/guides/chain-fusion/bitcoin.mdx b/docs/guides/chain-fusion/bitcoin.mdx index 8eaeb48b..047f2b51 100644 --- a/docs/guides/chain-fusion/bitcoin.mdx +++ b/docs/guides/chain-fusion/bitcoin.mdx @@ -1,5 +1,5 @@ --- -title: "Bitcoin Integration" +title: "Bitcoin integration" description: "Send and receive BTC from ICP canisters using ckBTC or the direct Bitcoin API" sidebar: order: 1 @@ -31,23 +31,7 @@ ckBTC is the recommended path for most developers. The ckBTC minter canister hol ### Deposit flow (BTC to ckBTC) -```plantuml -actor User -participant "ckBTC Minter" as Minter -participant "Bitcoin Checker" as KYT -participant "ckBTC Ledger" as Ledger -participant "Bitcoin Network" as BTC - -User -> Minter: get_btc_address(owner, subaccount) -Minter --> User: btc_address -User -> BTC: send BTC to btc_address -note right of BTC: 4 confirmations required -User -> Minter: update_balance(owner, subaccount) -Minter -> KYT: check UTXO -KYT --> Minter: ok -Minter -> Ledger: mint ckBTC (amount - kyt_fee) -Minter --> User: MintedUtxos -``` +For a flow diagram, see [Bitcoin integration](../../concepts/chain-fusion/bitcoin.md#converting-btc-to-ckbtc). 1. Call `get_btc_address` on the minter with the user's principal and subaccount. This returns a unique Bitcoin address controlled by the minter via threshold ECDSA. 2. Send BTC to that address from any Bitcoin wallet. @@ -245,24 +229,9 @@ async fn transfer(to: Principal, amount: Nat) -> Result { ### Withdraw (ckBTC to BTC) -```plantuml -actor User -participant "ckBTC Ledger" as Ledger -participant "ckBTC Minter" as Minter -participant "Bitcoin Checker" as KYT -participant "Bitcoin Network" as BTC - -User -> Ledger: icrc2_approve(spender=minter, amount) -User -> Minter: retrieve_btc_with_approval(btc_address, amount) -Minter -> KYT: check destination address -KYT --> Minter: ok -Minter -> Ledger: icrc2_transfer_from(user, minter, amount) -Minter --> User: block_index -note right of Minter: processed asynchronously -Minter -> BTC: submit signed transaction -``` +For a flow diagram, see [Bitcoin integration](../../concepts/chain-fusion/bitcoin.md#converting-ckbtc-to-btc). -Withdrawal is a two-step process: approve the minter to spend your ckBTC, then call `retrieve_btc_with_approval`. Before burning ckBTC, the minter runs a KYT check on the destination Bitcoin address. The Bitcoin transaction is submitted asynchronously — the minter batches pending requests to optimize miner fees. Track status with `retrieve_btc_status_v2(block_index)`. The minimum withdrawal is 50,000 satoshis (0.0005 BTC). +Withdrawal is a two-step process: approve the minter to spend your ckBTC, then call `retrieve_btc_with_approval`. Before burning ckBTC, the minter runs a KYT check on the destination Bitcoin address. The Bitcoin transaction is submitted asynchronously: the minter batches pending requests to optimize miner fees. Track status with `retrieve_btc_status_v2(block_index)`. The minimum withdrawal is 50,000 satoshis (0.0005 BTC). @@ -1172,12 +1141,12 @@ docker stop bitcoind && docker rm bitcoind ## Next steps -- [Chain fusion overview](../../concepts/chain-fusion.md): understand how ICP integrates with external blockchains +- [Chain fusion overview](../../concepts/chain-fusion/index.md): understand how ICP integrates with external blockchains - [Chain-key cryptography](../../concepts/chain-key-cryptography.md): learn how threshold ECDSA and Schnorr signatures work - [Chain-key tokens](../digital-assets/chain-key-tokens.md): explore ckBTC, ckETH, and other chain-key tokens - [Ethereum integration](ethereum.md): apply similar patterns for Ethereum - [Management canister reference](../../references/management-canister.md): full API reference for `sign_with_ecdsa`, `sign_with_schnorr`, and other management canister methods (note: the `bitcoin_*` methods in the management canister are deprecated; use the Bitcoin canister directly) - [Bitcoin canister API specification](https://github.com/dfinity/bitcoin-canister/blob/master/INTERFACE_SPECIFICATION.md): detailed API documentation -- [Bitcoin integration (Learn Hub)](https://learn.internetcomputer.org/hc/en-us/articles/34211154520084): protocol-level details of how ICP connects to Bitcoin +- [Bitcoin integration](../../concepts/chain-fusion/bitcoin.md): protocol-level details of how ICP connects to Bitcoin {/* Upstream: informed by dfinity/portal (docs/build-on-btc/*, docs/references/bitcoin-how-it-works.mdx, docs/references/cycles-cost-formulas.mdx); dfinity/icskills (skills/ckbtc/SKILL.md); dfinity/icp-cli-templates (bitcoin-starter/); dfinity/cdk-rs (ic-cdk-bitcoin-canister 0.2); dfinity/examples (rust/basic_bitcoin/src/common.rs, rust/basic_bitcoin/src/service/get_utxos.rs, rust/basic_bitcoin/src/service/get_blockchain_info.rs, rust/basic_bitcoin/basic_bitcoin.did, motoko/basic_bitcoin/src/basic_bitcoin/src/BitcoinApi.mo) */} diff --git a/docs/guides/chain-fusion/dogecoin.md b/docs/guides/chain-fusion/dogecoin.md index df73100d..e954819e 100644 --- a/docs/guides/chain-fusion/dogecoin.md +++ b/docs/guides/chain-fusion/dogecoin.md @@ -1,5 +1,5 @@ --- -title: "Dogecoin Integration" +title: "Dogecoin integration" description: "Send and receive DOGE from ICP canisters using the Dogecoin canister" sidebar: order: 4 @@ -34,7 +34,7 @@ For reading balances and UTXO state without sending a transaction, only steps 1 The Dogecoin canister exposes these methods: - `dogecoin_get_utxos`: returns unspent transaction outputs for a Dogecoin address -- `dogecoin_get_balance`: returns the balance of a Dogecoin address in koinus (1 DOGE = 100,000,000 koinus) +- `dogecoin_get_balance`: returns the balance of a Dogecoin address in koinu (1 DOGE = 100,000,000 koinu) - `dogecoin_get_current_fee_percentiles`: returns fee percentiles from recent Dogecoin transactions - `dogecoin_send_transaction`: submits a signed transaction to the Dogecoin network @@ -84,7 +84,7 @@ fn dogecoin_canister_id() -> Principal { Principal::from_text(DOGECOIN_CANISTER).expect("Invalid Dogecoin canister ID") } -/// Returns the balance of a Dogecoin address in koinus (1 DOGE = 100,000,000 koinus). +/// Returns the balance of a Dogecoin address in koinu (1 DOGE = 100,000,000 koinu). #[update] async fn get_dogecoin_balance(address: String, network: DogecoinNetwork) -> u64 { let (balance,): (u64,) = Call::unbounded_wait(dogecoin_canister_id(), "dogecoin_get_balance") @@ -120,7 +120,7 @@ The [Bitcoin integration guide](bitcoin.md) covers the same conceptual steps wit - Use the Dogecoin canister for UTXO queries and transaction submission (not the Bitcoin canister's `bitcoin_*` API) - Use Dogecoin's P2PKH address format (mainnet addresses start with `D`) -- Dogecoin uses koinus instead of satoshis (1 DOGE = 100,000,000 koinus) +- Dogecoin uses koinu instead of satoshis (1 DOGE = 100,000,000 koinu) - Dogecoin uses a different fee rate: use `dogecoin_get_current_fee_percentiles` to get current rates ## Relationship to Bitcoin integration @@ -149,38 +149,18 @@ ckDOGE is a 1:1 DOGE-backed token on ICP. The ckDOGE minter holds real DOGE and ### Deposit (DOGE to ckDOGE) -```plantuml -actor User -participant "ckDOGE Minter" as Minter -participant "Dogecoin Network" as DOGE - -User -> Minter: get_doge_address(account) -Minter --> User: doge_address -User -> DOGE: send DOGE to doge_address -User -> Minter: update_balance(account) -Minter --> User: ckDOGE minted to ICRC-1 account -``` +For a flow diagram, see [Dogecoin integration](../../concepts/chain-fusion/dogecoin.md#depositing-doge-doge-to-ckdoge). ### Withdrawal (ckDOGE to DOGE) -```plantuml -actor User -participant "ckDOGE Ledger" as Ledger -participant "ckDOGE Minter" as Minter -participant "Dogecoin Network" as DOGE - -User -> Ledger: icrc2_approve(spender=minter, amount) -User -> Minter: retrieve_doge_with_approval(doge_address, amount) -Minter -> Ledger: icrc2_transfer_from(user, minter, amount) -Minter -> DOGE: send DOGE to doge_address -``` +For a flow diagram, see [Dogecoin integration](../../concepts/chain-fusion/dogecoin.md#withdrawing-doge-ckdoge-to-doge). ## Next steps -- [Chain fusion overview](../../concepts/chain-fusion.md): understand how ICP integrates with external blockchains +- [Chain fusion overview](../../concepts/chain-fusion/index.md): understand how ICP integrates with external blockchains - [Bitcoin integration](bitcoin.md): the same UTXO-based integration with complete code examples - [Chain-key cryptography](../../concepts/chain-key-cryptography.md): how threshold ECDSA signatures work -- [Chain-key tokens](../digital-assets/chain-key-tokens.md): ckBTC, ckETH, and upcoming ckDOGE +- [Chain-key tokens](../digital-assets/chain-key-tokens.md): ckBTC, ckETH, and ckDOGE - [Build on Dogecoin book](https://dfinity.github.io/dogecoin-canister): full tutorial for building Dogecoin apps on ICP diff --git a/docs/guides/chain-fusion/ethereum.mdx b/docs/guides/chain-fusion/ethereum.mdx index 9014bda5..2264083c 100644 --- a/docs/guides/chain-fusion/ethereum.mdx +++ b/docs/guides/chain-fusion/ethereum.mdx @@ -1,5 +1,5 @@ --- -title: "Ethereum Integration" +title: "Ethereum integration" description: "Interact with Ethereum and EVM chains from ICP canisters via the EVM RPC canister" sidebar: order: 2 @@ -9,29 +9,11 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ICP canisters can read data from Ethereum and other EVM-compatible chains, sign transactions with threshold ECDSA, and submit them onchain: all without bridges, oracles, or external signers. This guide covers the EVM RPC canister, which handles JSON-RPC calls to Ethereum nodes on your behalf. -For a conceptual overview of how ICP connects to other blockchains, see [Chain Fusion](../../concepts/chain-fusion.md). +For a conceptual overview of how ICP connects to other blockchains, see [Chain Fusion](../../concepts/chain-fusion/index.md). ## How it works -The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) is a system canister deployed on ICP's 34-node fiduciary subnet. When your canister calls it: - -```plantuml -participant "Your Canister" as Canister -participant "EVM RPC Canister" as EVM -participant "Provider 1" as P1 -participant "Provider 2" as P2 -participant "Provider N" as PN - -Canister -> EVM: eth_getBlockByNumber(chain, args) + cycles -EVM -> P1: JSON-RPC (HTTPS outcall) -EVM -> P2: JSON-RPC (HTTPS outcall) -EVM -> PN: JSON-RPC (HTTPS outcall) -P1 --> EVM: response -P2 --> EVM: response -PN --> EVM: response -note right of EVM: consensus check (≥2/3 nodes agree) -EVM --> Canister: Consistent(result) + refund excess cycles -``` +The EVM RPC canister (`7hfb6-caaaa-aaaar-qadga-cai`) is a system canister deployed on ICP's 34-node fiduciary subnet. For a flow diagram, see [Ethereum integration](../../concepts/chain-fusion/ethereum.md#multi-provider-architecture). When your canister calls it: 1. Your canister sends a request to the EVM RPC canister with cycles attached. 2. The EVM RPC canister fans the request out to multiple RPC providers via [HTTPS outcalls](../backends/https-outcalls.md). @@ -603,7 +585,7 @@ Where `nodes` = 34 (fiduciary subnet) and `rpc_count` = number of providers quer **Practical guidance:** - Send 10,000,000,000 cycles (10B) as a starting budget. Unused cycles are refunded. -- Typical calls cost 100M--1B cycles (approximately $0.0001--$0.001 USD). +- Typical calls cost 100M to 1B cycles (approximately $0.0001 to $0.001 USD). - Use `requestCost` to get an exact estimate before making a raw JSON-RPC call. - The Candid-RPC methods (like `eth_getBlockByNumber`) automatically retry with larger response sizes if needed, consuming more cycles from your budget. @@ -719,7 +701,7 @@ ic-cdk = "0.20" - [Bitcoin integration](bitcoin.md): similar patterns for BTC using the Bitcoin API - [Chain-key tokens](../digital-assets/chain-key-tokens.md): learn about ckETH and other chain-key tokens backed 1:1 by native assets -- [Chain Fusion concepts](../../concepts/chain-fusion.md): understand how ICP connects to external blockchains +- [Chain Fusion concepts](../../concepts/chain-fusion/index.md): understand how ICP connects to external blockchains - [HTTPS outcalls](../backends/https-outcalls.md): the underlying mechanism the EVM RPC canister uses - [basic_ethereum example](https://github.com/dfinity/examples/tree/master/rust/basic_ethereum): complete end-to-end Rust example with address generation, signing, and transaction submission - [EVM RPC canister source](https://github.com/dfinity/evm-rpc-canister): canister source code and Candid interface diff --git a/docs/guides/chain-fusion/exchange-rates.mdx b/docs/guides/chain-fusion/exchange-rates.mdx new file mode 100644 index 00000000..a12fe55b --- /dev/null +++ b/docs/guides/chain-fusion/exchange-rates.mdx @@ -0,0 +1,255 @@ +--- +title: "Fetch exchange rates" +description: "Call the exchange rate canister from a Rust or Motoko canister to get cryptocurrency and fiat exchange rates" +sidebar: + order: 7 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +The [exchange rate canister (XRC)](../../concepts/chain-fusion/exchange-rate-canister.md) provides cryptocurrency and fiat exchange rates to other canisters. Because the XRC requires cycles attached to every call, you must call it from a canister that has cycles available; the CLI cannot attach cycles to a direct call. + +This guide shows how to call the XRC from Rust and Motoko, parse the scaled-integer response, and test from the CLI using the proxy canister pattern. + +## Call the XRC + +The XRC exposes a single method, `get_exchange_rate`, which takes a base asset, quote asset, and optional timestamp. Every call must include exactly **1 billion cycles**; unused cycles are refunded. + + + + +In Motoko, declare the XRC actor interface inline and use the `(with cycles = amount)` syntax to attach cycles. The Candid field `class` maps to `class_` in Motoko because `class` is a reserved keyword. + +```motoko +import Cycles "mo:core/Cycles"; +import Float "mo:core/Float"; +import Int "mo:core/Int"; +import Nat32 "mo:core/Nat32"; +import Nat64 "mo:core/Nat64"; + +type AssetClass = { #Cryptocurrency; #FiatCurrency }; +type Asset = { symbol : Text; class_ : AssetClass }; + +type GetExchangeRateRequest = { + base_asset : Asset; + quote_asset : Asset; + timestamp : ?Nat64; +}; + +type ExchangeRateMetadata = { + decimals : Nat32; + base_asset_num_received_rates : Nat64; + base_asset_num_queried_sources : Nat64; + quote_asset_num_received_rates : Nat64; + quote_asset_num_queried_sources : Nat64; + standard_deviation : Nat64; + forex_timestamp : ?Nat64; +}; + +type ExchangeRate = { + base_asset : Asset; + quote_asset : Asset; + timestamp : Nat64; + rate : Nat64; + metadata : ExchangeRateMetadata; +}; + +type ExchangeRateError = { + #AnonymousPrincipalNotAllowed; + #Pending; + #CryptoBaseAssetNotFound; + #CryptoQuoteAssetNotFound; + #StablecoinRateNotFound; + #StablecoinRateTooFewRates; + #StablecoinRateZeroRate; + #ForexInvalidTimestamp; + #ForexBaseAssetNotFound; + #ForexQuoteAssetNotFound; + #ForexAssetsNotFound; + #RateLimited; + #NotEnoughCycles; + #FailedToAcceptCycles; + #InconsistentRatesReceived; + #Other : { code : Nat32; description : Text }; +}; + +transient let xrc : actor { + get_exchange_rate : shared GetExchangeRateRequest -> async { + #Ok : ExchangeRate; + #Err : ExchangeRateError; + }; +} = actor "uf6dk-hyaaa-aaaaq-qaaaq-cai"; + +persistent actor { + + public func getRate(base : Text, quote : Text) : async ?Float { + let request : GetExchangeRateRequest = { + base_asset = { symbol = base; class_ = #Cryptocurrency }; + quote_asset = { symbol = quote; class_ = #FiatCurrency }; + timestamp = null; + }; + + let result = await (with cycles = 1_000_000_000) xrc.get_exchange_rate(request); + + switch result { + case (#Ok rate) { + let scale = Float.fromInt(Int.pow(10, Nat32.toNat(rate.metadata.decimals))); + ?(Float.fromInt(Nat64.toNat(rate.rate)) / scale) + }; + case (#Err err) { + // handle specific errors as needed (see Error handling section below) + null + }; + }; + }; +} +``` + + + + +Add `ic-xrc-types` to your `Cargo.toml`: + +```toml +[dependencies] +ic-cdk = "0.18" +ic-xrc-types = "1.2" +candid = "0.10" +``` + +Then use `Call::bounded_wait` with `.with_cycles` to attach the required cycles: + +```rust +use candid::Principal; +use ic_cdk::call::{Call, CallResult}; +use ic_xrc_types::{ + Asset, AssetClass, ExchangeRate, ExchangeRateError, GetExchangeRateRequest, +}; + +const XRC_CANISTER_ID: &str = "uf6dk-hyaaa-aaaaq-qaaaq-cai"; +const CYCLES_PER_REQUEST: u128 = 1_000_000_000; + +#[ic_cdk::update] +async fn get_rate(base: String, quote: String) -> Option { + let xrc = Principal::from_text(XRC_CANISTER_ID).unwrap(); + + let request = GetExchangeRateRequest { + base_asset: Asset { symbol: base, class: AssetClass::Cryptocurrency }, + quote_asset: Asset { symbol: quote, class: AssetClass::FiatCurrency }, + timestamp: None, + }; + + let result: CallResult<(Result,)> = + Call::bounded_wait(xrc, "get_exchange_rate") + .with_cycles(CYCLES_PER_REQUEST) + .with_arg(&request) + .await; + + match result { + Ok((Ok(rate),)) => { + let scale = 10f64.powi(rate.metadata.decimals as i32); + Some(rate.rate as f64 / scale) + } + Ok((Err(err),)) => { + ic_cdk::println!("XRC error: {:?}", err); + None + } + Err(e) => { + ic_cdk::println!("Call failed: {:?}", e); + None + } + } +} +``` + +The full example project, including `Cargo.toml` and project configuration, is at [dfinity/examples: rust/exchange-rates](https://github.com/dfinity/examples/tree/master/rust/exchange-rates). + + + + +## Reading the response + +The `rate` field is a scaled 64-bit integer. The `metadata.decimals` field tells you the scale factor: + +``` +human_readable_price = rate / 10^decimals +``` + +For example, if `rate = 8_523_450_000` and `decimals = 8`, the price is `85.2345`. + +The response also includes useful metadata: + +| Field | Description | +|---|---| +| `base_asset_num_queried_sources` | Number of exchanges queried for the base asset | +| `base_asset_num_received_rates` | Number of exchanges that responded with a valid rate | +| `standard_deviation` | Spread across received rates (scaled by `decimals`) | +| `forex_timestamp` | Timestamp of the forex data used, if a fiat asset was involved | + +A large gap between `num_queried_sources` and `num_received_rates` indicates that many exchanges were unavailable, which may affect rate quality. + +## Requesting historical rates + +Pass a Unix timestamp (in seconds) to request a rate for a past minute. Timestamps have 1-minute granularity; seconds within the minute are ignored. + +For reliability, use the start of the **previous minute** rather than the current minute, because some exchanges may not yet have published data for the current interval: + + + + +```motoko +let oneMinuteAgo : Nat64 = (Nat64.fromNat(Int.abs(Time.now())) / 1_000_000_000) - 60; + +let request : GetExchangeRateRequest = { + base_asset = { symbol = "ICP"; class_ = #Cryptocurrency }; + quote_asset = { symbol = "USD"; class_ = #FiatCurrency }; + timestamp = ?oneMinuteAgo; +}; +``` + + + + +```rust +use ic_cdk::api::time; + +let one_minute_ago = time() / 1_000_000_000 - 60; + +let request = GetExchangeRateRequest { + base_asset: Asset { symbol: "ICP".into(), class: AssetClass::Cryptocurrency }, + quote_asset: Asset { symbol: "USD".into(), class: AssetClass::FiatCurrency }, + timestamp: Some(one_minute_ago), +}; +``` + + + + +## Error handling + +The most important errors to handle explicitly: + +| Error | Cause | Action | +|---|---|---| +| `NotEnoughCycles` | Fewer than 1B cycles attached | Ensure the caller provides sufficient cycles | +| `Pending` | XRC is already retrieving a rate for this asset | Retry after a short delay | +| `RateLimited` | Too many concurrent requests from non-CMC callers | Retry with backoff | +| `CryptoBaseAssetNotFound` / `CryptoQuoteAssetNotFound` | Exchange returned no data for the asset | Check the symbol and try again | +| `InconsistentRatesReceived` | Rates across exchanges diverged too widely | The XRC refuses to return an unreliable rate; retry later | +| `ForexInvalidTimestamp` | Requested timestamp is outside the available forex window | Use a more recent timestamp | + +## Testing from the CLI + +The XRC requires cycles attached to the call, so you cannot call it directly from the CLI on mainnet. To test the integration from the terminal, use the [proxy canister pattern](../canister-management/cycles-management.md#calling-canisters-that-require-cycles): deploy a proxy canister that forwards the call with cycles attached. + +On a local replica, note that the XRC fetches from live external exchanges via HTTPS outcalls, so local testing requires a connection to the internet and a subnet configured as type `system`. + +## Next steps + +- [Exchange rate canister concept](../../concepts/chain-fusion/exchange-rate-canister.md): how median aggregation and rate derivation work +- [Exchange rate canister reference](../../references/protocol-canisters.md#exchange-rate-canister-xrc): full Candid interface, all error types, and data sources +- [Calling canisters that require cycles](../canister-management/cycles-management.md#calling-canisters-that-require-cycles): proxy canister pattern for CLI testing +- [HTTPS outcalls](../../concepts/https-outcalls.md): how the XRC fetches external price data +- [Full Rust example](https://github.com/dfinity/examples/tree/master/rust/exchange-rates): complete Rust project with build configuration + +{/* Upstream: informed by dfinity/examples (rust/exchange-rates/src/lib.rs); dfinity/exchange-rate-canister (src/xrc/xrc.did, INTERFACE_SPECIFICATION.md); dfinity/portal (docs/defi/fetching-exchange-rates.mdx, docs/references/system-canisters/xrc.mdx) */} diff --git a/docs/guides/chain-fusion/solana.mdx b/docs/guides/chain-fusion/solana.mdx index ad64fa5d..96fd141c 100644 --- a/docs/guides/chain-fusion/solana.mdx +++ b/docs/guides/chain-fusion/solana.mdx @@ -1,5 +1,5 @@ --- -title: "Solana Integration" +title: "Solana integration" description: "Interact with Solana from ICP canisters using the SOL RPC canister and threshold Ed25519 signatures" sidebar: order: 3 @@ -9,7 +9,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ICP canisters can interact directly with the Solana network: read account balances, query transaction history, and sign and submit transactions: all without bridges, oracles, or external signers. This guide covers the SOL RPC canister for querying Solana and threshold Ed25519 signatures for signing Solana transactions. -For a conceptual overview of how ICP connects to other blockchains, see [Chain Fusion](../../concepts/chain-fusion.md). +For a conceptual overview of how ICP connects to other blockchains, see [Chain Fusion](../../concepts/chain-fusion/index.md). ## How it works @@ -20,19 +20,7 @@ Two ICP features enable Solana integration: ## SOL RPC canister -The SOL RPC canister (`2xib7-jqaaa-aaaar-qai6q-cai`) is deployed on ICP mainnet and handles Solana JSON-RPC calls on your behalf. When your canister calls it: - -```plantuml -participant "Your Canister" as Canister -participant "SOL RPC Canister" as SolRpc -participant "Solana Providers" as Providers -participant "Solana" as SOL - -Canister -> SolRpc: request(json_rpc, max_response_bytes) + cycles -SolRpc -> Providers: HTTPS outcalls to multiple providers -Providers --> SolRpc: aggregated responses -SolRpc --> Canister: result + refund excess cycles -``` +The SOL RPC canister (`2xib7-jqaaa-aaaar-qai6q-cai`) is deployed on ICP mainnet and handles Solana JSON-RPC calls on your behalf. For a flow diagram, see [Solana integration](../../concepts/chain-fusion/solana.md#sol-rpc-canister). When your canister calls it: 1. Your canister sends a JSON-RPC request with cycles attached. 2. The SOL RPC canister fans the request out to multiple Solana RPC providers via HTTPS outcalls. @@ -42,11 +30,12 @@ SolRpc --> Canister: result + refund excess cycles No API keys are required. The SOL RPC canister is controlled by the [Network Nervous System](../../concepts/governance.md), so any change to it requires an NNS proposal. The SOL RPC canister contacts these JSON-RPC providers: -- [Helius](https://www.helius.dev/) - [Alchemy](https://www.alchemy.com/) - [Ankr](https://www.ankr.com/) +- [Chainstack](https://chainstack.com/) - [dRPC](https://drpc.org/) -- [Public Node](https://www.publicnode.com/) +- [Helius](https://www.helius.dev/) +- [PublicNode](https://www.publicnode.com/) ## Querying Solana @@ -346,39 +335,11 @@ ckSOL is a 1:1 SOL-backed token on ICP. The ckSOL minter holds real SOL via chai ### Deposit (SOL to ckSOL) -```plantuml -actor User -participant "ckSOL Minter" as Minter -participant "ckSOL Ledger" as Ledger -participant "SOL RPC Canister" as SolRpc -participant "Solana" as SOL - -User -> Minter: get_deposit_address(owner, subaccount) -Minter --> User: deposit_address -User -> SOL: transfer SOL to deposit_address -User -> Minter: process_deposit(owner, subaccount, tx_signature) -Minter -> SolRpc: fetch & verify transaction -Minter -> Ledger: mint ckSOL (amount - deposit_fee) -Minter --> User: Minted { block_index, minted_amount } -``` +For a flow diagram, see [Solana integration](../../concepts/chain-fusion/solana.md#depositing-sol-sol-to-cksol). ### Withdrawal (ckSOL to SOL) -```plantuml -actor User -participant "ckSOL Minter" as Minter -participant "ckSOL Ledger" as Ledger -participant "Solana" as SOL - -User -> Ledger: icrc2_approve(spender=minter, amount) -User -> Minter: withdraw(sol_address, amount) -Minter -> Ledger: burn via icrc2_transfer_from(user, amount) -Minter --> User: burn_block_index -note right of Minter: processed asynchronously -Minter -> SOL: submit SOL transfer (chain-key Ed25519) -User -> Minter: withdrawal_status(burn_block_index) -Minter --> User: TxFinalized -``` +For a flow diagram, see [Solana integration](../../concepts/chain-fusion/solana.md#withdrawing-sol-cksol-to-sol). ## Current status and limitations @@ -397,6 +358,6 @@ Follow the [SOL RPC canister repository](https://github.com/dfinity/sol-rpc-cani - [Bitcoin integration](bitcoin.md): direct protocol-level BTC integration - [Ethereum integration](ethereum.md): EVM RPC canister, similar JSON-RPC pattern - [HTTPS outcalls](../backends/https-outcalls.md): the mechanism underlying the SOL RPC canister -- [Chain Fusion concepts](../../concepts/chain-fusion.md): how ICP connects to other blockchains +- [Chain Fusion concepts](../../concepts/chain-fusion/index.md): how ICP connects to other blockchains {/* Upstream: informed by dfinity/portal (docs/building-apps/chain-fusion/solana/overview.mdx; dfinity/cdk-rs) ic-cdk/src/management_canister.rs, ic-management-canister-types/src/lib.rs; dfinity/examples: rust/basic_solana/README.md */} diff --git a/docs/guides/digital-assets/chain-key-tokens.mdx b/docs/guides/digital-assets/chain-key-tokens.mdx index 791f85ff..7f8f7d3e 100644 --- a/docs/guides/digital-assets/chain-key-tokens.mdx +++ b/docs/guides/digital-assets/chain-key-tokens.mdx @@ -1,5 +1,5 @@ --- -title: "Chain-Key Tokens" +title: "Chain-key tokens" description: "Deposit, withdraw, and transfer ckBTC, ckETH, ckERC20, ckDOGE, and ckSOL: ICP-native representations of external assets backed 1:1 with no bridges or custodians" sidebar: order: 2 diff --git a/docs/guides/digital-assets/wallet-integration.md b/docs/guides/digital-assets/wallet-integration.md index 7614b222..45e9357f 100644 --- a/docs/guides/digital-assets/wallet-integration.md +++ b/docs/guides/digital-assets/wallet-integration.md @@ -1,5 +1,5 @@ --- -title: "Wallet Integration" +title: "Wallet integration" description: "Integrate ICRC signer-standard wallets with your app using explicit per-action user approval." sidebar: order: 4 diff --git a/docs/guides/frontends/asset-canister.md b/docs/guides/frontends/asset-canister.md index 00ddcf57..5ec4a905 100644 --- a/docs/guides/frontends/asset-canister.md +++ b/docs/guides/frontends/asset-canister.md @@ -1,11 +1,11 @@ --- -title: "Asset Canister" +title: "Asset canister" description: "Deploy and serve frontend assets from an ICP canister with SPA routing, canister discovery, programmatic uploads, and security configuration" sidebar: order: 1 --- -The asset [canister](../../concepts/canisters.md) hosts static files (HTML, CSS, JavaScript, images) directly on the Internet Computer. It serves web frontends over HTTP, with responses certified by the [subnet](../../concepts/network-overview.md#subnets) so that HTTP gateways and browsers can verify that content was served tamperproof by the network rather than a centralized server. +The asset [canister](../../concepts/canisters.md) hosts static files (HTML, CSS, JavaScript, images) directly on the Internet Computer. It serves web frontends over HTTP, with responses certified by the [subnet](../../concepts/network-overview.md#subnets) so that [HTTP gateways](../../concepts/edge-infrastructure.md#http-gateways) and browsers can verify that content was served tamperproof by the network rather than a centralized server. This guide covers configuring the asset canister recipe in `icp.yaml`, deploying frontends, configuring SPA routing with `.ic-assets.json5`, connecting frontends to backend canisters, and uploading assets programmatically. diff --git a/docs/guides/frontends/certification.md b/docs/guides/frontends/certification.md index 65ddeaf3..f155d2f4 100644 --- a/docs/guides/frontends/certification.md +++ b/docs/guides/frontends/certification.md @@ -1,11 +1,11 @@ --- -title: "Response Certification" +title: "Response certification" description: "Verify that frontend responses are authentic and untampered using IC certificates" sidebar: order: 3 --- -Query responses on ICP are answered by a single replica without going through consensus. A malicious or faulty replica could return fabricated data. **Response certification** solves this: canisters commit a cryptographic hash to the subnet's certified state, and query responses include a certificate signed by the subnet's threshold BLS key. HTTP gateways (boundary nodes) verify every response automatically, so users are protected without any extra client-side code: as long as the canister certifies its responses. +Query responses on ICP are answered by a single replica without going through consensus. A malicious or faulty replica could return fabricated data. **Response certification** solves this: canisters commit a cryptographic hash to the subnet's certified state, and query responses include a certificate signed by the subnet's threshold BLS key. [HTTP gateways](../../concepts/edge-infrastructure.md#http-gateways) ([boundary nodes](../../concepts/edge-infrastructure.md#api-boundary-nodes)) verify every response automatically, so users are protected without any extra client-side code: as long as the canister certifies its responses. This guide explains how certification works at the HTTP layer, what the asset canister does automatically, when you need custom certification, and how to verify certificates client-side. diff --git a/docs/guides/frontends/custom-domains.md b/docs/guides/frontends/custom-domains.md index f0b9299f..a0da3875 100644 --- a/docs/guides/frontends/custom-domains.md +++ b/docs/guides/frontends/custom-domains.md @@ -1,5 +1,5 @@ --- -title: "Custom Domains" +title: "Custom domains" description: "Point a custom domain to your ICP-hosted frontend with DNS and boundary node configuration" sidebar: order: 2 diff --git a/docs/guides/frontends/frameworks.md b/docs/guides/frontends/frameworks.md index 06605c91..5874cc04 100644 --- a/docs/guides/frontends/frameworks.md +++ b/docs/guides/frontends/frameworks.md @@ -1,5 +1,5 @@ --- -title: "Frontend Frameworks" +title: "Frontend frameworks" description: "Integrate React, Vue, Svelte, Next.js, and game engines with ICP canisters using the asset canister and icp-cli" sidebar: order: 4 diff --git a/docs/guides/governance/managing.md b/docs/guides/governance/managing.md index 9a527df3..70a80f60 100644 --- a/docs/guides/governance/managing.md +++ b/docs/guides/governance/managing.md @@ -121,7 +121,7 @@ type NervousSystemParameters = record { }; ``` -For a description of each parameter and its effect, see the Learn Hub [DAO Settings](https://learn.internetcomputer.org/hc/en-us/articles/34142964565396) article. +For a description of each parameter and its effect, see the [SNS settings reference](../../references/sns-settings.md). ### ManageSnsMetadata @@ -617,7 +617,7 @@ Neurons are the staking units that give token holders voting power and a share o The SNS neuron staking flow is a two-step process: first transfer SNS tokens to the governance canister using the derived subaccount, then call `claim_or_refresh_neuron_from_account` on the SNS governance canister to claim the neuron. Note that this is distinct from NNS neuron staking, which uses NNS governance and the ICP ledger. -For information on neurons, dissolve delays, voting power bonuses, and reward mechanics, see the Learn Hub articles on [SNS Neurons](https://learn.internetcomputer.org/hc/en-us/articles/34084687583252) and [SNS Rewards](https://learn.internetcomputer.org/hc/en-us/articles/34143058069396). +For information on neurons, dissolve delays, voting power bonuses, and reward mechanics, see [SNS framework](../../concepts/sns-framework.md#sns-neurons). ### Querying neuron state diff --git a/docs/guides/governance/testing.md b/docs/guides/governance/testing.md index 66c559a3..a794e080 100644 --- a/docs/guides/governance/testing.md +++ b/docs/guides/governance/testing.md @@ -1,5 +1,5 @@ --- -title: "Testing SNS Governance" +title: "Testing SNS governance" description: "Test your SNS configuration locally and with a mainnet testflight before submitting the NNS proposal" sidebar: order: 2 diff --git a/docs/guides/index.md b/docs/guides/index.md index ff1a2f49..74eb053d 100644 --- a/docs/guides/index.md +++ b/docs/guides/index.md @@ -7,6 +7,8 @@ sidebar: Practical how-to guides organized by development stage. Each guide solves a specific task with working code. +## Tooling + - **[AI Coding Agents](ai-coding-agents.md)**: Use ICP skills to give AI coding agents accurate canister IDs and tested code patterns. ## Build @@ -25,5 +27,5 @@ Practical how-to guides organized by development stage. Each guide solves a spec ## Advanced features - **[Digital Assets](digital-assets/ledgers.md)**: Create and integrate with ledgers and wallets using digital asset standards. -- **[Chain Fusion](chain-fusion/bitcoin.md)**: Connect canisters to Bitcoin, Ethereum, and Solana and sign cross-chain transactions. +- **[Chain Fusion](chain-fusion/bitcoin.md)**: Connect canisters to Bitcoin, Ethereum, and Solana, sign cross-chain transactions, and fetch exchange rates. - **[Governance](governance/launching.md)**: Transfer control of your app to your community and govern it through proposals. diff --git a/docs/guides/security/access-management.mdx b/docs/guides/security/access-management.mdx index 8c756eba..8dc0b48f 100644 --- a/docs/guides/security/access-management.mdx +++ b/docs/guides/security/access-management.mdx @@ -1,5 +1,5 @@ --- -title: "Access Management" +title: "Access management" description: "Control who can call your canister with guards, caller checks, and controller management" sidebar: order: 1 diff --git a/docs/guides/security/canister-upgrades.md b/docs/guides/security/canister-upgrades.md index 7e8ba7a2..6753eff9 100644 --- a/docs/guides/security/canister-upgrades.md +++ b/docs/guides/security/canister-upgrades.md @@ -1,5 +1,5 @@ --- -title: "Secure Upgrades" +title: "Secure upgrades" description: "Upgrade canisters safely: pre/post hooks, stable memory, Candid compatibility, snapshot rollbacks, schema evolution, and testing" sidebar: order: 2 diff --git a/docs/guides/security/data-integrity.md b/docs/guides/security/data-integrity.md index ad7d37db..c0668273 100644 --- a/docs/guides/security/data-integrity.md +++ b/docs/guides/security/data-integrity.md @@ -1,5 +1,5 @@ --- -title: "Data Integrity" +title: "Data integrity" description: "Protect data confidentiality and authenticity in canisters using vetKeys encryption, identity-based encryption, certified variables, and signature verification." sidebar: order: 3 diff --git a/docs/guides/security/dos-prevention.md b/docs/guides/security/dos-prevention.md index 946284d7..7357eeb3 100644 --- a/docs/guides/security/dos-prevention.md +++ b/docs/guides/security/dos-prevention.md @@ -1,5 +1,5 @@ --- -title: "DoS Prevention" +title: "DoS prevention" description: "Protect canisters from denial-of-service attacks with rate limiting, cycle drain protection, and resource management" sidebar: order: 4 diff --git a/docs/guides/security/inter-canister-calls.md b/docs/guides/security/inter-canister-calls.md index 2f5414b2..9821d0cd 100644 --- a/docs/guides/security/inter-canister-calls.md +++ b/docs/guides/security/inter-canister-calls.md @@ -1,5 +1,5 @@ --- -title: "Inter-Canister Call Safety" +title: "Inter-canister call safety" description: "Handle reentrancy, callback traps, and async safety in inter-canister calls" sidebar: order: 5 diff --git a/docs/guides/testing/strategies.md b/docs/guides/testing/strategies.md index d417c1bf..23f86f60 100644 --- a/docs/guides/testing/strategies.md +++ b/docs/guides/testing/strategies.md @@ -1,5 +1,5 @@ --- -title: "Testing Strategies" +title: "Testing strategies" description: "Test canisters with unit tests, PocketIC integration tests, and benchmarking" sidebar: order: 1 diff --git a/docs/index.mdx b/docs/index.mdx index 8c662be2..2e485ee6 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -42,5 +42,5 @@ Teach your AI coding agent the patterns, APIs, and deployment workflows it needs - + diff --git a/docs/languages/rust/stable-structures.md b/docs/languages/rust/stable-structures.md index 4499d65f..4fbbf76c 100644 --- a/docs/languages/rust/stable-structures.md +++ b/docs/languages/rust/stable-structures.md @@ -1,5 +1,5 @@ --- -title: "Stable Structures" +title: "Stable structures" description: "Use StableBTreeMap, StableCell, StableLog, StableVec, and MemoryManager for upgrade-safe persistent storage in Rust canisters" sidebar: order: 2 diff --git a/docs/languages/rust/testing.md b/docs/languages/rust/testing.md index 2a9cc056..94f8e167 100644 --- a/docs/languages/rust/testing.md +++ b/docs/languages/rust/testing.md @@ -1,5 +1,5 @@ --- -title: "Testing Rust Canisters" +title: "Testing Rust canisters" description: "Unit and integration testing patterns for Rust canisters, including dependency injection, mocking, and PocketIC" sidebar: order: 3 diff --git a/docs/references/application-canisters.md b/docs/references/application-canisters.md index 86401afe..2a8d0a9c 100644 --- a/docs/references/application-canisters.md +++ b/docs/references/application-canisters.md @@ -1,5 +1,5 @@ --- -title: "Application Canisters" +title: "Application canisters" description: "Reference for the asset canister, SNS canisters, LLM canister, and other application-layer canisters with their interfaces and canister IDs" sidebar: order: 4 diff --git a/docs/references/candid-spec.md b/docs/references/candid-spec.md index c61faf42..36af45d5 100644 --- a/docs/references/candid-spec.md +++ b/docs/references/candid-spec.md @@ -1,5 +1,5 @@ --- -title: "Candid Type Reference" +title: "Candid type reference" description: "Complete reference for all Candid types: syntax, subtyping rules, and Motoko, Rust and JavaScript mappings" sidebar: order: 13 diff --git a/docs/references/chain-key-canister-ids.md b/docs/references/chain-key-canister-ids.md index 7cdf4747..2b591035 100644 --- a/docs/references/chain-key-canister-ids.md +++ b/docs/references/chain-key-canister-ids.md @@ -1,5 +1,5 @@ --- -title: "Chain-Key Token Canister IDs" +title: "Chain-key token canister IDs" description: "Mainnet and testnet canister IDs for all chain-key tokens: ckBTC, ckETH, ckERC20, ckDOGE, and ckSOL" sidebar: order: 7 diff --git a/docs/references/cycles-costs.md b/docs/references/cycles-costs.md index 38a3374a..6f958ec2 100644 --- a/docs/references/cycles-costs.md +++ b/docs/references/cycles-costs.md @@ -1,5 +1,5 @@ --- -title: "Cycles Costs" +title: "Cycles costs" description: "Exact cycle costs for compute, storage, HTTPS outcalls, signing, and canister operations" sidebar: order: 8 @@ -91,7 +91,7 @@ By default canisters are scheduled best-effort. Setting `compute_allocation` gua - **2%**: Scheduled every 50 rounds - **100%**: Scheduled every round -Total allocatable compute capacity per subnet is 299%. The per-second cost is `10M cycles * allocation_percent` on a 13-node subnet: see the *Compute allocation* row in the Cost table above for exact figures. +Total allocatable compute capacity per subnet is 299%. The per-second cost is `10M cycles * allocation_percent` on a 13-node subnet: see the *Compute allocation* row in the [Cost table](#cost-table) above for exact figures. ## Storage reservation diff --git a/docs/references/developer-tools.md b/docs/references/developer-tools.md index a2e1f816..b8774c00 100644 --- a/docs/references/developer-tools.md +++ b/docs/references/developer-tools.md @@ -1,5 +1,5 @@ --- -title: "Developer Tools" +title: "Developer tools" description: "Overview of the ICP developer toolchain: icp-cli, CDKs, JS SDK, PocketIC, and more" sidebar: hidden: true diff --git a/docs/references/digital-asset-standards.md b/docs/references/digital-asset-standards.md index cab577e4..efd77681 100644 --- a/docs/references/digital-asset-standards.md +++ b/docs/references/digital-asset-standards.md @@ -1,5 +1,5 @@ --- -title: "Digital Asset Standards" +title: "Digital asset standards" description: "ICP's ICRC standards for fungible assets, NFTs, and their extension protocols" sidebar: order: 6 diff --git a/docs/references/execution-errors.md b/docs/references/execution-errors.md index 4505f972..222e2485 100644 --- a/docs/references/execution-errors.md +++ b/docs/references/execution-errors.md @@ -1,5 +1,5 @@ --- -title: "Execution Errors" +title: "Execution errors" description: "Reference for canister execution errors on ICP: causes, example messages, and how to fix each error." sidebar: order: 10 diff --git a/docs/references/glossary.md b/docs/references/glossary.md index e456386d..70401f55 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -48,6 +48,10 @@ referred to as one **e8**. A **batch** is a collection of [messages](#message) whose order is agreed upon by [consensus](#consensus). +#### block maker + +A **block maker** is a [node](#node) selected by the [consensus](#consensus) protocol to propose a block in a given round. Block makers are chosen through a random permutation of [subnet](#subnet) nodes using randomness from the [random beacon](#random-beacon). The lowest-ranked node acts as the primary block maker; higher-ranked nodes step in if the primary fails to produce a notarized block within the timeout. + #### beneficiary The **beneficiary** of an [account](#account) is the [principal](#principal) who owns the [balance](#balance) of the account. The beneficiary of an @@ -164,15 +168,19 @@ single public key. This is a huge advantage as it allows any device, including smart watches and mobile phones, to verify the authenticity of artifacts from the Internet Computer. +#### ckBTC + +**ckBTC** (chain-key Bitcoin) is a fungible token on ICP backed 1:1 by BTC held by the [Bitcoin canister](../references/protocol-canisters.md#bitcoin-canisters). Depositing BTC to a generated custody address mints the equivalent amount of ckBTC. Transfers settle in 1–2 seconds at a 10 satoshi fee. ckBTC can be redeemed for the underlying BTC at any time. It is the recommended way to integrate Bitcoin value into ICP applications. See [chain-key tokens](../concepts/chain-fusion/chain-key-tokens.md) for the underlying architecture. + #### consensus -In distributed computing, **consensus** is a [fault-tolerant](https://learn.internetcomputer.org/hc/en-us/articles/34210647901460-Fault-Tolerance) mechanism by +In distributed computing, **consensus** is a [fault-tolerant](../concepts/evolution-scaling.md#fault-tolerance) mechanism by means of which a number of [nodes](#node) can reach agreement about a value or state. Consensus is a core component of the [replica](#replica) -software. The [consensus](https://learn.internetcomputer.org/hc/en-us/articles/34207558615956-Consensus) layer selects [messages](#message) -from the [peer-to-peer](https://learn.internetcomputer.org/hc/en-us/articles/34207428453140-Peer-to-peer) artifact pool and pulls messages from the +software. The [consensus](../concepts/protocol/consensus.md) layer selects [messages](#message) +from the [peer-to-peer](../concepts/protocol/peer-to-peer.md) artifact pool and pulls messages from the cross-network streams of other [subnets](#subnet) and organizes them into a [batch](#batch), which is delivered to the [message routing](#message-routing) layer. @@ -210,6 +218,10 @@ A **data center** (DC) is a physical site that hosts software infrastructure required for node deployment. Data centers are nodes that are selected and vetted by the [NNS](#network-nervous-system-nns). +#### Deterministic Time Slicing (DTS) + +**Deterministic Time Slicing** (DTS) is a mechanism in the [execution layer](../concepts/protocol/execution.md) that allows a long-running canister computation to span multiple [consensus](#consensus) rounds. Instead of timing out, a computation that exceeds the per-round instruction limit is paused at the end of a round and automatically resumed in the next. DTS is transparent to canisters and requires no special canister code. + #### dissolve delay The **dissolve delay** is the amount of time that @@ -261,7 +273,7 @@ The distinction between fiduciary and beneficiary is also important for canister #### governance canister -The **[governance](https://learn.internetcomputer.org/hc/en-us/articles/34574082263700-Tokenomics-Governance) canister** is a [system canister](#system-canister) that implements the +The **[governance](../concepts/governance.md#the-network-nervous-system) canister** is a [system canister](#system-canister) that implements the [NNS](#network-nervous-system-nns) governance system, i.e., among others, stores and manages [neurons](#neuron) and [proposals](#proposal), and implements the NNS @@ -286,6 +298,10 @@ The **ICP supply account** is a quasi-fictitious ledger central role in [ICP](#icp) [burning](#burning-transaction) and [minting](#minting-transaction) operations. +#### ICRC + +**ICRC** (Internet Computer Request for Comments) is the token and interface standard system for ICP, analogous to ERC standards on Ethereum. Standards are numbered sequentially: ICRC-1 defines the core fungible token interface (transfers and balance queries), ICRC-2 adds approval and transfer-from semantics, ICRC-3 standardizes the transaction log format. All DFINITY-maintained asset ledgers implement at least ICRC-1 and ICRC-2. See [digital asset standards](digital-asset-standards.md) for the full list. + #### identity An **identity** is a byte string that is used to identify an entity, @@ -345,6 +361,10 @@ in geographically distributed [data centers](#data-center). ## L +#### latency + +**Latency** is the time between submitting a call to a canister and receiving a response. Update call latency is bounded by consensus finality: typically 1–2 seconds on a 13-node subnet. Query call latency is dominated by network round-trip time to a single node: typically 100–200ms. See [Performance](../concepts/protocol/performance.md) for measured values. + #### ledger canister The **ledger canister** is a [system canister](#system-canister) whose main role is to store @@ -358,9 +378,13 @@ The **ledger canister** is a [system canister](#system-canister) whose main role A **message** is data sent from one [canister](#canister) to another or from a user to a canister. +#### MIEPS + +**MIEPS** (Millions of Instructions Executed Per Second) is the primary throughput metric for ICP compute capacity. It counts replicated Wasm instructions executed per second across all subnets, excluding query calls. A single subnet can execute up to 8 billion instructions per second (8,000 MIEPS). See [Performance](../concepts/protocol/performance.md) for measured network-wide values. + #### message routing -The **[message routing](https://learn.internetcomputer.org/hc/en-us/articles/34208241927316-Message-Routing)** layer receives [batches](#batch) from +The **[message routing](../concepts/protocol/message-routing.md)** layer receives [batches](#batch) from the [consensus](#consensus) layer and inducts them into the [induction pool](#induction-pool). Message routing then schedules a set of [canisters](#canister) to execute messages @@ -416,7 +440,7 @@ The NNS consists of a collection of [system canisters](#system-canister) (aka "N A **neuron** is an [ICP](#icp) entity that can make [proposals](#proposal) and vote on proposals related -to the [governance](https://learn.internetcomputer.org/hc/en-us/articles/34574082263700-Tokenomics-Governance) of the [Internet Computer](#internet-computer-protocol-icp). +to the [governance](../concepts/governance.md#the-network-nervous-system) of the [Internet Computer](#internet-computer-protocol-icp). To provide the stability required for responsible governance, neurons need to store ("stake") a certain amount of [ICP](#icp) in @@ -474,6 +498,10 @@ Node providers are selected and vetted by the [NNS](#network-nervous-system-nns) ## O +#### orthogonal persistence + +**Orthogonal persistence** is the storage model used by the ICP [execution layer](../concepts/protocol/execution.md). Canister memory pages are persisted to disk automatically after each round without requiring explicit read or write operations. Developers can treat canister state as always in memory; the runtime handles persistence transparently. See the [orthogonal persistence concept page](../concepts/orthogonal-persistence.md) for details. + #### output queue Each [canister](#canister) has an **output queue** of @@ -483,18 +511,18 @@ Each [canister](#canister) has an **output queue** of #### peer-to-peer (P2P) -In common usage, **[peer-to-peer](https://learn.internetcomputer.org/hc/en-us/articles/34207428453140-Peer-to-peer)** (P2P) computing or networking is a +In common usage, **[peer-to-peer](../concepts/protocol/peer-to-peer.md)** (P2P) computing or networking is a distributed application architecture that partitions workload across a network of equally privileged computer [nodes](#node) so that participants can contribute resources such as processing power, disk storage, or network bandwidth to handle application workload. -The **[peer-to-peer](https://learn.internetcomputer.org/hc/en-us/articles/34207428453140-Peer-to-peer) layer** collects and disseminates +The **[peer-to-peer](../concepts/protocol/peer-to-peer.md) layer** collects and disseminates [messages](#message) and artifacts from users and from other nodes. The [nodes](#node) of a [subnet](#subnet) form a -dedicated [peer-to-peer](https://learn.internetcomputer.org/hc/en-us/articles/34207428453140-Peer-to-peer) broadcast network that facilitates the secure +dedicated [peer-to-peer](../concepts/protocol/peer-to-peer.md) broadcast network that facilitates the secure **bounded-time/eventual delivery** broadcast of artifacts (such as [ingress messages](#ingress-message), control messages, and their signature shares). The [consensus](#consensus) layer @@ -502,11 +530,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 @@ -545,6 +569,10 @@ preserved. Queries are synchronous and can be made to any ## R +#### random beacon + +The **random beacon** is a source of cryptographic randomness produced each [consensus](#consensus) round using threshold BLS signatures. Every [subnet](#subnet) node contributes a signature share; when enough shares are combined, a verifiable random value is produced. The random beacon is used to select [block makers](#block-maker) and other randomized elements of the consensus protocol. + #### replica The **replica** an instance of software containing all the protocol components @@ -560,6 +588,10 @@ and accessed by all [subnet](#subnet) blockchains. ## S +#### stable memory + +**Stable memory** is a persistent memory region in each [canister](#canister) that survives Wasm module upgrades. Unlike heap memory, which is cleared when a new Wasm module is installed, stable memory is preserved across upgrades and is addressed through the system API. It is the recommended location for data that must persist long-term. See [orthogonal persistence](../concepts/orthogonal-persistence.md) for how Motoko manages this automatically, and [data persistence](../guides/backends/data-persistence.mdx) for Rust patterns. + #### state change A **state change** is the result of any function call or operation that changes the information stored in a [canister](#canister). For example, if a function makes an update call that adds two numbers together or removes a name from a list, the result is a change to the canister state. @@ -604,6 +636,14 @@ regular ledger [account](#account) (i.e., any ledger account except the [ICP supply account](#icp-supply-account)) to another regular ledger account. +#### throughput + +**Throughput** is the number of messages a subnet can process per second. It is measured separately for update calls (replicated, consensus-required) and [query calls](#query) (non-replicated, single-node). Update throughput is bounded by consensus capacity and scales by adding subnets. Query throughput scales linearly with the number of nodes in a subnet, since each node independently handles queries. See [Performance](../concepts/protocol/performance.md) for measured values. + +#### Trusted Execution Environment (TEE) + +A **Trusted Execution Environment** (TEE) is a hardware-enforced isolation mechanism that protects the memory and state of a virtual machine from the host operating system and hypervisor. ICP uses AMD SEV-SNP as its TEE technology on supported nodes, providing memory encryption, VM launch measurements, and attestation reports that allow external parties to verify the exact software a node is running. See [node infrastructure](../concepts/node-infrastructure.md#trusted-execution-environments) for how ICP uses TEEs in practice. + ## U #### user @@ -621,6 +661,10 @@ The **valid set rule** is the rule that determines a valid [induction pool](#ind to ensure that the valid set rule is upheld before they can be added to the induction pool. +#### vetKeys + +**VetKeys** (Verifiable Encrypted Threshold Keys) is a protocol that enables ICP to derive encrypted key material on demand and deliver it to authorized callers without any single node learning the plaintext key. It enables onchain encryption, identity-based encryption, and time-lock decryption without requiring trust in a single party. See [VetKeys](../concepts/vetkeys.md) for the full concept. + #### voting **Voting** is the process through which @@ -645,6 +689,10 @@ stack-based virtual machine. ## X +#### XNet + +**XNet** is the cross-subnet messaging stream used to deliver [messages](#message) between [canisters](#canister) on different [subnets](#subnet). XNet messages produced by the [execution layer](../concepts/protocol/execution.md) are certified by the originating subnet using [chain-key](#chain-key) cryptography and validated by [block makers](#block-maker) on the receiving subnet before being included in a block. + #### XDR **XDR** is the currency code for *special drawing rights (SDR)*. SDRs are supplementary foreign exchange assets that are defined and maintained by the International Monetary Fund (IMF). SDRs are not a currency themselves but represent a claim to a currency that is held by IMF member countries in which they may be exchanged. The ICP developer docs refer to currencies based on their currency codes, therefore SDRs are referenced as its currency code **XDR** in this documentation. diff --git a/docs/references/http-gateway-spec.md b/docs/references/http-gateway-spec.md index c67fe9f2..fd767094 100644 --- a/docs/references/http-gateway-spec.md +++ b/docs/references/http-gateway-spec.md @@ -1,10 +1,12 @@ --- -title: "HTTP Gateway Protocol Specification" +title: "HTTP gateway protocol specification" description: "The HTTP Gateway Protocol specification: how HTTP clients interact with the Internet Computer through canister-served HTTP responses" sidebar: order: 12 --- +See also: [Edge Infrastructure](../concepts/edge-infrastructure.md): conceptual overview of API boundary nodes, HTTP gateways, and asset certification. + ## Introduction The HTTP Gateway Protocol is an extension of the Internet Computer Protocol that allows conventional HTTP clients to interact with the Internet Computer network. This is important for software such as web browsers to be able to fetch and render client-side canister code, including HTML, CSS, and JavaScript as well as other static assets such as images or videos. The HTTP Gateway does this by translating between standard HTTP requests and [API canister calls](./ic-interface-spec/https-interface.md#http-interface) that the Internet Computer Protocol will understand. diff --git a/docs/references/ic-dashboard-api.md b/docs/references/ic-dashboard-api.md new file mode 100644 index 00000000..67cd7610 --- /dev/null +++ b/docs/references/ic-dashboard-api.md @@ -0,0 +1,112 @@ +--- +title: "IC dashboard APIs" +description: "Five public REST APIs for querying ICP network state: metrics, governance, ICRC tokens, ICP ledger, and SNS data." +sidebar: + order: 16 +--- + +The Internet Computer exposes five public REST APIs for querying live network state. All are read-only and require no authentication. Each has its own subdomain, versioned base path, and Swagger UI for interactive exploration. + +| API | Base URL | Swagger / Docs | +|-----|----------|----------------| +| IC API | `https://ic-api.internetcomputer.org/api/v3/` | [swagger](https://ic-api.internetcomputer.org/api/v3/swagger) | +| Metrics API | `https://metrics-api.internetcomputer.org/api/v1/` | [docs](https://metrics-api.internetcomputer.org/api/v1/docs) | +| ICRC API | `https://icrc-api.internetcomputer.org/api/v1/` | [docs](https://icrc-api.internetcomputer.org/docs) | +| Ledger API | `https://ledger-api.internetcomputer.org/api/v1/` | [swagger](https://ledger-api.internetcomputer.org/swagger-ui/) | +| SNS API | `https://sns-api.internetcomputer.org/api/v1/` | [docs](https://sns-api.internetcomputer.org/docs) | + +## IC API + +**`https://ic-api.internetcomputer.org/api/v3/`**: general network data across 40 endpoint groups. + +| Group | What it returns | +|-------|----------------| +| `metrics` | Prometheus metrics: instruction rate, node count, cycle burn rate, block rate, total subnets, registered canisters, neuron counts, community fund, energy consumption, and more | +| `daily_stats` | Daily aggregate throughput: update calls/s, query calls/s, message counts | +| `subnets` / `subnets v4` | Subnet list, subnet details, replica versions per subnet | +| `nodes` / `node_providers` | Node list with data center and operator, node provider details | +| `data_centers` | Data center locations and node counts | +| `boundary-node-locations` | Boundary node geographic distribution | +| `canisters` / `canisters v4` | Deployed canisters, canister details by ID | +| `neurons` / `neuron_voting_powers` | Neuron details, voting power, maturity modulation | +| `governance_metrics` | Aggregate governance statistics | +| `proposals` / `proposals_over_time` | Proposal list, participation rates, tallies, deadline extensions | +| `icp_xdr_conversion_rates` / `icp_usd_rate` | ICP token price and conversion rates | +| `bitcoin` | Bitcoin integration metrics | +| `block_heights` / `block_heights_over_time` | Block production data | +| `images` | Generated images for proposals, canisters, neurons, nodes, and more | + +Full endpoint reference: [ic-api.internetcomputer.org/api/v3/swagger](https://ic-api.internetcomputer.org/api/v3/swagger) + +## Metrics API + +**`https://metrics-api.internetcomputer.org/api/v1/`**: time-series metrics, organized by topic. + +| Group | What it returns | +|-------|----------------| +| `IC` | General ICP metrics: cycle burn rate, transaction rate | +| `Instructions` | Instruction execution rate over time | +| `Transactions` | Transaction counts and rates | +| `Blocks` | Block production metrics | +| `Governance` | Total voting power over time | +| `Conversion Rates` | ICP/XDR conversion rate history | +| `Bitcoin` | Bitcoin integration metrics over time | +| `Boundary Nodes` | Boundary node count over time | +| `Internet Identity` | Internet Identity user count over time | +| `Canisters` | Canister count over time | +| `Energy Consumption` | Network energy usage | +| `Trustworthy Metrics` | Certified block total metrics | + +Full endpoint reference: [metrics-api.internetcomputer.org/api/v1/docs](https://metrics-api.internetcomputer.org/api/v1/docs) + +## ICRC API + +**`https://icrc-api.internetcomputer.org/api/v1/`**: data for any ICRC-standard token. Requires the token's ledger canister ID as a path parameter. + +| Group | What it returns | +|-------|----------------| +| `accounts` | Accounts holding a token, account owner lookup | +| `transactions` | Transaction history, transaction details, transaction count and volume | +| `circulating-supply` | Circulating supply, supply values over time | +| `holders` | Account holders list | +| `total-supply` | Total token supply | +| `blocks` | Ledger blocks, block details | +| `ledgers` | Ledger list, ledger metadata | +| `token_values` | Token value data | +| `total-burned-per-day` | Daily burn totals | +| `total-new-accounts-per-day` | Daily new account creation | +| `transaction-count` / `transaction-volume` | Aggregate transaction metrics | +| `images` | Graph images for ledger, transactions, and accounts | + +Full endpoint reference: [icrc-api.internetcomputer.org/docs](https://icrc-api.internetcomputer.org/docs) + +## Ledger API + +**`https://ledger-api.internetcomputer.org/api/v1/`**: data for the ICP ledger specifically. For other ICRC tokens, use the [ICRC API](#icrc-api) instead. + +| Group | What it returns | +|-------|----------------| +| `Accounts` | Accounts that have made transactions, account balance history, transaction history per account | +| `Transactions` | Transaction history, transaction details, daily transaction counts | +| `Total & Circulating Supplies` | Total ICP supply, circulating supply, supply over time | +| `ICP Burned` | Total ICP burned | +| `Metrics` | Transaction volume metrics, unique accounts per day | + +Full endpoint reference: [ledger-api.internetcomputer.org/swagger-ui/](https://ledger-api.internetcomputer.org/swagger-ui/) + +## SNS API + +**`https://sns-api.internetcomputer.org/api/v1/`**: data for all SNS instances deployed on ICP. + +| Group | What it returns | +|-------|----------------| +| `snses` | List of all deployed SNSes | +| `neurons` | Neuron list for an SNS, neuron details, neuron count | +| `proposals` | Proposals for an SNS, proposal details, proposal count | +| `statistics` | SNS statistics | +| `healthchecks` | SNS health status | +| `images` | Generated images for SNS neurons, proposals | + +Full endpoint reference: [sns-api.internetcomputer.org/docs](https://sns-api.internetcomputer.org/docs) + + diff --git a/docs/references/ic-interface-spec/abstract-behavior.md b/docs/references/ic-interface-spec/abstract-behavior.md index 820a44af..fc268f0f 100644 --- a/docs/references/ic-interface-spec/abstract-behavior.md +++ b/docs/references/ic-interface-spec/abstract-behavior.md @@ -1,5 +1,5 @@ --- -title: "Abstract Behavior" +title: "Abstract behavior" description: "Formal specification of the Internet Computer abstract state machine and execution semantics" sidebar: label: "Abstract Behavior" diff --git a/docs/references/ic-interface-spec/canister-interface.md b/docs/references/ic-interface-spec/canister-interface.md index 52c49ce0..0db58772 100644 --- a/docs/references/ic-interface-spec/canister-interface.md +++ b/docs/references/ic-interface-spec/canister-interface.md @@ -1,5 +1,5 @@ --- -title: "Canister Interface (System API)" +title: "Canister interface (system API)" description: "WebAssembly module format and the System API available to canisters at runtime" sidebar: label: "Canister Interface" diff --git a/docs/references/ic-interface-spec/changelog.md b/docs/references/ic-interface-spec/changelog.md index 284abb97..1787f629 100644 --- a/docs/references/ic-interface-spec/changelog.md +++ b/docs/references/ic-interface-spec/changelog.md @@ -1,5 +1,5 @@ --- -title: "IC Interface Spec Changelog" +title: "IC interface spec changelog" description: "Version history and changes to the IC Interface Specification" sidebar: label: "Changelog" diff --git a/docs/references/ic-interface-spec/https-interface.md b/docs/references/ic-interface-spec/https-interface.md index 544a2771..f8742886 100644 --- a/docs/references/ic-interface-spec/https-interface.md +++ b/docs/references/ic-interface-spec/https-interface.md @@ -1,5 +1,5 @@ --- -title: "HTTPS Interface" +title: "HTTPS interface" description: "HTTP endpoints for submitting calls, reading state, and querying canisters on the Internet Computer" sidebar: label: "HTTPS Interface" diff --git a/docs/references/ic-interface-spec/index.md b/docs/references/ic-interface-spec/index.md index feaeaed7..d4e23614 100644 --- a/docs/references/ic-interface-spec/index.md +++ b/docs/references/ic-interface-spec/index.md @@ -1,5 +1,5 @@ --- -title: "IC Interface Specification" +title: "IC interface specification" description: "Introduction, pervasive concepts, and the IC system state tree" sidebar: label: "Introduction" diff --git a/docs/references/ic-interface-spec/management-canister.md b/docs/references/ic-interface-spec/management-canister.md index a221dee2..e4b60b42 100644 --- a/docs/references/ic-interface-spec/management-canister.md +++ b/docs/references/ic-interface-spec/management-canister.md @@ -1,5 +1,5 @@ --- -title: "IC Management Canister" +title: "IC management canister" description: "The virtual management canister interface: canister lifecycle, threshold signing, Bitcoin, and provisional APIs" sidebar: label: "Management Canister" diff --git a/docs/references/icrc-standards.md b/docs/references/icrc-standards.md index d03dc5c7..502c67b1 100644 --- a/docs/references/icrc-standards.md +++ b/docs/references/icrc-standards.md @@ -1,5 +1,5 @@ --- -title: "ICRC Standards" +title: "ICRC standards" description: "Index of all adopted ICRC standards on ICP, grouped by category" sidebar: order: 5 diff --git a/docs/references/index.md b/docs/references/index.md index 05c2b166..7377136f 100644 --- a/docs/references/index.md +++ b/docs/references/index.md @@ -23,7 +23,7 @@ Technical reference material for ICP development. These pages cover exact specif - **[ICRC Standards](icrc-standards.md)**: Index of all adopted ICRC standards grouped by category. - **[Digital Asset Standards](digital-asset-standards.md)**: ICRC-1, ICRC-2, ICRC-3, ICRC-7, and ICRC-37 in full detail. - **[Chain-Key Token Canister IDs](chain-key-canister-ids.md)**: Mainnet and testnet canister IDs for ckBTC, ckETH, ckERC20, ckDOGE, and ckSOL. -- **[Cycles Costs](cycles-costs.md)**: Exact cycle costs for compute, storage, HTTPS outcalls, signing, and canister operations. +- **[Cycles costs](cycles-costs.md)**: Exact cycle costs for compute, storage, HTTPS outcalls, signing, and canister operations. - **[Subnet Types](subnet-types.md)**: All subnet types with node counts, replication factors, and cycle cost multipliers. ## Errors and debugging @@ -37,6 +37,15 @@ Technical reference material for ICP development. These pages cover exact specif - **[Candid Specification](candid-spec.md)**: The Candid interface description language: type system, encoding, and subtyping rules. - **[Internet Identity Specification](internet-identity-spec.md)**: Delegation chains, passkey management, and canister signatures. -## Other +## Governance + +- **[NNS Proposal Types](nns-proposal-types.md)**: All NNS proposal topics and their proposal types, with descriptions of what each type does on adoption. +- **[SNS Settings](sns-settings.md)**: Reference for all SNS nervous system parameters: voting power, governance rules, asset economics, and reward behavior. + +## Network observability + +- **[IC Dashboard APIs](ic-dashboard-api.md)**: Five public REST APIs for querying live network state: metrics, governance, ICRC tokens, ICP ledger, and SNS data. + +## Terminology - **[Glossary](glossary.md)**: Definitions of ICP-specific terms: canister, cycle, principal, subnet, and more. diff --git a/docs/references/internet-identity-spec.md b/docs/references/internet-identity-spec.md index 0396f342..5e8f4987 100644 --- a/docs/references/internet-identity-spec.md +++ b/docs/references/internet-identity-spec.md @@ -1,5 +1,5 @@ --- -title: "Internet Identity Specification" +title: "Internet Identity specification" description: "The Internet Identity specification: identity design, client authentication protocol, delegation chain, and backend Candid interface" sidebar: order: 14 diff --git a/docs/references/management-canister.md b/docs/references/management-canister.md index 09c99159..77bcec7e 100644 --- a/docs/references/management-canister.md +++ b/docs/references/management-canister.md @@ -1,5 +1,5 @@ --- -title: "Management Canister" +title: "Management canister" description: "API reference for the IC management canister (aaaaa-aa): canister lifecycle, signing, randomness, and more" sidebar: order: 1 diff --git a/docs/references/nns-proposal-types.md b/docs/references/nns-proposal-types.md new file mode 100644 index 00000000..4101c382 --- /dev/null +++ b/docs/references/nns-proposal-types.md @@ -0,0 +1,165 @@ +--- +title: "NNS proposal types" +description: "All NNS proposal topics and their proposal types, with descriptions" +--- + +Network Nervous System (NNS) proposals are grouped into topics that determine their reward weight, voting period, and how neurons can delegate their votes. Each proposal type specifies which canister method is called on adoption. For background on how proposals work, see [Governance](../concepts/governance.md#proposals). + +## Topic: ProtocolCanisterManagement + +Manages canisters essential to the Internet Computer Protocol, including the NNS governance canister (`rrkah-fqaaa-aaaaa-aaaaq-cai`), NNS root (`r7inp-6aaaa-aaaaa-aaabq-cai`), the registry canister (`rwlgt-iiaaa-aaaaa-aaaaa-cai`), and the ICP ledger (`ryjl3-tyaaa-aaaaa-aaaba-cai`). + +| Proposal type | Description | +|---|---| +| `InstallCode` | Install, reinstall, or upgrade the code of an NNS-controlled canister. | +| `UpdateCanisterSettings` | Update the settings of an NNS-controlled canister. | +| `StopOrStartCanister` | Stop or start an NNS-controlled canister. | +| `HardResetNnsRootToVersion` | Emergency reset of the root canister to a specified Wasm. Intended as a break-glass mechanism when an open call context prevents normal upgrades. | + +## Topic: ServiceNervousSystemManagement + +Manages SNS canister code and the SNS Wasm modules canister (SNS-W, `qaa6y-5yaaa-aaaaa-aaafa-cai`). + +| Proposal type | Description | +|---|---| +| `InstallCode` | Same as in ProtocolCanisterManagement, targeting SNS canisters. | +| `UpdateCanisterSettings` | Same as in ProtocolCanisterManagement, targeting SNS canisters. | +| `StopOrStartCanister` | Same as in ProtocolCanisterManagement, targeting SNS canisters. | +| `AddSnsWasm` | Add a new SNS canister Wasm to SNS-W, making it available for SNS instances to upgrade to. | +| `InsertSnsWasmUpgradePathEntries` | Insert custom upgrade path entries into SNS-W for all SNSes or for a specific SNS. | + +## Topic: ApplicationCanisterManagement + +Manages NNS-controlled canisters not covered by the above topics. + +| Proposal type | Description | +|---|---| +| `InstallCode` | Same as ProtocolCanisterManagement, targeting application canisters. | +| `UpdateCanisterSettings` | Same as ProtocolCanisterManagement, targeting application canisters. | +| `StopOrStartCanister` | Same as ProtocolCanisterManagement, targeting application canisters. | +| `BitcoinSetConfig` | Set the configuration of the Bitcoin integration canister: fees, block syncing, API enablement. | + +## Topic: IcOsVersionElection + +Elects new IC OS versions before deployment. The IC OS has two layers: HostOS (the hypervisor running on physical hardware) and GuestOS (the VM containing the replica). + +| Proposal type | Description | +|---|---| +| `ReviseElectedGuestosVersions` | Add or remove GuestOS versions from the elected set. Identified by Git revision and installation image SHA-256. Only elected versions can be deployed to subnets. | +| `ReviseElectedHostosVersions` | Add or remove HostOS versions from the elected set. | + +## Topic: IcOsVersionDeployment + +Deploys previously elected IC OS versions to specific nodes or subnets. + +| Proposal type | Description | +|---|---| +| `DeployHostosToSomeNodes` | Deploy a HostOS version to a specified set of nodes. | +| `DeployGuestosToAllSubnetNodes` | Deploy a GuestOS version to all nodes in a subnet. | +| `DeployGuestosToSomeApiBoundaryNodes` | Update the GuestOS version on a set of API Boundary Nodes. | +| `DeployGuestosToAllUnassignedNodes` | Update the GuestOS version on all unassigned nodes. | + +## Topic: Governance + +Reward weight: 20 (higher than most topics, incentivizing participation). Covers governance of the Internet Computer itself. + +| Proposal type | Description | +|---|---| +| `Motion` | Opinion poll with no direct onchain effect. Used to signal community consensus on strategy. | +| `UninstallCode` | Uninstall code from a canister. | +| `SetDefaultFollowees` | Set the default following for newly created neurons. | +| `KnownNeuron` | Register or update a known neuron with a name, optional description, links, and committed proposal topics. | +| `DeregisterKnownNeuron` | Remove a neuron from the known neurons list. | + +## Topic: SnsAndCommunityFund + +Reward weight: 20. Covers SNS decentralization swaps and the Neurons' Fund. + +| Proposal type | Description | +|---|---| +| `CreateServiceNervousSystem` | Install a new SNS and specify all settings: initial digital asset distribution, decentralization swap conditions, initial governance parameters, and Neurons' Fund contribution. | + +## Topic: NetworkEconomics + +Economic parameters for the network and NNS governance settings. + +| Proposal type | Description | +|---|---| +| `UpdateNodeRewardsTable` | Update the table used to calculate node provider rewards by region. | +| `NetworkEconomics` | Update one or more economic parameters: reject cost, minimum neuron stake, neuron management fee, minimum ICP/XDR rate, spawned neuron dissolve delay, maximum node provider rewards, transaction fee, maximum proposals per topic, Neurons' Fund economics, and voting power parameters. | +| `ClearProvisionalWhitelist` | Remove principals from the bootstrapping whitelist that allows canister creation without cycles. Intended for use after mainnet initialization only. | + +## Topic: SubnetManagement + +Subnet topology, configuration, and canister routing. + +**Subnet creation and composition:** + +| Proposal type | Description | +|---|---| +| `CreateSubnet` | Create a new subnet from a set of nodes, triggering distributed key generation. | +| `UpdateConfigOfSubnet` | Update a subnet's protocol configuration (message sizes and similar consensus-level parameters). | +| `AddNodeToSubnet` | Add an unassigned node to a subnet. | +| `RemoveNodesFromSubnet` | Remove nodes from a subnet, making them available for reassignment. | +| `ChangeSubnetMembership` | Atomically add and remove nodes (node swap) in a single operation. | +| `RecoverSubnet` | Update a subnet's recovery catch-up package to recover a stalled subnet. | + +**Firewall rules:** + +| Proposal type | Description | +|---|---| +| `SetFirewallConfig` | Set firewall configuration in the registry. | +| `AddFirewallRules` | Add firewall rules. | +| `RemoveFirewallRules` | Remove firewall rules. | +| `UpdateFirewallRules` | Update firewall rules. | + +**Subnet type and canister routing:** + +| Proposal type | Description | +|---|---| +| `SetAuthorizedSubnetworks` | Authorize a principal to use specific subnets for canister creation via the Cycles Minting Canister. | +| `UpdateSubnetType` | Update the available subnet types in the Cycles Minting Canister. | +| `ChangeSubnetTypeAssignment` | Change which subnets are assigned to which subnet type. | +| `UpdateSnsWasmSnsSubnetIds` | Update the list of subnet IDs where SNS-W deploys new SNS instances. | +| `RerouteCanisterRanges` | Update the registry routing table (which canister ID ranges are on which subnet). | +| `PrepareCanisterMigration` | Insert canister migration entries for a subnet split. | +| `CompleteCanisterMigration` | Remove canister migration entries after a split completes. | + +## Topic: ParticipantManagement + +Node provider and data center identities. + +| Proposal type | Description | +|---|---| +| `AddOrRemoveDataCenters` | Add or remove data center records in the registry. | +| `AddOrRemoveNodeProvider` | Assign or revoke an identity to a node provider, including legal entity information and jurisdiction. | + +## Topic: NodeAdmin + +Node machine administration. + +| Proposal type | Description | +|---|---| +| `AssignNoid` | Assign an identity to a node operator and set their remaining node allowance. | +| `UpdateNodeOperatorConfig` | Update a node operator's allowance or configuration in the registry. | +| `RemoveNodeOperators` | Remove a node operator from the registry. | +| `RemoveNodes` | Remove unassigned nodes from the registry. | +| `UpdateSshReadonlyAccessForAllUnassignedNodes` | Update SSH read-only access for all unassigned nodes. | + +## Topic: KYC + +Genesis neuron KYC verification. All neurons created after genesis have `kyc_verified = true` automatically, since they derive from already-KYC-verified balances. + +| Proposal type | Description | +|---|---| +| `ApproveGenesisKYC` | Set `kyc_verified = true` for a batch of genesis principals, enabling them to spawn neurons and disburse stakes. | + +## Topic: NeuronManagement (restricted voting) + +A special topic for collective management of a specific neuron. Only the target neuron's followers on this topic can vote, so proposals have a shorter-than-normal voting period. The standard restriction on following private neurons does not apply to this topic. + +| Proposal type | Description | +|---|---| +| `ManageNeuron` | Call a command on a specified target neuron. Only the target neuron's followers may vote. | + + diff --git a/docs/references/protocol-canisters.md b/docs/references/protocol-canisters.md index 085990e9..3335600e 100644 --- a/docs/references/protocol-canisters.md +++ b/docs/references/protocol-canisters.md @@ -1,11 +1,11 @@ --- -title: "Protocol Canisters" +title: "Protocol canisters" description: "Bitcoin canister, ckBTC minter, ckETH minter, EVM RPC canister, exchange rate canister, and other protocol-level canisters with their APIs and Candid interfaces" sidebar: order: 3 --- -Protocol canisters implement platform-level features on the Internet Computer. Unlike [system canisters](system-canisters.md), which govern the network itself, protocol canisters provide infrastructure that applications build on: Bitcoin integration, Ethereum integration, chain-key tokens, and exchange rates. They are controlled by the NNS and run on dedicated system subnets. +Protocol canisters implement platform-level features on the Internet Computer. Unlike [system canisters](system-canisters.md), which govern the network itself, protocol canisters provide infrastructure that applications build on: Bitcoin integration, Ethereum integration, [chain-key tokens](../concepts/chain-fusion/chain-key-tokens.md), and exchange rates. They are controlled by the NNS and run on dedicated system subnets. For all chain-key token canister IDs (ledger, minter, index), see [Chain-Key Token Canister IDs](chain-key-canister-ids.md). For deposit, withdrawal, and transfer flows, see [Chain-key tokens](../guides/digital-assets/chain-key-tokens.md). @@ -38,8 +38,38 @@ The Bitcoin integration canisters connect ICP to the Bitcoin network. They track - `bitcoin_send_transaction`: submits a signed Bitcoin transaction - `bitcoin_get_current_fee_percentiles`: returns fee percentiles in millisatoshi/vbyte - `bitcoin_get_block_headers`: returns block headers for a range of heights +- `get_blockchain_info`: returns chain tip height, block hash, timestamp, difficulty, and UTXO count -For integration patterns, see the [Bitcoin guide](../guides/chain-fusion/bitcoin.md). +### Cycle costs + +All Bitcoin canister calls require cycles attached. In Rust, the `ic-cdk-bitcoin-canister` crate handles this automatically. In Motoko, attach cycles explicitly with `(with cycles = amount)`. + +| Endpoint | Testnet / Regtest | Mainnet | +|---|---|---| +| `bitcoin_get_balance` | 40,000,000 | 100,000,000 | +| `bitcoin_get_utxos` | 4,000,000,000 | 10,000,000,000 | +| `bitcoin_send_transaction` (base) | 2,000,000,000 | 5,000,000,000 | +| `bitcoin_send_transaction` (per byte) | 8,000,000 | 20,000,000 | +| `bitcoin_get_current_fee_percentiles` | 40,000,000 | 100,000,000 | +| `bitcoin_get_block_headers` | 4,000,000,000 | 10,000,000,000 | +| `get_blockchain_info` | 40,000,000 | 100,000,000 | + +For integration patterns and code examples, see the [Bitcoin guide](../guides/chain-fusion/bitcoin.md). + +## Dogecoin canister + +The Dogecoin canister is a system-level canister that connects ICP to the Dogecoin network using the same architecture as the Bitcoin integration. It syncs blocks from the Dogecoin peer-to-peer network, maintains the UTXO set, and exposes an API for querying Dogecoin state and submitting transactions. + +For the current canister ID, see the [Dogecoin canister repository](https://github.com/dfinity/dogecoin-canister). + +### Key endpoints + +- `dogecoin_get_utxos`: returns UTXOs for a Dogecoin address +- `dogecoin_get_balance`: returns the balance of a Dogecoin address in koinu (1 DOGE = 100,000,000 koinu) +- `dogecoin_get_current_fee_percentiles`: returns fee percentiles from recent Dogecoin transactions +- `dogecoin_send_transaction`: submits a signed transaction to the Dogecoin network + +For integration patterns, see the [Dogecoin guide](../guides/chain-fusion/dogecoin.md). ## ckBTC minter @@ -69,6 +99,16 @@ For canister IDs, see [Chain-Key Token Canister IDs: ckBTC](chain-key-canister-i - `get_minter_info`: returns current minter parameters - `get_events(start, length)`: returns the minter's internal event log +### Withdrawal fee + +The minter fee for a Bitcoin withdrawal transaction is `146 × inputs + 4 × outputs + 26` satoshi. This formula covers the cost of threshold ECDSA signatures and Bitcoin transaction broadcasting. When multiple withdrawal requests are batched into one transaction, the fee is split among all outputs. + + + +### UTXO consolidation + +As deposits accumulate, the minter manages a growing set of UTXOs. If the UTXO count exceeds 10,000, the minter periodically creates consolidation transactions that merge the 1,000 smallest UTXOs into 2 new outputs, funded from the minter's fee subaccount. This prevents the UTXO set from growing large enough to make withdrawals impossible (a Bitcoin transaction is limited to 100 KB). + ### KYT checker The ckBTC checker canister (`oltsj-fqaaa-aaaar-qal5q-cai`) performs know-your-transaction compliance checks on incoming Bitcoin UTXOs. It is called internally by the minter on deposit and is not part of the developer-facing API. @@ -191,9 +231,31 @@ By default, the canister requires all providers to agree (`Equality` consensus). For integration examples, see the [Ethereum guide](../guides/chain-fusion/ethereum.md). +## SOL RPC canister + +The SOL RPC canister proxies JSON-RPC calls to the Solana network via HTTPS outcalls. It follows the same pattern as the EVM RPC canister: each request is forwarded to multiple independent RPC providers and the results are compared for consensus before being returned to the caller. No API keys are required. + +| Field | Value | +|---|---| +| Canister ID | [`2xib7-jqaaa-aaaar-qai6q-cai`](https://dashboard.internetcomputer.org/canister/2xib7-jqaaa-aaaar-qai6q-cai) | +| Source | [dfinity/sol-rpc-canister](https://github.com/dfinity/sol-rpc-canister) | + +### Built-in RPC providers + +| Provider | +|---| +| [Alchemy](https://www.alchemy.com/) | +| [Ankr](https://www.ankr.com/) | +| [Chainstack](https://chainstack.com/) | +| [dRPC](https://drpc.org/) | +| [Helius](https://www.helius.dev/) | +| [PublicNode](https://publicnode.com/) | + +For integration examples, see the [Solana guide](../guides/chain-fusion/solana.md). + ## Exchange rate canister (XRC) -The exchange rate canister (XRC) uses HTTPS outcalls to fetch cryptocurrency and foreign exchange rates from major exchanges. It runs on the `uzr34` system subnet and is used by the cycles minting canister (CMC) to convert ICP to cycles at a stable XDR-pegged price. +The [exchange rate canister](../concepts/chain-fusion/exchange-rate-canister.md) (XRC) uses HTTPS outcalls to fetch cryptocurrency and foreign exchange rates from major exchanges. It runs on the `uzr34` system subnet and is used by the cycles minting canister (CMC) to convert ICP to cycles at a stable XDR-pegged price. | Field | Value | |---|---| @@ -201,48 +263,86 @@ The exchange rate canister (XRC) uses HTTPS outcalls to fetch cryptocurrency and | Subnet | [`uzr34-akd3s-xrdag-3ql62-ocgoh-ld2ao-tamcv-54e7j-krwgb-2gm4z-oqe`](https://dashboard.internetcomputer.org/subnet/uzr34-akd3s-xrdag-3ql62-ocgoh-ld2ao-tamcv-54e7j-krwgb-2gm4z-oqe) | | Specification | [XRC interface spec](https://github.com/dfinity/exchange-rate-canister/blob/main/INTERFACE_SPECIFICATION.md) | -### Data sources - -The XRC pulls from the following exchanges: Coinbase, Kucoin, OKX, Gate.io, MEXC, Poloniex, Crypto.com, Bitget, and DigiFinex. +For how the aggregation and rate derivation work, see [Exchange rate canister](../concepts/chain-fusion/exchange-rate-canister.md). -For forex rates, it queries public APIs from foreign exchange data providers worldwide on a periodic basis. +### Data sources -### Rate aggregation +Cryptocurrency rates: Coinbase, Kucoin, OKX, Gate.io, MEXC, Poloniex, Crypto.com, Bitget, DigiFinex. -The XRC calculates rates using candlestick chart data for specific one-minute intervals across exchanges. Rather than time-weighted or volume-weighted averages, it collects, combines, and filters rates from all sources and returns the median. This approach minimizes manipulation risk. The XRC can also derive rates for pairs not directly traded (e.g., A/B from A/C and B/C rates). +Forex rates: queried from public APIs of foreign exchange data providers worldwide on a periodic schedule. -### Interface +### Candid interface The XRC exposes a single endpoint: -``` +```candid get_exchange_rate : (GetExchangeRateRequest) -> (GetExchangeRateResult) ``` -**Request:** +**Types:** ```candid +type AssetClass = variant { Cryptocurrency; FiatCurrency }; + +type Asset = record { + symbol : text; + class : AssetClass; +}; + type GetExchangeRateRequest = record { base_asset : Asset; quote_asset : Asset; timestamp : opt nat64; }; -``` -`Asset` is a record with a `symbol` (e.g., `"BTC"`) and `class` (`Cryptocurrency` or `FiatCurrency`). Any combination of digital asset and fiat is supported (e.g., ICP/USD, BTC/ICP, USD/EUR). If `timestamp` is omitted, the current rate is returned. +type ExchangeRateMetadata = record { + decimals : nat32; + base_asset_num_received_rates : nat64; + base_asset_num_queried_sources: nat64; + quote_asset_num_received_rates: nat64; + quote_asset_num_queried_sources:nat64; + standard_deviation : nat64; + forex_timestamp : opt nat64; +}; + +type ExchangeRate = record { + base_asset : Asset; + quote_asset : Asset; + timestamp : nat64; + rate : nat64; + metadata : ExchangeRateMetadata; +}; -**Response:** +type ExchangeRateError = variant { + AnonymousPrincipalNotAllowed : null; + Pending : null; + CryptoBaseAssetNotFound : null; + CryptoQuoteAssetNotFound : null; + StablecoinRateNotFound : null; + StablecoinRateTooFewRates : null; + StablecoinRateZeroRate : null; + ForexInvalidTimestamp : null; + ForexBaseAssetNotFound : null; + ForexQuoteAssetNotFound : null; + ForexAssetsNotFound : null; + RateLimited : null; + NotEnoughCycles : null; + FailedToAcceptCycles : null; + InconsistentRatesReceived : null; + Other : record { code : nat32; description : text }; +}; -```candid type GetExchangeRateResult = variant { Ok : ExchangeRate; Err : ExchangeRateError; }; ``` +The `rate` field is a scaled 64-bit integer. Divide by `10^decimals` (from `metadata.decimals`) to get the human-readable price. If `timestamp` in the request is omitted, the rate for the current minute is returned. Timestamps have 1-minute granularity; seconds are ignored. + ### Cycle costs -Each request requires 1B cycles attached. If insufficient cycles are provided, the canister returns `ExchangeRateError::NotEnoughCycles`. The actual cost depends on the asset types and cache state: +Each request requires 1 billion cycles attached. If insufficient cycles are provided, the canister returns `NotEnoughCycles`. The actual cost after the call depends on the asset types and cache state: | Condition | Actual cost | |---|---| @@ -253,20 +353,7 @@ Each request requires 1B cycles attached. If insufficient cycles are provided, t Unused cycles are refunded. At least 1M cycles are charged even on error, to prevent denial-of-service attacks. -### Example call - -Calling the XRC requires attaching cycles, which is only possible from canister-to-canister calls. The CLI cannot attach cycles to direct calls. Call the XRC from a canister using the Candid interface: pass the required cycles in the `ic_cdk::api::call::call_with_payment128` call or equivalent. - -To query the current rate without attaching cycles (for inspection only, expect a `NotEnoughCycles` error on mainnet): - -```bash -icp canister call uf6dk-hyaaa-aaaaq-qaaaq-cai get_exchange_rate \ - '(record { - base_asset = record { symbol = "BTC"; class = variant { Cryptocurrency } }; - quote_asset = record { symbol = "USD"; class = variant { FiatCurrency } }; - })' \ - -n ic -``` +Cycles must be attached to the inter-canister call itself; the CLI cannot call the XRC directly on mainnet. For working code, see [Fetch exchange rates](../guides/chain-fusion/exchange-rates.md). ## SNS-W canister @@ -279,7 +366,7 @@ The SNS Wasm canister (SNS-W) manages the deployment and upgrade of Service Nerv The SNS-W canister stores blessed SNS Wasm binaries, creates new SNS instances, and coordinates SNS upgrades. When the NNS passes an SNS upgrade proposal, it installs the new Wasms on each SNS canister via SNS-W. -For governance context, see the [SNS documentation](https://learn.internetcomputer.org/hc/en-us/articles/34084394684564-SNS-Service-Nervous-System). +For governance context, see [SNS framework](../concepts/sns-framework.md). ## Quick reference @@ -293,6 +380,7 @@ For governance context, see the [SNS documentation](https://learn.internetcomput | ckDOGE Minter | `eqltq-xqaaa-aaaar-qb3vq-cai` | DOGE ↔ ckDOGE minting and burning | | ckSOL Minter | `lh22c-kyaaa-aaaar-qb5nq-cai` | SOL ↔ ckSOL minting and burning | | EVM RPC | `7hfb6-caaaa-aaaar-qadga-cai` | Ethereum JSON-RPC proxy | +| SOL RPC | `2xib7-jqaaa-aaaar-qai6q-cai` | Solana JSON-RPC proxy | | Exchange Rate (XRC) | `uf6dk-hyaaa-aaaaq-qaaaq-cai` | Crypto and forex exchange rates | | SNS-W | `qaa6y-5yaaa-aaaaa-aaafa-cai` | SNS deployment and upgrades | @@ -301,9 +389,12 @@ For ledger, index, and testnet canister IDs for all chain-key tokens, see [Chain ## Next steps - [Chain-Key Token Canister IDs](chain-key-canister-ids.md): ledger, minter, and index IDs for all chain-key tokens -- [Chain-key tokens](../guides/digital-assets/chain-key-tokens.md): deposit, withdrawal, and transfer flows for all chain-key tokens +- [Chain-key tokens concept](../concepts/chain-fusion/chain-key-tokens.md): how trustless 1:1 asset representations work and why they differ from wrapped tokens +- [Chain-key tokens guide](../guides/digital-assets/chain-key-tokens.md): deposit, withdrawal, and transfer flows for all chain-key tokens +- [Exchange rate canister concept](../concepts/chain-fusion/exchange-rate-canister.md#how-rates-are-computed): how rates are aggregated and what pairs are available - [Bitcoin guide](../guides/chain-fusion/bitcoin.md): integrating Bitcoin in canisters using the Bitcoin canister and ckBTC - [Ethereum guide](../guides/chain-fusion/ethereum.md): integrating Ethereum in canisters using the EVM RPC canister and ckETH +- [IC Dashboard APIs](ic-dashboard-api.md#ic-api): programmatic access to canister metrics, subnet data, and protocol-level information - [System canisters](system-canisters.md): NNS canisters, Internet Identity, ICP ledger, and other network-level canisters - [Management canister](management-canister.md): the virtual canister for canister lifecycle, signing, and platform APIs diff --git a/docs/references/sns-settings.md b/docs/references/sns-settings.md new file mode 100644 index 00000000..66e83cda --- /dev/null +++ b/docs/references/sns-settings.md @@ -0,0 +1,72 @@ +--- +title: "SNS settings" +description: "Reference for all SNS nervous system parameters (NervousSystemParameters)" +--- + +Each SNS is customized through its **nervous system parameters**, also called SNS settings. These parameters govern voting power calculation, governance rules, asset economics, and reward behavior. Parameters are set at launch and can be changed by governance proposal at any time. + +For background, see [SNS framework](../concepts/sns-framework.md). + +## Neuron settings + +| Parameter | Type | Description | +|---|---|---| +| `neuron_minimum_stake_e8s` | `nat64` | Minimum number of e8s (10⁻⁸ of the SNS asset) that can be staked in a neuron. Must be larger than `transaction_fee_e8s`. | +| `max_number_of_neurons` | `nat64` | Maximum number of neurons allowed. New neurons are blocked once this ceiling is reached. Ceiling: 200,000. | +| `max_number_of_principals_per_neuron` | `nat64` | Maximum number of principals that can hold permissions for a single neuron. | +| `neuron_claimer_permissions` | permission set | The set of permissions automatically granted to the principal that claims a new neuron. | +| `neuron_grantable_permissions` | permission set | The superset of permissions that a principal with `ManagePrincipals` permission can grant to others on the same neuron. | +| `default_followees` | map | Default following rules applied to every newly created neuron, as a mapping of proposal function IDs to followee neuron IDs. | +| `max_followees_per_function` | `nat64` | Maximum number of followees a neuron can configure per proposal function. Ceiling: 15. | + +## Voting power settings + +| Parameter | Type | Description | +|---|---|---| +| `neuron_minimum_dissolve_delay_to_vote_seconds` | `nat64` | Minimum dissolve delay a neuron must have to be eligible to vote. Must be less than `max_dissolve_delay_seconds`. | +| `max_dissolve_delay_seconds` | `nat64` | Maximum dissolve delay achievable by a neuron. The dissolve delay bonus is saturated at this value. | +| `max_dissolve_delay_bonus_percentage` | `nat64` | Additional voting power percentage granted at maximum dissolve delay. Set to 100 for a 2x bonus (matching Network Nervous System (NNS) behavior). Set to 0 for no bonus. | +| `max_neuron_age_for_age_bonus` | `nat64` | Maximum neuron age (seconds) at which the age bonus is saturated. | +| `max_age_bonus_percentage` | `nat64` | Additional voting power percentage granted at maximum age. Set to 25 for a 1.25x bonus (matching NNS behavior). Set to 0 for no bonus. | + +## Proposal and governance settings + +| Parameter | Type | Description | +|---|---|---| +| `reject_cost_e8s` | `nat64` | Fee (in e8s) charged to the proposer when a proposal is rejected, to discourage spam. | +| `initial_voting_period_seconds` | `nat64` | Initial voting period for non-critical proposals. The actual period may be extended by wait-for-quiet. Does not affect existing proposals. | +| `wait_for_quiet_deadline_increase_seconds` | `nat64` | Maximum total extension added by wait-for-quiet when a proposal outcome flips. The voting period can increase by at most twice this value. Does not affect existing proposals. | +| `max_proposals_to_keep_per_action` | `nat64` | Maximum number of proposals retained per proposal type. When exceeded, the oldest finalized proposals are eligible for deletion. Ceiling: 700. | +| `max_number_of_proposals_with_ballots` | `nat64` | Maximum number of open (unsettled) proposals with stored ballots. When reached, only a few critical proposal types can still be submitted. Ceiling: 700. | + +## Digital asset and fee settings + +| Parameter | Type | Description | +|---|---|---| +| `transaction_fee_e8s` | `nat64` | Per-transfer fee on the SNS ledger, in e8s. Does not apply to minting or burning. | + +## Voting reward settings + +All reward settings live inside a single nested field: **`voting_rewards_parameters`**. If this field is absent, voting rewards are disabled. + +| Parameter | Full field name | Description | +|---|---|---| +| round duration | `round_duration_seconds` | Length of a single reward distribution round, in seconds. Rewards are distributed to voting neurons at the end of each round. Default: 86,400 (1 day). | +| r\_max | `initial_reward_rate_basis_points` | Starting annualized reward rate as a fraction of total supply, in basis points (100 = 1%). | +| r\_min | `final_reward_rate_basis_points` | Floor reward rate after the transition period, in basis points. Set to 0 to end issuance after `t_delta`. | +| t\_delta | `reward_rate_transition_duration_seconds` | Duration of the quadratic decline from r\_max to r\_min, in seconds. | +| t\_start | `start_timestamp_seconds` | Timestamp (Unix seconds) when reward accrual begins. Set automatically to the current time when rewards are first enabled. | + +## Maturity modulation + +| Parameter | Type | Description | +|---|---|---| +| `maturity_modulation_disabled` | `opt bool` | If true, maturity modulation is disabled for this SNS: the ±5% conversion randomness is not applied when neuron holders disburse maturity. The CMC is still polled but the fetched value is ignored. Default: false (modulation enabled). | + +## SNS framework upgrade + +| Parameter | Type | Description | +|---|---|---| +| `automatically_advance_target_version` | `opt bool` | If true, the SNS automatically upgrades to the latest NNS-approved SNS version without a governance proposal. Defaults to true for newly created SNSs, false for older ones. | + + diff --git a/docs/references/subnet-types.md b/docs/references/subnet-types.md index 19bd867a..4f47c890 100644 --- a/docs/references/subnet-types.md +++ b/docs/references/subnet-types.md @@ -1,5 +1,5 @@ --- -title: "Subnet Types Reference" +title: "Subnet types reference" description: "All subnet types with node counts, replication factors, and cost multipliers" sidebar: order: 9 diff --git a/docs/references/system-canisters.md b/docs/references/system-canisters.md index e6000847..1ed0dc8e 100644 --- a/docs/references/system-canisters.md +++ b/docs/references/system-canisters.md @@ -1,5 +1,5 @@ --- -title: "System Canisters" +title: "System canisters" description: "NNS canisters, Internet Identity, ICP ledger, and other system-level canisters with canister IDs and interface references" sidebar: order: 2 @@ -196,7 +196,7 @@ Key differences from cycles wallets: - Transfers and balance queries use ICRC-1/ICRC-2 methods - Compatible with any ICRC-1 tooling -For the interface specification, see the [cycles ledger specification](https://github.com/dfinity/cycles-ledger/blob/main/INTERFACE_SPECIFICATION.md). +For the full interface, see the [cycles ledger Candid file](https://github.com/dfinity/cycles-ledger/blob/main/cycles-ledger/cycles-ledger.did). ## Cycles ledger index @@ -206,41 +206,7 @@ For the interface specification, see the [cycles ledger specification](https://g The cycles ledger index canister indexes cycles ledger transactions by account, mirroring the same pattern as the ICP index canister for ICP transactions. -## Using system canisters - -### Calling from a canister (Rust) - -Calls to system canisters are inter-canister calls. The Rust CDK provides direct bindings for some system canisters (such as the management canister). For others, use `ic_cdk::call::Call` with the canister's principal: - -```rust -use candid::Principal; -use ic_cdk::call::Call; - -let icp_ledger = Principal::from_text("ryjl3-tyaaa-aaaaa-aaaba-cai").unwrap(); -let args = /* ICRC-1 transfer args */; -let result: TransferResult = Call::bounded_wait(icp_ledger, "icrc1_transfer") - .with_arg(args) - .await? - .candid()?; -``` - -### Calling from a canister (Motoko) - -In Motoko, `canister:` imports use the canister **name** as declared in `icp.yaml`, not the raw canister ID. For the ICP ledger declared as `icp_ledger_canister` in your project config: - -```motoko -import Ledger "canister:icp_ledger_canister"; -``` - -To call a canister by hardcoded ID without a project config entry, use actor syntax: - -```motoko -let ledger : actor { - icrc1_balance_of : (Account) -> async Nat; -} = actor("ryjl3-tyaaa-aaaaa-aaaba-cai"); -``` - -### Using system canisters in local development +## Using system canisters in local development The icp-cli local network automatically includes Internet Identity and NNS canisters. Enable them in your `icp.yaml` network configuration: @@ -261,9 +227,11 @@ icp network start -d System canisters run at their mainnet canister IDs on the local network, so calls to `rdmx6-jaaaa-aaaaa-aaadq-cai` (Internet Identity) or `ryjl3-tyaaa-aaaaa-aaaba-cai` (ICP ledger) work without any additional configuration. -### Querying canister metadata via the Dashboard API +For how to call system canisters from your own canister, see [Inter-canister calls](../guides/canister-calls/inter-canister-calls.mdx). + +## Querying system canister data via the Dashboard API -The IC Dashboard API provides REST endpoints for querying canister metadata, transaction history, and network metrics without making onchain calls. See the [ic-dashboard skill](https://skills.internetcomputer.org/skills/ic-dashboard) for usage examples and the full API reference. +The IC Dashboard API provides REST endpoints for querying canister metadata, transaction history, and network metrics without making onchain calls. See [IC Dashboard APIs](ic-dashboard-api.md) for the full reference. ## Next steps diff --git a/public/concepts/chain-fusion/bitcoin-architecture.png b/public/concepts/chain-fusion/bitcoin-architecture.png new file mode 100644 index 00000000..5fbd0015 Binary files /dev/null and b/public/concepts/chain-fusion/bitcoin-architecture.png differ diff --git a/public/concepts/chain-fusion/bitcoin-checker-flow.png b/public/concepts/chain-fusion/bitcoin-checker-flow.png new file mode 100644 index 00000000..59223d16 Binary files /dev/null and b/public/concepts/chain-fusion/bitcoin-checker-flow.png differ diff --git a/public/concepts/chain-fusion/ckbtc-architecture.png b/public/concepts/chain-fusion/ckbtc-architecture.png new file mode 100644 index 00000000..e40ffe92 Binary files /dev/null and b/public/concepts/chain-fusion/ckbtc-architecture.png differ diff --git a/public/concepts/chain-fusion/dogecoin-architecture.png b/public/concepts/chain-fusion/dogecoin-architecture.png new file mode 100644 index 00000000..a0f4315b Binary files /dev/null and b/public/concepts/chain-fusion/dogecoin-architecture.png differ diff --git a/public/concepts/chain-fusion/exchange-rate-canister-flow.png b/public/concepts/chain-fusion/exchange-rate-canister-flow.png new file mode 100644 index 00000000..a3047f8d Binary files /dev/null and b/public/concepts/chain-fusion/exchange-rate-canister-flow.png differ diff --git a/public/concepts/cycles/cycles-ledger-architecture.png b/public/concepts/cycles/cycles-ledger-architecture.png new file mode 100644 index 00000000..02e1e22c Binary files /dev/null and b/public/concepts/cycles/cycles-ledger-architecture.png differ diff --git a/public/concepts/edge-infrastructure/edge-infrastructure.png b/public/concepts/edge-infrastructure/edge-infrastructure.png new file mode 100644 index 00000000..274d4eab Binary files /dev/null and b/public/concepts/edge-infrastructure/edge-infrastructure.png differ diff --git a/public/concepts/evolution-scaling/add-new-subnet.webp b/public/concepts/evolution-scaling/add-new-subnet.webp new file mode 100644 index 00000000..60fbc9be Binary files /dev/null and b/public/concepts/evolution-scaling/add-new-subnet.webp differ diff --git a/public/concepts/evolution-scaling/handing-cup.webp b/public/concepts/evolution-scaling/handing-cup.webp new file mode 100644 index 00000000..fcd5d20a Binary files /dev/null and b/public/concepts/evolution-scaling/handing-cup.webp differ diff --git a/public/concepts/evolution-scaling/new-subnet-proposal.webp b/public/concepts/evolution-scaling/new-subnet-proposal.webp new file mode 100644 index 00000000..09883a34 Binary files /dev/null and b/public/concepts/evolution-scaling/new-subnet-proposal.webp differ diff --git a/public/concepts/evolution-scaling/protocol-transition.webp b/public/concepts/evolution-scaling/protocol-transition.webp new file mode 100644 index 00000000..56840444 Binary files /dev/null and b/public/concepts/evolution-scaling/protocol-transition.webp differ diff --git a/public/concepts/evolution-scaling/registry-versions.webp b/public/concepts/evolution-scaling/registry-versions.webp new file mode 100644 index 00000000..ca330dd3 Binary files /dev/null and b/public/concepts/evolution-scaling/registry-versions.webp differ diff --git a/public/concepts/evolution-scaling/upgrade-proposal.webp b/public/concepts/evolution-scaling/upgrade-proposal.webp new file mode 100644 index 00000000..333c6bbc Binary files /dev/null and b/public/concepts/evolution-scaling/upgrade-proposal.webp differ diff --git a/public/concepts/network-economics/deflation-inflation.png b/public/concepts/network-economics/deflation-inflation.png new file mode 100644 index 00000000..c04a3ccb Binary files /dev/null and b/public/concepts/network-economics/deflation-inflation.png differ diff --git a/public/concepts/node-infrastructure/tee-attestation-report.svg b/public/concepts/node-infrastructure/tee-attestation-report.svg new file mode 100644 index 00000000..6df2d8c7 --- /dev/null +++ b/public/concepts/node-infrastructure/tee-attestation-report.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + AMD SEV-SNP Attestation Report + + + + 1. VM Launch Measurement + + 3a7c...8b2f [SHA-384 Hash] + + + + 2. Hardware Chip ID + + 9f8e...5b4a [Unique HW ID] + + + + 3. Custom Report Data (Nonce) + + d4e5...1a2b [64 Bytes User Data] + + + + + ... + Additional Fields ... + (TCB Version, Policy, Family ID) + + + + + + + + SIGNED BY AMD CERTIFICATE CHAIN + + + \ No newline at end of file diff --git a/public/concepts/node-infrastructure/tee-key-derivation.svg b/public/concepts/node-infrastructure/tee-key-derivation.svg new file mode 100644 index 00000000..8802582a --- /dev/null +++ b/public/concepts/node-infrastructure/tee-key-derivation.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + GuestOS image + + + + + AMD SEV-SNP + Launch Measurement + + + + + AMD SEV-SNP + Sealing Key + + + + + Partition specific + key material + + + + + LUKS + Encryption Key + + + \ No newline at end of file diff --git a/public/concepts/node-infrastructure/tee-overview.jpg b/public/concepts/node-infrastructure/tee-overview.jpg new file mode 100644 index 00000000..bc33a759 Binary files /dev/null and b/public/concepts/node-infrastructure/tee-overview.jpg differ diff --git a/public/concepts/protocol/block_maker.webp b/public/concepts/protocol/block_maker.webp new file mode 100644 index 00000000..6bd33360 Binary files /dev/null and b/public/concepts/protocol/block_maker.webp differ diff --git a/public/concepts/protocol/consensus_notarization.webp b/public/concepts/protocol/consensus_notarization.webp new file mode 100644 index 00000000..313f06c7 Binary files /dev/null and b/public/concepts/protocol/consensus_notarization.webp differ diff --git a/public/concepts/protocol/consensus_orders_messages.webp b/public/concepts/protocol/consensus_orders_messages.webp new file mode 100644 index 00000000..0cbc594d Binary files /dev/null and b/public/concepts/protocol/consensus_orders_messages.webp differ diff --git a/public/concepts/protocol/core_protocol_layers.webp b/public/concepts/protocol/core_protocol_layers.webp new file mode 100644 index 00000000..20b20bb6 Binary files /dev/null and b/public/concepts/protocol/core_protocol_layers.webp differ diff --git a/public/concepts/protocol/perf-latency-mainnet.png b/public/concepts/protocol/perf-latency-mainnet.png new file mode 100644 index 00000000..3695d548 Binary files /dev/null and b/public/concepts/protocol/perf-latency-mainnet.png differ diff --git a/public/concepts/protocol/perf-latency-synthetic.png b/public/concepts/protocol/perf-latency-synthetic.png new file mode 100644 index 00000000..fe8e4452 Binary files /dev/null and b/public/concepts/protocol/perf-latency-synthetic.png differ diff --git a/public/concepts/protocol/state-sync.webp b/public/concepts/protocol/state-sync.webp new file mode 100644 index 00000000..96ef49f0 Binary files /dev/null and b/public/concepts/protocol/state-sync.webp differ diff --git a/public/concepts/sns-framework/rewards-total-supply.png b/public/concepts/sns-framework/rewards-total-supply.png new file mode 100644 index 00000000..2e4ad864 Binary files /dev/null and b/public/concepts/sns-framework/rewards-total-supply.png differ diff --git a/scripts/validate.js b/scripts/validate.js index ff185ddf..c0362f43 100644 --- a/scripts/validate.js +++ b/scripts/validate.js @@ -44,7 +44,7 @@ function checkFrontmatter(file, content) { const FORBIDDEN = [ { re: /mo:base/, msg: '"mo:base" is banned — use "mo:core" instead' }, - { re: /internetcomputer\.org\/docs/, msg: 'internetcomputer.org/docs is retired — link internally or inline' }, + { re: /https?:\/\/(?:www\.)?internetcomputer\.org\/docs/, msg: 'internetcomputer.org/docs is retired — link internally or inline' }, { re: /docs\.internetcomputer\.org/, msg: 'docs.internetcomputer.org is this site — use relative paths for internal links' }, ]; diff --git a/sidebar.mjs b/sidebar.mjs index 4ef125bc..ef9fe5b9 100644 --- a/sidebar.mjs +++ b/sidebar.mjs @@ -11,13 +11,13 @@ export const sidebar = [ { - label: "Getting Started", + label: "Getting started", autogenerate: { directory: "getting-started" }, }, { label: "Guides", items: [ - { slug: "guides/ai-coding-agents", label: "AI Coding Agents" }, + { slug: "guides/ai-coding-agents", label: "AI coding agents" }, // Build: core development { label: "Backends", @@ -25,7 +25,7 @@ export const sidebar = [ autogenerate: { directory: "guides/backends" }, }, { - label: "Canister Calls", + label: "Canister calls", collapsed: true, autogenerate: { directory: "guides/canister-calls" }, }, @@ -46,7 +46,7 @@ export const sidebar = [ autogenerate: { directory: "guides/testing" }, }, { - label: "Canister Management", + label: "Canister management", collapsed: true, autogenerate: { directory: "guides/canister-management" }, }, @@ -57,7 +57,7 @@ export const sidebar = [ }, // Advanced features { - label: "Digital Assets", + label: "Digital assets", collapsed: true, autogenerate: { directory: "guides/digital-assets" }, }, @@ -76,9 +76,85 @@ export const sidebar = [ { label: "Concepts", collapsed: true, - autogenerate: { directory: "concepts" }, + items: [ + // Network: infrastructure topology, nodes, and scaling + { + label: "Network", + collapsed: true, + items: [ + { slug: "concepts/network-overview", label: "Overview" }, + { slug: "concepts/node-infrastructure" }, + { slug: "concepts/edge-infrastructure" }, + { slug: "concepts/evolution-scaling" }, + ], + }, + // Protocol Stack: ICP's internal execution layers + { + label: "Protocol stack", + collapsed: true, + items: [ + { slug: "concepts/protocol", label: "Overview" }, + { slug: "concepts/protocol/peer-to-peer" }, + { slug: "concepts/protocol/consensus" }, + { slug: "concepts/protocol/message-routing" }, + { slug: "concepts/protocol/execution" }, + { slug: "concepts/protocol/state-synchronization" }, + { slug: "concepts/protocol/performance" }, + ], + }, + // Canisters: the developer runtime and canister capabilities + { + label: "Canisters & capabilities", + collapsed: true, + items: [ + { slug: "concepts/canisters" }, + { slug: "concepts/principals" }, + { slug: "concepts/app-architecture" }, + { slug: "concepts/cycles" }, + { slug: "concepts/orthogonal-persistence" }, + { slug: "concepts/timers" }, + { slug: "concepts/verifiable-randomness" }, + { slug: "concepts/https-outcalls" }, + ], + }, + // Cryptography: ICP's cryptographic primitives + { + label: "Cryptography", + collapsed: true, + items: [ + { slug: "concepts/chain-key-cryptography" }, + { slug: "concepts/certified-data" }, + { slug: "concepts/vetkeys" }, + ], + }, + // Chain Fusion: cross-chain integration + { + label: "Chain Fusion", + collapsed: true, + items: [ + { slug: "concepts/chain-fusion", label: "Overview" }, + { slug: "concepts/chain-fusion/bitcoin" }, + { slug: "concepts/chain-fusion/ethereum" }, + { slug: "concepts/chain-fusion/solana" }, + { slug: "concepts/chain-fusion/dogecoin" }, + { slug: "concepts/chain-fusion/chain-key-tokens" }, + { slug: "concepts/chain-fusion/exchange-rate-canister" }, + ], + }, + // Trust & governance: security model, governance, and economics + { + label: "Trust & governance", + collapsed: true, + items: [ + { slug: "concepts/governance" }, + { slug: "concepts/sns-framework" }, + { slug: "concepts/network-economics" }, + { slug: "concepts/ledgers" }, + { slug: "concepts/security" }, + ], + }, + ], }, - { slug: "references/developer-tools", label: "Developer Tools" }, { label: "Languages", items: [ @@ -95,7 +171,7 @@ export const sidebar = [ }, }, { - label: "ICP Features", + label: "ICP features", autogenerate: { directory: "languages/motoko/icp-features", }, @@ -115,28 +191,60 @@ export const sidebar = [ }, ], }, + { slug: "references/developer-tools", label: "Developer tools" }, { label: "References", collapsed: true, items: [ - { slug: "references/management-canister" }, - { slug: "references/system-canisters" }, - { slug: "references/protocol-canisters" }, - { slug: "references/application-canisters" }, - { slug: "references/icrc-standards" }, - { slug: "references/digital-asset-standards" }, - { slug: "references/chain-key-canister-ids" }, - { slug: "references/cycles-costs" }, - { slug: "references/subnet-types" }, - { slug: "references/execution-errors" }, - { slug: "references/http-gateway-spec" }, + // Development reference: system API, costs, subnets, errors + { + label: "Development reference", + collapsed: true, + items: [ + { slug: "references/management-canister" }, + { slug: "references/cycles-costs" }, + { slug: "references/subnet-types" }, + { slug: "references/execution-errors" }, + ], + }, + // Canister registry: known canisters and their IDs + { + label: "Canister registry", + collapsed: true, + items: [ + { slug: "references/system-canisters" }, + { slug: "references/protocol-canisters" }, + { slug: "references/application-canisters" }, + { slug: "references/chain-key-canister-ids" }, + ], + }, + // Standards: ICRC standard family + { + label: "Standards", + collapsed: true, + items: [ + { slug: "references/icrc-standards" }, + { slug: "references/digital-asset-standards" }, + ], + }, + // Governance: NNS and SNS parameter references + { + label: "Governance", + collapsed: true, + items: [ + { slug: "references/nns-proposal-types" }, + { slug: "references/sns-settings" }, + ], + }, + // Formal specifications (ungrouped to avoid 4-level nesting with IC interface spec) { slug: "references/candid-spec" }, - { slug: "references/internet-identity-spec" }, { - label: "IC Interface Spec", + label: "IC interface spec", collapsed: true, autogenerate: { directory: "references/ic-interface-spec" }, }, + { slug: "references/http-gateway-spec" }, + { slug: "references/internet-identity-spec" }, { slug: "references/glossary" }, ], },