From d03494ba99c9f54fde3f83e24b0574bdb0e0871e Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 16 Apr 2026 15:22:44 +0200 Subject: [PATCH 1/2] docs: IC interface spec reference --- docs/reference/ic-interface-spec.md | 360 +++++++++++++++++++++++++++- 1 file changed, 349 insertions(+), 11 deletions(-) diff --git a/docs/reference/ic-interface-spec.md b/docs/reference/ic-interface-spec.md index f7eedd65..dfaefc66 100644 --- a/docs/reference/ic-interface-spec.md +++ b/docs/reference/ic-interface-spec.md @@ -1,20 +1,358 @@ --- title: "IC Interface Specification" -description: "Summary and links to the IC interface specification: System API, HTTP interface, certified data" +description: "Overview of the Internet Computer interface specification: System API, HTTP interface, certified data, and management canister" sidebar: order: 9 --- -TODO: Write content for this page. +The IC interface specification is the authoritative formal description of the Internet Computer's external interfaces. It describes what the IC guarantees to canister developers, agents, tooling authors, and anyone building on the protocol. - -Summary page for the IC interface specification. Provide a structured overview of the spec sections: System API (canister imports), HTTP interface (ingress messages, read state), certified data, canister lifecycle, and management canister. Link to the full specification for each section. This page serves as a navigation aid, not a duplication of the spec. +This page gives a structured overview of the spec's main sections to help you find what you need. The spec itself is precise and technically dense — it is the ground truth for behavior, error handling, and protocol invariants. - -- Portal: references/ic-interface-spec.mdx -- Full spec: https://internetcomputer.org/docs/references/ic-interface-spec +The full specification source is maintained in the `dfinity/portal` repository and is available as a reference document for tooling authors, CDK implementers, and protocol contributors. - -- reference/management-canister -- management canister subset -- reference/candid-spec -- encoding used by the interface -- reference/http-gateway-spec -- HTTP gateway protocol +## Who should read the IC interface spec + +The IC interface spec is aimed at: + +- **Tooling and agent authors** — those implementing agents, canister development kits, emulators, or other tooling that interacts directly with the IC at the protocol level. +- **Security researchers** — those performing detailed security analysis of IC behavior. +- **Protocol contributors** — those working on the IC implementation itself. + +Most canister developers interact with the IC through CDKs (Motoko, Rust CDK) and the icp-cli toolchain. For practical development guides, see the [guides section](../guides/index.md) and the [management canister reference](management-canister.md). + +## Pervasive concepts + +Several concepts apply across all interfaces described in the spec. + +### Principals + +Principals are the generic identifier type for canisters, users, and other entities on the IC. They are binary blobs between 0 and 29 bytes long. The spec defines five classes of principal: + +| Class | Form | Used for | +|---|---|---| +| Opaque | Generated by the IC | Canister IDs assigned by the IC | +| Self-authenticating | `SHA-224(public_key) · 0x02` | External user identities | +| Derived | Hash of registering principal + nonce | Reserved for future use | +| Anonymous | `0x04` | Unsigned calls | +| Reserved | `blob · 0x7f` | Application-defined identifiers | + +The **textual representation** of a principal is `Grouped(Base32(CRC32(blob) · blob))` — groups of 5 characters separated by dashes, in lowercase. For example, the management canister ID is `aaaaa-aa`. + +### Canister lifecycle + +A canister has the following state: + +- A canister ID (principal) +- A list of controllers (up to 10 principals) +- A cycle balance and a reserved cycles balance +- A status: `running`, `stopping`, or `stopped` + +A canister is either **empty** (no installed code) or **non-empty** (has a Wasm module, heap memory, stable memory, and globals). Canisters start empty after creation. An empty canister that receives a response drops the response and credits the cycles back to its balance. + +When both the main and reserved cycle balances reach zero, the canister is **deallocated**: its code and memory are freed, but its ID, cycle balances, controllers, version, and change count are preserved for at least 10 years. + +For lifecycle management from a developer perspective, see the [canister lifecycle guide](../guides/canister-management/lifecycle.md). + +### Canister status + +| Status | Behavior | +|---|---| +| `running` | Calls are processed normally | +| `stopping` | Incoming calls are rejected with `CANISTER_ERROR`; responses continue to be processed | +| `stopped` | Incoming calls are rejected; no outstanding responses remain | + +Calls to the management canister (`aaaaa-aa`) are always processed regardless of the managed canister's status. + +### Signatures + +The IC supports multiple signature schemes for authentication: + +| Scheme | OID / Description | +|---|---| +| Ed25519 | Edwards-curve signature | +| ECDSA on secp256k1 | Used by Bitcoin-compatible keys | +| ECDSA on secp256r1 | P-256, used by passkeys and WebAuthn | +| RSA PKCS#1 v1.5 with SHA-256 | For legacy key types | +| Canister signatures | IC-specific delegated signatures from a canister | + +The spec also defines a **delegation chain** mechanism: a key may delegate signing authority to another key with optional restrictions on target canisters and expiry times. + +## System state tree + +The IC maintains a **system state tree** — a Merkle tree whose root hash is published in every certified response. Clients can request a partial tree (a **certificate**) and verify that any value in it was produced by the IC. + +Key subtrees of the state tree: + +| Path | Content | +|---|---| +| `/time` | Current IC time in nanoseconds since Unix epoch | +| `/api_boundary_nodes//...` | API boundary node information (domain, IPv4/IPv6) | +| `/subnet//...` | Subnet public key, canister ID ranges, node IDs | +| `/request_status//...` | Status of a submitted request (received, processing, replied, rejected, done) | +| `/canister//certified_data` | 32-byte blob set by the canister | +| `/canister//module_hash` | SHA-256 of the installed Wasm module | +| `/canister//controllers` | CBOR-encoded list of controller principals | + +The **certified data** subtree is used by canisters to publish verifiable values in query responses. See the [certified variables guide](../guides/backends/certified-variables.md) for a practical walkthrough. + +The **request status** subtree lets clients verify the outcome of update calls. Statuses progress through: `received` → `processing` → `replied` or `rejected` → `done`. + +## HTTPS interface + +External users interact with the IC by sending HTTPS requests to a **boundary node**. The boundary node routes requests to the appropriate subnet replica. + +### Endpoints + +All endpoints accept and return CBOR-encoded messages. + +| Endpoint | Method | Description | +|---|---|---| +| `/api/v2/canister//call` | POST | Submit an update call (synchronous response is provisional ACK) | +| `/api/v2/canister//read_state` | POST | Read certified state from the state tree | +| `/api/v2/canister//query` | POST | Execute a query call (non-replicated, fast) | +| `/api/v2/subnet//read_state` | POST | Read subnet-level state | +| `/api/v2/status` | GET | IC status and versioning information | + +There is also an asynchronous call endpoint at `/api/v3/canister//call` that returns a signed acknowledgement and the request ID without waiting for the call to reach consensus. + +### Request structure + +All update, read state, and query requests share a common envelope structure: + +``` +{ + "sender_pubkey": , + "sender_sig": , + "content": { + "request_type": "call" | "read_state" | "query", + "sender": , + "nonce": , + "ingress_expiry": , + ...request-specific fields... + } +} +``` + +Requests are authenticated by signing the request content. Anonymous requests use `sender = 0x04` and omit the key and signature fields. + +### Ingress messages + +An **ingress message** is a call submitted by an external user. The `ingress_expiry` field sets a deadline (up to 5 minutes in the future) after which the IC will not execute the call. Once submitted, the caller polls `/read_state` using the request ID to determine the outcome. + +### Query calls + +Query calls are executed by a single replica (non-replicated). They are fast but do not produce certified results — a malicious replica could return incorrect data. For verified query responses, use **certified data** in combination with a `read_state` request to verify the certificate. + +### Effective canister ID + +Requests must include an **effective canister ID** in the URL path. For most calls this is the target canister. For calls to the management canister that create a new canister, the effective canister ID must be the subnet ID. For other management canister calls, it is the target canister ID. + +### Authentication + +Requests are authenticated using the sender's key and a signature over the request content hash. The spec defines **representation-independent hashing** — a deterministic algorithm for hashing structured request data — and **request IDs** — the hash used to identify a submitted request when polling for status. + +### Reject codes + +When a call is rejected, the response includes a reject code: + +| Code | Symbolic name | Meaning | +|---|---|---| +| 1 | `SYS_FATAL` | Fatal system error; retry will not help | +| 2 | `SYS_TRANSIENT` | Transient system error; retry may succeed | +| 3 | `DESTINATION_INVALID` | Target canister does not exist or is not a valid destination | +| 4 | `CANISTER_REJECT` | Canister explicitly rejected the call with `ic0.msg_reject` | +| 5 | `CANISTER_ERROR` | Canister trapped or the IC rejected due to canister state | + +## Canister module format + +A canister module is a **WebAssembly binary** (raw `.wasm` or gzip-compressed) that exports specific entry points and imports System API functions. The IC validates the module at install time: + +- The module must be a valid WebAssembly binary. +- Any System API imports must match the exact signatures defined in the spec. +- The module must not import memory with a minimum greater than 4 GiB. +- The module must not use features that the IC's Wasm engine does not support. + +## Canister interface (System API) + +The System API is the set of WebAssembly **import functions** provided by the IC to canister code. Canisters import these under the module name `"ic0"`. + +### Entry points + +The IC invokes canisters through well-defined **entry points** — exported WebAssembly functions with specific names: + +| Entry point | When invoked | +|---|---| +| `canister_init` | After code installation (`install` mode) | +| `canister_post_upgrade` | After code installation (`upgrade` mode) | +| `canister_pre_upgrade` | Before code replacement (during upgrade) | +| `canister_inspect_message` | Before accepting an ingress message (update calls only) | +| `canister_heartbeat` | Periodically by the IC (replicated) | +| `canister_global_timer` | When the canister's global timer fires | +| `canister_on_low_wasm_memory` | When Wasm heap approaches the configured threshold | +| `canister_update ` | Update method call | +| `canister_query ` | Query method call | +| `canister_composite_query ` | Composite query method call | + +Entry points run in either **replicated** mode (all replicas execute and must agree) or **non-replicated** mode (single replica). Update calls and heartbeats run replicated. Query calls and composite queries run non-replicated. + +### Replicated vs. non-replicated execution + +| Mode | Guarantees | Restrictions | +|---|---|---| +| Replicated | State mutations are committed; results are consensus-verified | Higher latency | +| Non-replicated | Fast; single-replica execution | State mutations are discarded; cannot make inter-canister calls (except composite query → composite query) | + +### System API import categories + +The System API is organized into functional groups: + +**Call context** — reading the current call's arguments, sender, method name, cycles attached: +- `ic0.msg_arg_data_copy` / `ic0.msg_arg_data_size` +- `ic0.msg_caller_copy` / `ic0.msg_caller_size` +- `ic0.msg_method_name_copy` / `ic0.msg_method_name_size` +- `ic0.msg_cycles_available128` / `ic0.msg_cycles_refunded128` +- `ic0.msg_reject_code` / `ic0.msg_reject_msg_copy` + +**Responding** — sending a reply or reject from the current call: +- `ic0.msg_reply_data_append` / `ic0.msg_reply` +- `ic0.msg_reject` + +**Inter-canister calls** — initiating calls to other canisters: +- `ic0.call_new` / `ic0.call_on_cleanup` +- `ic0.call_data_append` / `ic0.call_cycles_add128` +- `ic0.call_perform` + +**Canister identity** — reading own canister ID, version, and status: +- `ic0.canister_self_copy` / `ic0.canister_self_size` +- `ic0.canister_version` +- `ic0.canister_status` + +**Cycles** — managing cycle balances: +- `ic0.canister_cycle_balance128` +- `ic0.msg_cycles_accept128` +- `ic0.cycles_burn128` + +**Stable memory** — 64-bit stable memory read/write: +- `ic0.stable64_read` / `ic0.stable64_write` +- `ic0.stable64_size` / `ic0.stable64_grow` + +**Time and randomness** — reading the current time and accessing a per-message random seed: +- `ic0.time` +- `ic0.performance_counter` +- `ic0.is_controller` +- `ic0.in_replicated_execution` + +**Certified data** — writing the 32-byte certified data blob: +- `ic0.certified_data_set` + +**Logging** — emitting debug messages and printing: +- `ic0.debug_print` +- `ic0.trap` + +**Environment variables** — reading key-value pairs set in canister settings: +- `ic0.env_var_copy` / `ic0.env_var_size` + +**Low-memory hook** — configuring the threshold for `canister_on_low_wasm_memory`: +- `ic0.wasm_memory_size_hook` + +For CDK-level abstractions over these imports, see the [Rust CDK docs](https://docs.rs/ic-cdk/latest/ic_cdk/) and the [Motoko core library](https://mops.one/core/docs). + +### Ingress message inspection + +Before executing an ingress update call, the IC calls `canister_inspect_message` if it is exported. The entry point can accept or reject the call by calling `ic0.accept_message` or trapping. If `canister_inspect_message` is not exported, all ingress calls are accepted. + +`canister_inspect_message` runs non-replicated — it is a filter, not a security boundary for on-chain state. Any secrets or state-dependent authorization must be enforced inside the actual update method. + +## The IC management canister + +The **management canister** (`aaaaa-aa`) is a virtual canister that provides access to IC platform features. It is not a real Wasm canister — it is implemented directly in the IC protocol. + +The spec defines the full interface of the management canister. For a practical API reference with all methods and their parameters, see the [management canister reference](management-canister.md). + +Key method groups: + +| Category | Methods | +|---|---| +| Canister lifecycle | `create_canister`, `install_code`, `install_chunked_code`, `uninstall_code`, `start_canister`, `stop_canister`, `delete_canister`, `update_settings` | +| Canister inspection | `canister_status`, `canister_info`, `canister_metadata` | +| Chunk store | `upload_chunk`, `clear_chunk_store`, `stored_chunks` | +| Snapshots | `take_canister_snapshot`, `load_canister_snapshot`, `list_canister_snapshots`, `delete_canister_snapshot`, `read_canister_snapshot_metadata`, `read_canister_snapshot_data`, `upload_canister_snapshot_metadata`, `upload_canister_snapshot_data` | +| Chain-key signing | `ecdsa_public_key`, `sign_with_ecdsa`, `schnorr_public_key`, `sign_with_schnorr`, `vetkd_public_key`, `vetkd_derive_key` | +| HTTPS outcalls | `http_request` | +| Randomness | `raw_rand` | +| Cycles | `deposit_cycles` | +| Node metrics | `node_metrics_history`, `subnet_info` | +| Logs | `fetch_canister_logs` | + +## Certified data and certification + +Canister code can write a **32-byte certified data blob** using `ic0.certified_data_set`. This blob is included in the IC's system state tree at `/canister//certified_data`, and the tree root hash is signed by the subnet in every certified response. + +A client that wants to verify a query response can: +1. Request the certificate via `read_state` +2. Verify the subnet signature on the tree root +3. Walk the tree to retrieve the `certified_data` value +4. Verify that the data matches a commitment included in the query response + +This pattern allows query responses to carry verifiable commitments without requiring update calls. See the [certified variables guide](../guides/backends/certified-variables.md) for a practical implementation. + +## Certification + +The spec defines the structure of **certificates** — data structures that prove a value was part of the IC's state tree at a given time. A certificate contains: + +- A **tree** — a partial Merkle tree with the relevant path and leaf values +- A **signature** — a threshold BLS signature from the subnet over the tree root +- An optional **delegation chain** — proving the signing subnet was authorized by the NNS root key + +The root key of the IC is published in the status endpoint (`/api/v2/status`) and known to clients that want to verify certificates independently. + +For developer-facing information on response certification, see [certified variables](../guides/backends/certified-variables.md). + +## Bitcoin API + +The spec includes a dedicated **Bitcoin API** section covering integration with the Bitcoin network: + +| Method | Description | +|---|---| +| `bitcoin_get_utxos` | Query unspent transaction outputs for a Bitcoin address | +| `bitcoin_get_balance` | Get the balance of a Bitcoin address | +| `bitcoin_send_transaction` | Broadcast a signed Bitcoin transaction | +| `bitcoin_get_current_fee_percentiles` | Get current fee percentile data | +| `bitcoin_get_block_headers` | Read Bitcoin block headers | + +These are management canister methods used for the IC's native Bitcoin integration. For usage guidance, see the [Bitcoin integration guide](../guides/chain-fusion/bitcoin.md). + +## HTTP Gateway protocol + +The **HTTP Gateway protocol** describes how IC boundary nodes translate HTTP requests from browsers into canister calls, and how they verify and serve certified HTTP responses. + +The HTTP Gateway spec is a separate specification referenced from the main IC interface spec. For an overview, see the [HTTP Gateway spec page](http-gateway-spec.md). + +## Abstract behavior + +The final section of the IC interface spec provides a formal pseudocode description of the IC's abstract state machine. It defines: + +- The abstract state (canister queues, message routing, consensus inputs) +- State transition rules for every type of request and system event +- Ordering guarantees and synchronicity properties + +This section is aimed at protocol implementers and formal verification. It is not required reading for canister developers. + +## Relationship to other specifications + +| Topic | Where it lives | +|---|---| +| Management canister API reference | [management-canister.md](management-canister.md) | +| Candid type system and encoding | [candid-spec.md](candid-spec.md) | +| HTTP Gateway protocol | [http-gateway-spec.md](http-gateway-spec.md) | +| Canister-level certified data | [certified variables guide](../guides/backends/certified-variables.md) | +| Canister lifecycle operations | [lifecycle guide](../guides/canister-management/lifecycle.md) | + +## Next steps + +- Read the [management canister reference](management-canister.md) for a developer-friendly API reference. +- See the [certified variables guide](../guides/backends/certified-variables.md) to learn how to build verifiable query responses. +- Read the [Candid specification](candid-spec.md) for the interface description language used to encode method arguments and results. + + From 7be0b2d387466556218c9cb14fc002dca7c817b1 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 16 Apr 2026 17:08:21 +0200 Subject: [PATCH 2/2] fix(reference/ic-interface-spec): address PR feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove fabricated ic0.wasm_memory_size_hook (does not exist in spec) - Remove fabricated 4 GiB memory import constraint (not in spec); replace with the correct rule: module may declare at most one memory - Fix ingress_expiry description: clarify 5-minute window is implementation-defined, not normative spec text - Fix Derived principal "Reserved for future use" — spec says they may be used internally; update to accurate language - Rename ## Certification to ## Certificate structure to distinguish it from the programming model section above - Remove portal repository reference from intro (spec will live here) --- docs/reference/ic-interface-spec.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/reference/ic-interface-spec.md b/docs/reference/ic-interface-spec.md index dfaefc66..8968ea2f 100644 --- a/docs/reference/ic-interface-spec.md +++ b/docs/reference/ic-interface-spec.md @@ -9,7 +9,7 @@ The IC interface specification is the authoritative formal description of the In This page gives a structured overview of the spec's main sections to help you find what you need. The spec itself is precise and technically dense — it is the ground truth for behavior, error handling, and protocol invariants. -The full specification source is maintained in the `dfinity/portal` repository and is available as a reference document for tooling authors, CDK implementers, and protocol contributors. +The full specification is available as a reference document for tooling authors, CDK implementers, and protocol contributors. ## Who should read the IC interface spec @@ -33,7 +33,7 @@ Principals are the generic identifier type for canisters, users, and other entit |---|---|---| | Opaque | Generated by the IC | Canister IDs assigned by the IC | | Self-authenticating | `SHA-224(public_key) · 0x02` | External user identities | -| Derived | Hash of registering principal + nonce | Reserved for future use | +| Derived | Hash of registering principal and derivation nonce | May be used internally; not currently used in the public spec | | Anonymous | `0x04` | Unsigned calls | | Reserved | `blob · 0x7f` | Application-defined identifiers | @@ -138,7 +138,7 @@ Requests are authenticated by signing the request content. Anonymous requests us ### Ingress messages -An **ingress message** is a call submitted by an external user. The `ingress_expiry` field sets a deadline (up to 5 minutes in the future) after which the IC will not execute the call. Once submitted, the caller polls `/read_state` using the request ID to determine the outcome. +An **ingress message** is a call submitted by an external user. The `ingress_expiry` field sets a deadline (expressed in nanoseconds since the Unix epoch) after which the IC will not execute the call. The IC may refuse requests with an expiry too far in the future; the exact window is implementation-defined (the IC mainnet currently rejects requests with an ingress expiry more than 5 minutes in the future). Once submitted, the caller polls `/read_state` using the request ID to determine the outcome. ### Query calls @@ -170,7 +170,7 @@ A canister module is a **WebAssembly binary** (raw `.wasm` or gzip-compressed) t - The module must be a valid WebAssembly binary. - Any System API imports must match the exact signatures defined in the spec. -- The module must not import memory with a minimum greater than 4 GiB. +- The module may declare at most one memory. - The module must not use features that the IC's Wasm engine does not support. ## Canister interface (System API) @@ -253,9 +253,6 @@ The System API is organized into functional groups: **Environment variables** — reading key-value pairs set in canister settings: - `ic0.env_var_copy` / `ic0.env_var_size` -**Low-memory hook** — configuring the threshold for `canister_on_low_wasm_memory`: -- `ic0.wasm_memory_size_hook` - For CDK-level abstractions over these imports, see the [Rust CDK docs](https://docs.rs/ic-cdk/latest/ic_cdk/) and the [Motoko core library](https://mops.one/core/docs). ### Ingress message inspection @@ -297,7 +294,7 @@ A client that wants to verify a query response can: This pattern allows query responses to carry verifiable commitments without requiring update calls. See the [certified variables guide](../guides/backends/certified-variables.md) for a practical implementation. -## Certification +## Certificate structure The spec defines the structure of **certificates** — data structures that prove a value was part of the IC's state tree at a given time. A certificate contains: