<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.internetcomputer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jessie.mongeon</id>
	<title>Internet Computer Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.internetcomputer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jessie.mongeon"/>
	<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/wiki/Special:Contributions/Jessie.mongeon"/>
	<updated>2026-04-11T06:07:31Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_message_routing_layer&amp;diff=8462</id>
		<title>IC message routing layer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_message_routing_layer&amp;diff=8462"/>
		<updated>2025-07-08T13:15:19Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Internet Computer (IC) achieves its security and fault tolerance by replicating computation across node machines located in various independent data centers across the world. For scalability reasons, the Internet Computing Protocol (ICP) composes the IC of multiple independent subnets. Each subnet can be viewed as an independent replicated state machine that replicates its state over a subset of all the available nodes.&lt;br /&gt;
&lt;br /&gt;
Roughly speaking, replication is achieved by having the two lower ICP layers (P2P &amp;amp; Consensus) agree on blocks containing batches of messages to be executed, and then having the two upper ICP layers (Message Routing &amp;amp; Execution) execute them. Blocks are organized as a chain, where each block builds on the previous block. Each block has an associated height in the chain and one can look at execution of a batch of messages corresponding to the agreed upon block at height &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; by the upper layers as taking the replicated state of version &amp;lt;math&amp;gt;x-1&amp;lt;/math&amp;gt;, and &amp;quot;applying&amp;quot; the batch to it to obtain replicated state of version &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This document describes the role of the Message Routing layer in deterministic batch processing. Its responsibilities are:&lt;br /&gt;
* &#039;&#039;&#039;Coordinating the deterministic processing of batches:&#039;&#039;&#039; Fetching the right versions of the replicated state and the registry view to process the batch, triggering the deterministic processing, and committing the resulting replicated state.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Deterministic processing of batches:&#039;&#039;&#039; Deterministic processing of batches relative to some replicated state and some registry view, resulting in an updated replicated state.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Transferring message streams from one subnet to another:&#039;&#039;&#039; Moving streams from one subnet to another.&lt;br /&gt;
&lt;br /&gt;
=== Remarks and Required Prior Knowledge ===&lt;br /&gt;
&lt;br /&gt;
* The goal of this document is to provide the next level of detail compared to the material in the [https://internetcomputer.org/how-it-works &amp;quot;How it works&amp;quot; section of internetcomputer.org]. So it is recommended to study the material available there first.&lt;br /&gt;
* This page builds upon definitions made in the page describing the [[IC state manager|state manager]]. Please refer to this page for missing definitions related to the replicated state etc.&lt;br /&gt;
* Also see [https://mmapped.blog/posts/08-ic-xnet.html this] and [https://mmapped.blog/posts/02-ic-state-machine-replication.html this] blog post for some relevant and easier to digest background information.&lt;br /&gt;
* The documentation provided in this page may slightly deviate from the current implementation in terms of API as well as naming of functions, variables, etc. However, it still conveys the high-level ideas required to understand how the component itself works and how it interacts with other components. The implementation also contains several optimizations which are, however, not important for the conceptual overview here and therefore skipped.&lt;br /&gt;
* The notation used in this page is described [[Notation|here]].&lt;br /&gt;
&lt;br /&gt;
=== Replicated vs. Canonical State ===&lt;br /&gt;
While the external API functions defined in this document will always take state in its implementation specific representation, i.e., as &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt;, the operation the message routing component performs on the state based on its canonical representation, i.e., the &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is described. Given the relations between &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; as defined in the specification of the state manager, this will implicitly define how an implementation needs to act on the respective parts of the &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt;. An implicit conversion from &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is assumed whenever some state passed to this component via an API function is accessed.&lt;br /&gt;
&lt;br /&gt;
== Guarantees Provided by Message Routing ==&lt;br /&gt;
Intuitively, the goal of the message routing layer is to enable transparent communication of canisters across subnets. This means that this layer formally does not add any guarantees the system provides, but simply needs to make sure that system invariants are preserved. Those system invariants include&lt;br /&gt;
&lt;br /&gt;
* guaranteed replies (each canister-to-canister request will eventually receive a reply),&lt;br /&gt;
&lt;br /&gt;
* canister-to-canister ordering (the order of canister-to-canister requests sent from one canister to another canister is preserved), and&lt;br /&gt;
&lt;br /&gt;
* authenticity (only messages that come from canisters on the IC are processed).&lt;br /&gt;
&lt;br /&gt;
To ensure that the system invariants hold, message routing needs to provide the following guarantees:&lt;br /&gt;
&lt;br /&gt;
* Canister-to-canister messages will eventually be passed to the execution layer at the subnet the destination canister lives on exactly once.&lt;br /&gt;
&lt;br /&gt;
* If a message can not be delivered, a synthetic reject response must be produced.&lt;br /&gt;
&lt;br /&gt;
* If a canister &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; sends two messages &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; to a canister &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, then, if none of them gets synthetically rejected, it must be guaranteed that they are put in canister &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&#039;s input queue from &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; in that order.&lt;br /&gt;
&lt;br /&gt;
== Preliminaries ==&lt;br /&gt;
=== Description of the Relevant Parts of the Registry ===&lt;br /&gt;
The registry can be viewed as a central store of configuration information of the IC that is maintained by the NNS DAO. The content of the registry is held by a canister on the NNS subnet, and, roughly speaking, its authenticity is guaranteed by obtaining a certification on the content on behalf of the NNS using the certification mechanism as described in the [[IC state manager|state manager]] wiki page. Throughout this document it is assume that the registry contents are authentic.&lt;br /&gt;
&lt;br /&gt;
The registry entries required by this component are set of all existing subnet ids, as well as a canister-to-subnet mapping subnet_assignment. Note that the actual implementation may choose to represent the required fields differently as long as they are conceptually equivalent.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Registry {&lt;br /&gt;
    subnets : Set&amp;lt;SubnetId&amp;gt;,&lt;br /&gt;
	subnet_assignment: CanisterId ↦ SubnetId&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description of the Relevant Canonical State ===&lt;br /&gt;
This section defined the parts of the canonical state which are relevant for the description of this component together with some constraints imposed on the replicated state. Abstractly the &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is defined as a nested partial map. For easier readability the entries of the outermost map are bundled together in a data structure with multiple fields where the names of the fields represent the keys in the respective partial map, e.g., for some &amp;lt;code&amp;gt;s : CanonicalState&amp;lt;/code&amp;gt; one can use &amp;lt;code&amp;gt;s.ingress_queue&amp;lt;/code&amp;gt; to access &amp;lt;code&amp;gt;s[ingress_queues]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section defines the individual fields of the type &amp;lt;/code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; which are relevant in the context of this document. After that there are more details about the datatypes of the individual fields. There is a distinction made between the parts which are exclusively visible to message routing, and the parts which are also visible to the execution layer.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parts visible to message routing and execution&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CanonicalState {&lt;br /&gt;
    ...&lt;br /&gt;
    ingress_queues  : IngressQueues,&lt;br /&gt;
    input_queues    : InputQueues,&lt;br /&gt;
    output_queues   : OutputQueues,&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parts visible to Message Routing only&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CanonicalState {&lt;br /&gt;
    ...&lt;br /&gt;
    streams               : Streams,&lt;br /&gt;
    expected_xnet_indices : Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Even though there are parts of the state that are accessed by both message routing and execution, one can enforce a conceptual boundary between them. In particular, for input queues, message routing will only ever push messages to them, whereas for output queues, message routing will only ever pull messages from them. The opposite holds for the execution environment.&lt;br /&gt;
&lt;br /&gt;
==== Abstract Queues ====&lt;br /&gt;
Define a generic queue type &amp;lt;code&amp;gt;Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; which has the following fields:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Queue&amp;lt;T&amp;gt; {&lt;br /&gt;
    next_index : ℕ,     // Rolling index; the index of the next message to be inserted&lt;br /&gt;
    elements   : ℕ ↦ T  // The elements currently in the queue&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Define a new queue as &amp;lt;code&amp;gt;new_queue : Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;new_queue.elements = ∅&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;new_queue.next_index = 1&amp;lt;/code&amp;gt;. Furthermore, it has the following associated functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; takes a queue and a partial map of integers mapping to T, and returns a new queue consisting of the old queue with the given values appended. It also updates the next_index field so that it points to the index after the last inserted message.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;push : Self × (ℕ ↦ T) → Self&lt;br /&gt;
push(self, values) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index + |values|&lt;br /&gt;
            └─ elements := self.elements&lt;br /&gt;
                           ∪ { (i - 1 + k ↦ t) | i = self.next_index ∧&lt;br /&gt;
                                                 (j ↦ t) ∈ values ∧&lt;br /&gt;
                                                 k = rank(j, dom(values)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; removes the given elements from the queues keeping the &amp;lt;code&amp;gt;next_index&amp;lt;/code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% REQUIRE: values ⊆ self.elements&lt;br /&gt;
delete : Self × (ℕ ↦ T) → Self&lt;br /&gt;
delete(self, values) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index&lt;br /&gt;
            └─ elements := self.elements&lt;br /&gt;
                           \ values&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;clear&amp;lt;/code&amp;gt; removes all elements from the queues keeping the next_index&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;clear : Self → Self&lt;br /&gt;
clear(self) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index&lt;br /&gt;
            └─ elements := ∅&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Partial maps of type &amp;lt;code&amp;gt;SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; are often used, in which case the following shorthand notation is used. With &amp;lt;code&amp;gt;q&amp;lt;/code&amp;gt; being a queue of the aforementioned type, and &amp;lt;code&amp;gt;v&amp;lt;/code&amp;gt; being a partial map of type &amp;lt;code&amp;gt;(SomeIdentifier × ℕ) ↦ T&amp;lt;/code&amp;gt;, define the following semantic for the functions &amp;lt;code&amp;gt;f ∈ { push, delete }&amp;lt;/code&amp;gt; associated to &amp;lt;code&amp;gt;Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;f_map : (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;) × ((SomeIdentifier × ℕ) ↦ T) → (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;)&lt;br /&gt;
f_map(q, v) = { (id ↦ queue&#039;) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                                (id ↦ values) ∈ v ∧&lt;br /&gt;
                                queue&#039; = f(queue, values)&lt;br /&gt;
              } ∪&lt;br /&gt;
              { (id ↦ queue&#039;) | (id ↦ values) ∈ v ∧&lt;br /&gt;
                                ∄ (id ↦ ·) ∈ q ∧&lt;br /&gt;
                                queue&#039; = f(Queue&amp;lt;T&amp;gt;::new_queue, values)&lt;br /&gt;
              } ∪&lt;br /&gt;
              { (id ↦ queue) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                               ∄ (id ↦ ·) ∈ v&lt;br /&gt;
              }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the functions &amp;lt;code&amp;gt;f ∈ { clear }&amp;lt;/code&amp;gt; use&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;f_map : (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;) → (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;)&lt;br /&gt;
f_map(q) = { (id ↦ queue&#039;) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                             queue&#039; = f(queue)&lt;br /&gt;
           }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Henceforth the &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; postfix will be omitted in &amp;lt;code&amp;gt;f_map&amp;lt;/code&amp;gt; and simply use &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; if it is clear from the input type that the map variant of &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; should be used.&lt;br /&gt;
&lt;br /&gt;
==== Indices ====&lt;br /&gt;
Define an &amp;lt;code&amp;gt;Index&amp;lt;/code&amp;gt; to be an arbitrary length sequence, where every element in the sequence up to the last one can have an arbitrary type, and the last one is a natural number.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Index : X × ... × Y × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition the following semantic is defined:&lt;br /&gt;
&lt;br /&gt;
* Define the prefix of an index Index &amp;lt;code&amp;gt;i := (x, …​, y, seq_nr)&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;prefix(i) := i[1…​|i| - 1] = (x, …​, y)&amp;lt;/code&amp;gt;, i.e., it contains all elements of i except the last one.&lt;br /&gt;
&lt;br /&gt;
* Define the postfix of an Index &amp;lt;code&amp;gt;i := (x, …​, y, seq_nr)&amp;lt;/code&amp;gt; as &amp;lt;/code&amp;gt;postfix(i) := i[|i|] = seq_nr&amp;lt;/code&amp;gt;, i.e., the last element of the index sequence. As already mentioned, the postfix of an index is required to be a natural number.&lt;br /&gt;
&lt;br /&gt;
* For an &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt;, the operation &amp;lt;math&amp;gt;i + 1&amp;lt;/math&amp;gt; is defined as &amp;lt;code&amp;gt;concatenate(prefix(i), postfix(i) + 1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Two indices, &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Index j&amp;lt;/code&amp;gt;, are incomparable if &amp;lt;code&amp;gt;prefix(i) ≠ prefix(j)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* For two indices, &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Index j&amp;lt;/code&amp;gt;, it is the case that &amp;lt;math&amp;gt;i \leq j&amp;lt;/math&amp;gt; if &amp;lt;code&amp;gt;prefix(i) = prefix(j)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;postfix(i) ≤ postfix(j)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Queues ====&lt;br /&gt;
&lt;br /&gt;
Three different types of queues exist in the replicated state: ingress queues, input queues, and output queues. Ingress queues contain the incoming messages from users (i.e., ingress messages). Input queues contain the incoming canister-to-canister messages. Output queues contain the outgoing canister-to-canister messages.&lt;br /&gt;
&lt;br /&gt;
Ingress queues are organized on a per destination basis. Messages in ingress queues are indexed by a concrete instance of Index called &amp;lt;code&amp;gt;IngressIndex&amp;lt;/code&amp;gt;, which is a tuple consisting of the destination canister ID and a natural number, i.e.,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;IngressIndex : CanisterId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Input queues and output queues are organized on a per-source-and-destination basis. Messages in input- and output queues are indexed by a concrete instance of Index called QueueIndex, which is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;QueueIndex : CanisterId × CanisterId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The type representing all of the ingress queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;IngressQueues : CanisterId ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;IngressQueues.elements : IngressIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The type representing all of the input queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;InputQueues : (CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;InputQueues.elements : QueueIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The type representing all of the output queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;OutputQueues : (CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;OutputQueues.elements : QueueIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Streams ====&lt;br /&gt;
Each individual &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; is scoped to a pair of subnets—​the subnet a stream originates from and subnet the stream is targeted at. An individual stream is organized in multiple substreams identified by a &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt;. The concrete definition of &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; is up to the implementation. In the current implementation &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; is defined to be the unit type &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;, i.e., flat streams. Messages in streams are indexed by a concrete instance of &amp;lt;code&amp;gt;Index&amp;lt;/code&amp;gt; called StreamIndex which is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;StreamIndex : SubstreamId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
A &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; is comprised of a sequence of &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; messages &amp;lt;code&amp;gt;signals&amp;lt;/code&amp;gt; and a sequence of canister-to-canister messages &amp;lt;code&amp;gt;msgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Stream {&lt;br /&gt;
    signals : StreamIndex ↦ {ACCEPT, REJECT},&lt;br /&gt;
    msgs    : SubstreamId ↦ Queue&amp;lt;Message&amp;gt;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;Stream.msgs.elements : StreamIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
While the subnet the stream originates from is implicitly determined, the target subnet needs to be made explicit. Hence, a data structure Streams is defined holding all streams indexed by destination subnetwork:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Streams : SubnetId ↦ Stream&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notation may be sometimes abused and directly access the fields defined for an individual &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; on the Streams type, in which case maps of the following type are obtained:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Streams.signals : SubnetId ↦ (StreamIndex ↦ {ACCEPT, REJECT})&lt;br /&gt;
&lt;br /&gt;
Streams.msgs    : SubnetId ↦ (SubstreamId ↦ Queue&amp;lt;Message&amp;gt;)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== (Certified) Stream Slices ====&lt;br /&gt;
&amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt;, respectively, are used to transport streams from one to an other subnet within &amp;lt;code&amp;gt;XNetPayloads&amp;lt;/code&amp;gt; that are part of consensus blocks. Essentially, a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; is a slice of a stream which retains the begin and the end of the original stream. A &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; is wrapped in a &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; for transport so that authenticity can be guaranteed. Neither &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt; nor &amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; are ever explicitly created within message routing, but instead one relies on the encoding and decoding routines provided by the state manager: A &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; is created by calling the respective encoding routine of the state manager. Such a &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; can then be decoded into a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; using the corresponding decoding routine provided by the state manager.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;StreamSlice {&lt;br /&gt;
    stream    : Stream,&lt;br /&gt;
    begin     : Set&amp;lt;StreamIndex&amp;gt;,&lt;br /&gt;
    end       : Set&amp;lt;StreamIndex&amp;gt;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CertifiedStreamSlice {&lt;br /&gt;
    payload   : PartialCanonicalState&lt;br /&gt;
    witness   : Witness&lt;br /&gt;
    signature : Certification&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the precise relation of &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt;, refer to the specification of the state manager.&lt;br /&gt;
&lt;br /&gt;
==== Batch ====&lt;br /&gt;
A batch consists of multiple elements including an &amp;lt;code&amp;gt;ingress_payload&amp;lt;/code&amp;gt; constituting a sequence of ingress messages, and an &amp;lt;code&amp;gt;xnet_payload&amp;lt;/code&amp;gt;.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Batch {&lt;br /&gt;
    batch_number             : Height&lt;br /&gt;
    registry_version         : RegistryVersion&lt;br /&gt;
    ingress_payload          : ℕ ↦ Message&lt;br /&gt;
    xnet_payload             : SubnetId ↦ CertifiedStreamSlice&lt;br /&gt;
    requires_full_state_hash : { TRUE, FALSE }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Decoded Batch ====&lt;br /&gt;
A decoded batch represents a batch where all transport-specific things are decoded into the format suitable for processing and some things which are not required inside the deterministic state machine are stripped off.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;DecodedBatch {&lt;br /&gt;
    ingress_payload : ℕ ↦ Message&lt;br /&gt;
    xnet_payload : SubnetId ↦ StreamSlice&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Currently this only means decoding the &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; because it is assumed that the ingress payload is suitable to be processed right away. Formally there is a function, which, based on the own subnet id and the given batch decodes the batch into a decoded batch:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;decode : SubnetId × Batch → DecodedBatch&lt;br /&gt;
decode(own_subnet, b) :=&lt;br /&gt;
    DecodedBatch {&lt;br /&gt;
        with&lt;br /&gt;
           ├─ ingress_payload := b.ingress_payload&lt;br /&gt;
           └─ xnet_payload :=&lt;br /&gt;
                  { (src_subnet ↦ slice) |&lt;br /&gt;
                      (src_subnet ↦ cert_slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                      slice = StateManager.decode_valid_certified_stream(own_subnet,&lt;br /&gt;
                                                                         cert_slice&lt;br /&gt;
                                                                        )&lt;br /&gt;
                  }&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Message Routing ==&lt;br /&gt;
Message routing is triggered by incoming batches from consensus. For each &amp;lt;code&amp;gt;Batch b&amp;lt;/code&amp;gt;, message routing will perform the following steps:&lt;br /&gt;
[[File:Message Routing Components.png|thumb|Components interacting with message routing during a deterministic processing round]]&lt;br /&gt;
[[File:MR Interactions.png|thumb|Interactions of message routing with other components during a deterministic processing round]]&lt;br /&gt;
&lt;br /&gt;
* Obtain the &amp;lt;code&amp;gt;ReplicatedState s&amp;lt;/code&amp;gt; of the right version w.r.t. &amp;lt;code&amp;gt;Batch b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Submit &amp;lt;code&amp;gt;s&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;decode(own_subnet, b)&amp;lt;/code&amp;gt; for processing by the deterministic state machine comprised of the message routing and execution layer. This includes&lt;br /&gt;
&lt;br /&gt;
** An induction phase (cf. &amp;lt;code&amp;gt;pre_process&amp;lt;/code&amp;gt;), where the valid messages in &amp;lt;code&amp;gt;decode(own_subnet, b)&amp;lt;/code&amp;gt; are inducted. Among others, a message m in a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; from subnet &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; is considered valid if &amp;lt;code&amp;gt;registry.get_registry_at(b.registry_version).subnet_assignment&amp;lt;/code&amp;gt; maps &amp;lt;code&amp;gt;m.src&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
** An execution phase (cf. &amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;), which executes messages available in the induction pool.&lt;br /&gt;
&lt;br /&gt;
** An XNet message routing phase (cf. &amp;lt;code&amp;gt;post_process&amp;lt;/code&amp;gt;), which moves the messages produced in the execution phase from the per-session output queues to the subnet-to-subnet streams according to the mapping defined by the subnet assignment in the registry.&lt;br /&gt;
&lt;br /&gt;
* Commit the replicated state, incrementally updated by the previous steps, to the state manager via &amp;lt;code&amp;gt;commit_and_certify&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Deterministic State Machine ===&lt;br /&gt;
As shown in the sequence diagram above, the deterministic state machine implemented by message routing and execution applies batches provided by consensus to the appropriate state, additionally using some meta information provided by the registry. As discussed above, state of type &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is used to generally describe the operations of the message-routing-related operations of this component.&lt;br /&gt;
&lt;br /&gt;
[[File:Message-routing-data-flow.png|thumb|Data flow during batch processing]]&lt;br /&gt;
&lt;br /&gt;
The flow diagram below details the operation of the component. Its operation is logically split into three phases.&lt;br /&gt;
&lt;br /&gt;
* The induction phase, where the messages contained in the batch are preprocessed. This includes extracting them from the batch and, subject to their validity and the decision of VSR, added to the induction pool or not.&lt;br /&gt;
&lt;br /&gt;
* The execution phase, where the hypervisor is triggered to perform an execution cycle. The important thing from a message routing perspective is that it will take messages from the input queues and process them, which causes messages to be added to the output queues.&lt;br /&gt;
&lt;br /&gt;
* The XNet message routing phase, where the messages produced in the execution cycle are post-processed. This means that they are taken from the canister-to-canister output queues and routed into the appropriate subnet-to-subnet streams.&lt;br /&gt;
&lt;br /&gt;
All messages will be added to the respective destination queue/stream preserving the order they appear in the respective source stream/queue.&lt;br /&gt;
&lt;br /&gt;
==== API ====&lt;br /&gt;
The deterministic state machine does not provide any external API functions. It only provides the following functions resembling the state transformations implemented by the individual steps of the deterministic state machine depicted above. Refer to the previous section for context regarding when the individual functions are called.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;pre_process(s : CanonicalState, subnet_assignment : (CanisterId ↦ SubnetId), b : DecodedBatch) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the induction phase.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;execute(s : CanonicalState) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the execution phase.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;post_process(s : CanonicalState, subnet_assignment : (CanisterId ↦ SubnetId)) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the XNet message routing phase.&lt;br /&gt;
&lt;br /&gt;
==== Abstractions of Other Parts of the System ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Valid Set Rule (VSR)&#039;&#039;&#039;&lt;br /&gt;
The VSR is a component that makes the decision of whether to &amp;lt;code&amp;gt;ACCEPT&amp;lt;/code&amp;gt; a message or to &amp;lt;code&amp;gt;REJECT&amp;lt;/code&amp;gt; a message. For message routing, &amp;lt;code&amp;gt;ACCEPT&amp;lt;/code&amp;gt; has the semantic that the execution layer takes responsibility for the message, whereas &amp;lt;code&amp;gt;REJECT&amp;lt;/code&amp;gt; has the semantic that the message is dropped and may require action from the message routing layer.&lt;br /&gt;
&lt;br /&gt;
The operation of the VSR on ingress messages is defined as follows, where &amp;lt;code&amp;gt;vsr_check_ingress : CanonicalState × Batch → Set&amp;lt;ℕ&amp;gt;&amp;lt;/code&amp;gt; is a deterministic function returning the indices of the messages in the ingress payload accepted by the VSR, which returns a possibly empty set of index-message tuples corresponding to the accepted messages in the ingress_payload of the batch. The set is determined by the concrete implementation of the VSR.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;VSR(state, batch).ingress :=&lt;br /&gt;
  { ((m_i.dst, j) ↦ m_i) | (i ↦ m_i) ∈ batch.ingress_payload&lt;br /&gt;
                           ∧ i ∈ vsr_check_ingress(state, batch)&lt;br /&gt;
                           ∧ j = Rank(i, vsr_check_ingress(state, batch))&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The VSR for cross-net messages is defined as follows, where &amp;lt;code&amp;gt;vsr_check_xnet : CanonicalState × Batch → Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&amp;lt;/code&amp;gt; is a deterministic function that determines the indices of the messages in the individual substreams contained in &amp;lt;code&amp;gt;xnet_payload&amp;lt;/code&amp;gt; to be inducted.&lt;br /&gt;
&lt;br /&gt;
It is required that the implementation of the VSR (or the layer above) makes sure that all reply messages are accepted by the VSR. Formally this means that for any valid State-Batch combination &amp;lt;code&amp;gt;(s, b)&amp;lt;/code&amp;gt; it holds that for all &amp;lt;code&amp;gt;(subnet, index)&amp;lt;/code&amp;gt; so that &amp;lt;code&amp;gt;b.xnet_payload[subnet].msgs[index]&amp;lt;/code&amp;gt; is a reply message that &amp;lt;code&amp;gt;(subnet, index) ∈ vsr_check_xnet(s, b)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Based on this rule one can straight-forwardly define the interface behavior of the VSR.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;VSR(state, batch).xnet :=&lt;br /&gt;
  { (index ↦ msg) |&lt;br /&gt;
      (index ↦ msg) ∈ batch.xnet_payload.msgs ∧&lt;br /&gt;
      index ∈ vsr_check_xnet(state, batch)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
VSR(state, batch).signals :=&lt;br /&gt;
    { (concatenate(subnet, index) ↦ ACCEPT) |&lt;br /&gt;
      (subnet ↦ stream) ∈ batch.xnet_payload ∧&lt;br /&gt;
      (index ↦ msg) ∈ stream.msgs ∧&lt;br /&gt;
      (subnet, index) ∈ vsr_check_xnet(state, batch)&lt;br /&gt;
    }&lt;br /&gt;
  ∪ { (concatenate(subnet, index) ↦ REJECT) |&lt;br /&gt;
      (subnet ↦ stream) ∈ batch.xnet_payload ∧&lt;br /&gt;
      (index ↦ msg) ∈ stream.msgs ∧&lt;br /&gt;
      (subnet, index) ∉ vsr_check_xnet(state, batch)&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Scheduler and Hypervisor&#039;&#039;&#039;. From the point of view of message routing, one can look at the the scheduler and the hypervisor together as one component. The functionality of scheduler and hypervisor are modeled as a deterministic function &amp;lt;code&amp;gt;schedule_and_execute : CanonicalState → (IngressIndex ↦ Message) × (QueueIndex ↦ Message) × (QueueIndex ↦ Message)&amp;lt;/code&amp;gt; which computes the change set introduced by the Scheduler and the Hypervisor. It takes messages from the input queues, executes them and puts new messages to the output queues.&lt;br /&gt;
&lt;br /&gt;
This function will be used lated when it&#039;s described how the state transition function &amp;lt;code&amp;gt;execute(CanonicalState) → CanonicalState&amp;lt;/code&amp;gt; transforms the state. For the sake of compact notation, the following fields are used to access the individual return values of the schedule_and_execute function.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;consumed_ingress_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;IngressIndex ↦ Message&amp;lt;/code&amp;gt; containing all consumed ingress messages.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;consumed_xnet_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;QueueIndex ↦ Message&amp;lt;/code&amp;gt; containing all consumed cross-net messages.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;produced_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;QueueIndex ↦ Message&amp;lt;/code&amp;gt; containing all produced messages, where the order of the messages implied by the queue index determines the order in which they need to be added to the queues.&lt;br /&gt;
&lt;br /&gt;
==== Description of the State Transitions ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Induction Phase&#039;&#039;&#039;. In the induction phase, one starts off with a &amp;lt;code&amp;gt;CanonicalState S&amp;lt;/code&amp;gt;, some &amp;lt;code&amp;gt;subnet_assignment&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;DecodedBatch b&amp;lt;/code&amp;gt; and applies &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; relative to &amp;lt;code&amp;gt;subnet_assignment&amp;lt;/code&amp;gt; to obtain &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt;, i.e., one computes &amp;lt;code&amp;gt;S&#039; = pre_process(S, subnet_assignment, b)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This section describes things w.r.t. to a version of the VSR which will accept all messages, while in reality the VSR may reject some messages in case canisters migrate across subnets or subnets are split. So while the possibility that messages can be REJECTed by the VSR would require specific action of the message routing layer those actions are omitted here for simplicity as they are not crucial to understand the basic functionality of message routing.&lt;br /&gt;
&lt;br /&gt;
Before defining the actual state transition, a couple of helper functions are defined. First, it is needed to define a function that determines the order of the messages in the queues based on the order of the messages in the incoming stream slices.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% REQUIRES: ∄ (s1 ↦ m1), (s2 ↦ m2) ∈ S :&lt;br /&gt;
%           └─ m1 = m2 ∧ s1 ≠ s2&lt;br /&gt;
%&lt;br /&gt;
% ENSURES: ∀ S satisfying the precondition above,&lt;br /&gt;
%          └─ ∀ (q1 ↦ m1), (q2 ↦ m2) ∈ queue_index(S) :&lt;br /&gt;
%             ├─ ∃ s1, s2 :&lt;br /&gt;
%             │  └─ (s1 ↦ m1) ∈ S ∧ (s2 ↦ m2) ∈ S ∧&lt;br /&gt;
%             └─ (m1.dst = m2.dst ∧ s1 ≤ s2) ==&amp;gt; q1 ≤ q2&lt;br /&gt;
%&lt;br /&gt;
queue_index: ((SubnetId × StreamIndex) ↦  Message) → ((CanisterId × ℕ) ↦ Message))&lt;br /&gt;
queue_index(S) := {&lt;br /&gt;
  % There is no concrete implementation of this function provided as there are&lt;br /&gt;
  % multiple possible implementations and the choice for one also depends on&lt;br /&gt;
  % how priorities/fairness etc. are handled.&lt;br /&gt;
  %&lt;br /&gt;
  % A trivial implementation is to iterate over the given stream slices S per&lt;br /&gt;
  % subnet and for each individual slice iterate over all the messages in the&lt;br /&gt;
  % order they appear in the slice and push each message m on the right queue,&lt;br /&gt;
  % i.e., the one belonging to the destination canister. This is also the way&lt;br /&gt;
  % things are currently implemented.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Based on this a function can now be defined that maps over the indexes of the valid XNet messages.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;map_valid_xnet_messages : (SubnetId ↦ Slice) ×&lt;br /&gt;
                          (CanisterId ↦ SubnetId) →&lt;br /&gt;
                          ((CanisterId × ℕ) ↦ Message)&lt;br /&gt;
map_valid_xnet_messages(slices, subnet_assignment) :=&lt;br /&gt;
    queue_index({ ((subnet, index) ↦ m) | (subnet ↦ slice) ∈ slices ∧&lt;br /&gt;
                                          (index ↦ m) ∈ slice.msgs ∧&lt;br /&gt;
                                          subnet_assignment[m.src] = subnet ∧&lt;br /&gt;
&lt;br /&gt;
               })&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;pre_process(S, b)&amp;lt;/code&amp;gt; can be defined:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Append the ingress messages accepted by the VSR to the appropriate ingress_queue&lt;br /&gt;
  ingress_queues            := push(S.ingress_queues, VSR(S, b).ingress)&lt;br /&gt;
&lt;br /&gt;
  % Append the canister to canister messages accepted by the VSR to the appropriate&lt;br /&gt;
  % input queue.&lt;br /&gt;
  input_queues              := push(S.input_queues,&lt;br /&gt;
                                    map_valid_xnet_messages(VSR(S, b).xnet, subnet_assignment)&lt;br /&gt;
                                   )&lt;br /&gt;
&lt;br /&gt;
  % Garbage collect the messages which have accepted by the target subnet.&lt;br /&gt;
  % (As soon as the VSR does no longer ACCEPT all messages, one would have&lt;br /&gt;
  %  to make sure that rejected messages are appropriately re-enqueued in&lt;br /&gt;
  %  the streams)&lt;br /&gt;
  streams.msgs              := delete(S.streams.msgs,&lt;br /&gt;
                                 { (concatenate(subnet, index) ↦ msg) |&lt;br /&gt;
                                       (subnet ↦ slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                                       (i ↦ ·) ∈ slice.signals ∧&lt;br /&gt;
                                       index = concatenate(subnet, i)&lt;br /&gt;
                                 }&lt;br /&gt;
                               )&lt;br /&gt;
&lt;br /&gt;
  % Add the signals reflecting the decisions made by the VSR in the current round and&lt;br /&gt;
  % garbage collect the signals which have already been processed on the other subnet&lt;br /&gt;
  % (one knows that a signal has been processed when the message is no longer included&lt;br /&gt;
  % in a given slice).&lt;br /&gt;
  streams.signals           := S.streams.signals&lt;br /&gt;
                               ∪ VSR(S, b).signals&lt;br /&gt;
                               \ { (index ↦ signal) |&lt;br /&gt;
                                       (subnet ↦ slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                                       (i ↦ signal) ∈ S.streams[subnet].signals ∧&lt;br /&gt;
                                       index = concatenate(subnet, i) ∧&lt;br /&gt;
                                       j ∈ slice.begin ∧&lt;br /&gt;
                                       i &amp;lt; j&lt;br /&gt;
                                 }&lt;br /&gt;
&lt;br /&gt;
  % Update the expected XNet indexes so that the block maker can compute which messages&lt;br /&gt;
  % to include in a block referencing this state.&lt;br /&gt;
  expected_xnet_indices     := { index     | index ∈ S.expected_xnet_indices ∧&lt;br /&gt;
                                             ∄ (i ↦ ·) ∈ b.xnet_payload.msgs.elements :&lt;br /&gt;
                                             └─ prefix(index) = prefix(i)&lt;br /&gt;
                               } ∪&lt;br /&gt;
                               { index + 1 | index ∈ max(dom(b.xnet_payload.msgs.elements)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Execution Phase&#039;&#039;&#039;. In the execution phase, one starts off with a &amp;lt;code&amp;gt;CanonicalState S&amp;lt;/code&amp;gt;, schedules messages for execution by the hypervisor, and triggers the hypervisor to execute them, i.e., one computes &amp;lt;code&amp;gt;S&#039; = execute(S)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; is the state after the induction phase. From the perspective of message routing, the state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;execute(S)&amp;lt;/code&amp;gt; looks as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Delete the consumed ingress messages from the respective ingress queues&lt;br /&gt;
  ingress_queues    := delete(S.ingress_queue, schedule_and_execute(S).consumed_ingress_messages)&lt;br /&gt;
&lt;br /&gt;
  % Delete the consumed canister to canister messages from the respective input queues&lt;br /&gt;
  input_queues      := delete(S.input_queues, schedule_and_execute(S).consumed_xnet_messages)&lt;br /&gt;
&lt;br /&gt;
  % Append the produced messages to the respective output queues&lt;br /&gt;
  output_queues     := push(S.output_queues, schedule_and_execute(S).produced_messages)&lt;br /&gt;
&lt;br /&gt;
  % Execution specific state is transformed by the execution environment; the precise transition&lt;br /&gt;
  % function is out of scope here.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XNet Message Routing Phase&#039;&#039;&#039;. In the XNet message routing phase, one takes all the messages from the canister-to-canister output queues and, according to the subnet_assignment, puts them into a subnet-to-subnet stream, i.e., it computes &amp;lt;code&amp;gt;S&#039; = post_process(S, registry)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; is the state after the execution phase and registry represents a view of the registry.&lt;br /&gt;
&lt;br /&gt;
Before defining the state transition, a helper function is defined to appropriately handle messages targeted at canisters that do not exist according to the given subnet assignment.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Remove all messages from output queues targeted at non-existent canisters according&lt;br /&gt;
% to the subnet assignment.&lt;br /&gt;
filter : ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;) × (CanisterId ↦ SubnetId) → ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;)&lt;br /&gt;
filter(queues, subnet_assignment) :=&lt;br /&gt;
    delete(queues, { (q_index ↦ msg) | (q_index ↦ msg) ∈ queues.elements ∧&lt;br /&gt;
                                       q_index = (·, dst, ·) ∧&lt;br /&gt;
                                       dst ∉ dom(subnet_assignment)&lt;br /&gt;
                   }&lt;br /&gt;
          )&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Produce &amp;lt;code&amp;gt;NON_EXISTENT_CANISTER&amp;lt;/code&amp;gt; replies telling the sending canister that the destination canister does not exist.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Produce NON_EXISTENT_CANISTER messages to be pushed to input queues &lt;br /&gt;
% of the senders of messages where the destination does not exist&lt;br /&gt;
non_existent_canister_replies : ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;) × (CanisterId ↦ SubnetId) → (QueueIndex ↦ Message)&lt;br /&gt;
non_existent_canister_replies(queues, subnet_assignment) :=&lt;br /&gt;
  { ((dst, src, i) ↦ NON_EXISTENT_CANISTER) | (q_index ↦ msg) ∈ queues.elements ∧&lt;br /&gt;
                                              q_index = (src, dst, i) ∧&lt;br /&gt;
                                              dst ∉ dom(subnet_assignment)&lt;br /&gt;
  })&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Non flat streams.&#039;&#039; As already mentioned before, the specification leaves it open whether one flat stream is produced per destination subnet, or whether each of the streams has multiple substreams—​this can be decided by the implementation. To enable this, a &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be a tuple of &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; and a natural number. If there is a flat stream, &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be the unit type &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt; which effectively means that the implementation can use natural numbers as stream index as one does not need to make the &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; explicit in this case. In contrast, if there is a per-destination (or per-source) substreams, &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be a &amp;lt;code&amp;gt;CanisterId&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Formally, this means that the implementation must fix a mapping function that—​based on a given prefix of a &amp;lt;code&amp;gt;QueueIndex&amp;lt;/code&amp;gt;, i.e., a src-dst tuple—​decides on the prefix of the &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt;, i.e., the SubstreamId.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;substream_id: (CanisterId × CanisterId) → SubstreamId&lt;br /&gt;
&lt;br /&gt;
% Definition of substream_id for flat streams&lt;br /&gt;
substream_id((src, dst)) := ()&lt;br /&gt;
&lt;br /&gt;
% Definition of substream_id for per-destination canister substreams&lt;br /&gt;
substream_id((src, dst)) := dst&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Description of the actual state transition&#039;&#039;. The state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;post_process(S, subnet_assignment)&amp;lt;/code&amp;gt; is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Clear the output queues&lt;br /&gt;
  output_queues := clear(S.output_queues)&lt;br /&gt;
&lt;br /&gt;
  % Route the messages produced in the previous execution phase to the appropriate streams&lt;br /&gt;
  % taking into account ordering and capacity management constraints enforced by stream_index.&lt;br /&gt;
  streams.msgs  := {&lt;br /&gt;
    let msgs = S.streams.msgs&lt;br /&gt;
&lt;br /&gt;
    % Iterate over filtered messages preserving order of messages in queues.&lt;br /&gt;
    for each (q_index ↦ msg) ∈ filter(S.output_queues, subnet_assignment)&lt;br /&gt;
      msgs = push(msgs, { (concatenate(substream_id(prefix(q_index)), postfix(q_index)) ↦ msg) })&lt;br /&gt;
&lt;br /&gt;
    return msgs&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  % Push NON_EXISTENT_CANISTER replies to input queues of the respective canisters&lt;br /&gt;
  input_queues := push(S.input_queues,&lt;br /&gt;
                       non_existent_canister_replies(S.output_queues, subnet_assignment))&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ordering of Messages in the Stream &amp;amp; Fairness&#039;&#039;. As long as the invariant that the canister-to-canister ordering of messages is preserved when iterating over the filtered messages in the state transition described above, the implementation can take the freedom to apply alternative orderings.&lt;br /&gt;
&lt;br /&gt;
Also note that, while the state transition defined above empties the output queues completely, this is not crucial to the design and one could hold back messages as long as this does not violate the ordering requirement.&lt;br /&gt;
&lt;br /&gt;
== XNet Transfer ==&lt;br /&gt;
After calling &amp;lt;code&amp;gt;commit_and_certify&amp;lt;/code&amp;gt; at the end of a deterministic processing cycle, the state manager will take care of getting the committed state certified. Once certification is complete, the certified stream slices can be made available to block makers on other subnets. The &amp;lt;code&amp;gt;XNetTransfer&amp;lt;/code&amp;gt; subcomponent is responsible to enable this transfer. It consists of&lt;br /&gt;
&lt;br /&gt;
[[File:Xnet.png|thumb|XNet transfer component diagram]]&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; which is responsible for serving certified stream slices and making them available to &amp;lt;code&amp;gt;XNetPayloadBuilders&amp;lt;/code&amp;gt; on other subnetworks.&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;, which allows the block makers to obtain an &amp;lt;code&amp;gt;XNetPayload&amp;lt;/code&amp;gt; containing the currently available certified streams originating from other subnetworks. The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; obtains those streams by interacting with &amp;lt;code&amp;gt;XNetEndpoints&amp;lt;/code&amp;gt; exposed by other subnets. The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; also provides functionality for notaries to verify &amp;lt;code&amp;gt;XNetPayloads&amp;lt;/code&amp;gt; contained in block proposals.&lt;br /&gt;
&lt;br /&gt;
There are no specifications about the protocol run between the &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; to transfer the streams between two subnetworks. The only requirement is that certified streams made available by an &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; of an honest replica on some source subnetwork, they can be obtained by an &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; of an honest replica on the destination subnetwork and that the information regarding which endpoints to contact is available in the Registry.&lt;br /&gt;
&lt;br /&gt;
=== Properties and Functionality ===&lt;br /&gt;
Assume an XNet transfer component on a replica part of subnet &amp;lt;code&amp;gt;own_subnet&amp;lt;/code&amp;gt;. The interface behavior of the XNet transfer component will guarantee that for any payload payload produced via&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;get_xnet_payload(registry_version, reference_height, past_payloads, size_limit)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For any &amp;lt;code&amp;gt;(remote_subnet ↦ css) ∈ payload&amp;lt;/code&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;StateManager.decode_certified_stream(registry_version, own_subnet, remote_subnet, css)&amp;lt;/code&amp;gt; succeeds, i.e., returns a valid slice slice that is guaranteed to come from remote_subnet.&lt;br /&gt;
&lt;br /&gt;
* Furthermore, for each slice it will hold that a soon as the state corresponding to height &amp;lt;code&amp;gt;h = reference_height + |past_payloads|&amp;lt;/code&amp;gt; is available that &amp;lt;code&amp;gt;concatenate(remote_subnet, min(dom(slice.msgs.elements))) ∈ StateManager.get_state_at(h).expected_indexes&amp;lt;/code&amp;gt;. This means that the streams will start with the expected indexes stored in the previous state, i.e., they gap freely extend the previously seen streams.&lt;br /&gt;
&lt;br /&gt;
Payloads verified using &amp;lt;code&amp;gt;validate_xnet_payload&amp;lt;/code&amp;gt; are accepted if they adhere to those requirements, and are rejected otherwise.&lt;br /&gt;
&lt;br /&gt;
=== XNet Endpoint ===&lt;br /&gt;
The &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; serves the streams available on some subnet to other subnets. For an implementation this will typically mean that there is some client which will handle querying the API of the &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; on the remote subnet in question. The following abstraction is used to avoid explicitly talking about this client: Assume that there is a function &amp;lt;code&amp;gt;get : SubnetId → XNetEndpoint&amp;lt;/code&amp;gt; which will return an appropriate instance of &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; which can directly be queried using the API described below.&lt;br /&gt;
&lt;br /&gt;
[[File:Xnet-sequence.png|thumb|XNet transfer sequence diagram]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get_stream(subnet_id : SubnetId, begin : StreamIndex, msg_limit : ℕ, size_limit : ℕ) → CertifiedStreamSlice&amp;lt;/code&amp;gt;: Returns the requested certified stream slice in its transport format.&lt;br /&gt;
&lt;br /&gt;
It is required that an honest &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; pair is able to successfully obtain slices over this API.&lt;br /&gt;
&lt;br /&gt;
Looking at the bigger picture, the intuition for why this will yield a secure system is that in each round a new pair of block maker and endpoint will try to pull over a stream, which, in turn, means that eventually an honest pair will be able to obtain the stream and include it into a block.&lt;br /&gt;
&lt;br /&gt;
=== XNet Payload Builder ===&lt;br /&gt;
The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; builds and verifies payloads whenever requested to do so by the block maker. The rules for whether a payload is considered valid or not must be so that every notary is guaranteed to make the same decision on the same input and that a payload built by an honest payload builder will be accepted by honest validators. Essentially the rules resemble what is described in the section on properties and functionality. However, given that the execution may be behind one can not directly look up the expected indexes in the appropriate state but need to compute it based on the referenced state and the payloads since then. Below, a figure is provided to illustrate the high-level functionality: generally speaking blocks are considered valid if they adhere to the rules described in the figure and are considered invalid otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Payload-building.png|thumb|Rules for payload building]]&lt;br /&gt;
&lt;br /&gt;
This section formally defines the operation of the component. The following helper functions are first defined. Assume that &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; has an associated field &amp;lt;code&amp;gt;own_subnet&amp;lt;/code&amp;gt; which is passed whenever constructing an &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;new : SubnetId → Self&lt;br /&gt;
new(own_subnet) :=&lt;br /&gt;
  XNetPayloadBuilder {&lt;br /&gt;
      with&lt;br /&gt;
         └─ own_subnet := own_subnet&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The API defines the past_payloads as a vector where the past payloads are ordered with respect to the corresponding height in the chain. While this ordering allows for a more efficient implementation of the functions below it does not matter on a conceptual level. Hence resort to looking at it as a set for the sake of simplicity.&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;slice_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, solely based on a set of Slices.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Take the maximum index for each individual (sub-)stream in the given set of slices and add&lt;br /&gt;
% 1 to obtain the next indexes one would expect when solely looking at the past payloads but&lt;br /&gt;
% ignoring the state.&lt;br /&gt;
slice_indexes : (SubnetId ↦ StreamSlice) → Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
slice_indexes(slices) := { i + 1 | i ∈ max(dom(slices.msgs.elements)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;state_and_payload_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, taking into account both the expected indices in the given replicated state and the more recent messages in the given slices from the past payloads.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Take the expected indexes from the state, remove whatever index appears in the given&lt;br /&gt;
% slices and add the expected indexes according to the streams in the slices.&lt;br /&gt;
%&lt;br /&gt;
% FAIL IF: ∃ i, j ∈ state_and_payload_indexes(state, slices) :&lt;br /&gt;
%              prefix(i) = prefix(j) ∧ postfix(i) ≠ postfix(j)&lt;br /&gt;
%&lt;br /&gt;
state_and_payload_indexes : ReplicatedState ×&lt;br /&gt;
                            (SubnetId ↦ StreamSlice) →&lt;br /&gt;
                            Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
state_and_payload_indexes(state, slices) := state.expected_xnet_indices&lt;br /&gt;
                                            \ dom(slices.msgs.elements)&lt;br /&gt;
                                            ∪ slice_indexes(slices)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;expected_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, taking into account both the expected indices in the given replicated state and the more recent messages in the given past payloads.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Decode the slices in the given payload and compute the expected indexes using the&lt;br /&gt;
% expected_indexes function above&lt;br /&gt;
expected_indexes : SubnetId ×&lt;br /&gt;
                   ReplicatedState ×&lt;br /&gt;
                   (SubnetId ↦ StreamSlice) →&lt;br /&gt;
                   Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
expected_indexes(own_subnet, state, slices) :=&lt;br /&gt;
    state_and_payload_indexes(&lt;br /&gt;
        state,&lt;br /&gt;
        { (src ↦ slice) | payload ∈ slices ∧&lt;br /&gt;
                          (src ↦ cert_slice) ∈ payload ∧&lt;br /&gt;
                          slice = StateManager.decode_valid_certified_stream(own_subnet,&lt;br /&gt;
                                                                             cert_slice)&lt;br /&gt;
        }&lt;br /&gt;
    )&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Creation of XNet Payloads ====&lt;br /&gt;
Based on the functions above, it is possible to define the function &amp;lt;code&amp;gt;get_xnet_payload : Height × Height × Set&amp;lt;XNetPayload&amp;gt; → XNetPayload&amp;lt;/code&amp;gt;. Note that the gap-freeness of streams is an invariant of the datatype, which is why the rule for gap-freeness is not explicitly included here.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Build an xnet payload containing the currently available streams. The begin is either given&lt;br /&gt;
% by the expected index, and, if there is no expected index for a given prefix, the index&lt;br /&gt;
% ONE is expected.&lt;br /&gt;
%&lt;br /&gt;
% ENSURES: size_of(get_xnet_payload(self, ·, ·, ·, size_limit)) ≤ size_limit ∧&lt;br /&gt;
%          each payload output by get_xnet_payload will be accepted by validate_xnet_payload&lt;br /&gt;
%&lt;br /&gt;
get_xnet_payload : Self × RegistryVersion × Height × Vec&amp;lt;XNetPayload&amp;gt; × ℕ → XNetPayload&lt;br /&gt;
get_xnet_payload(self, registry_version, reference_height, past_payloads, size_limit) :=&lt;br /&gt;
    { (remote_subnet ↦ slice) |&lt;br /&gt;
            S = StateManager.get_state_at(reference_height)&lt;br /&gt;
          ∧ subnets = Registry::get_registry_at(registry_version).subnets \ { self.own_subnet }&lt;br /&gt;
          ∧ (remote_subnet, begin_index) ∈&lt;br /&gt;
                  expected_indexes(self.own_subnet, S, past_payloads)&lt;br /&gt;
                ∪ { (subnet_id, StreamIndex::ONE) |&lt;br /&gt;
                        subnet_id ∈ subnets&lt;br /&gt;
                                    \ { s | (s, ·) ∈ expected_indexes(self.own_subnet,&lt;br /&gt;
                                                                      S,&lt;br /&gt;
                                                                      past_payloads)&lt;br /&gt;
                                      }&lt;br /&gt;
                  }&lt;br /&gt;
            % msg_limit and size limit need to be set by the implementation as appropriate&lt;br /&gt;
            % to satisfy the post condition&lt;br /&gt;
          ∧ slice = XNetEndpoint::get(subnet).get_stream(remote_subnet, begin_index, ·, ·)&lt;br /&gt;
          ∧ ERR ≠ StateManager.decode_certified_stream(registry_version,&lt;br /&gt;
                                                       self.own_subnet,&lt;br /&gt;
                                                       remote_subnet,&lt;br /&gt;
                                                       slice)&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Validation of XNet Payloads ====&lt;br /&gt;
Validation of XNetPayloads works analogously to the creation. The function &amp;lt;code&amp;gt;validate_xnet_payload&amp;lt;/code&amp;gt; is defined as follows, where it is assumed that it evaluates to false in case an error occurs. Again, note that the gap-freeness of streams is an invariant of the datatype, which is why the rule for gap-freeness is not explicitly included here.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Check whether a given xnet payload was built according to the rules given above.&lt;br /&gt;
%&lt;br /&gt;
% FAIL IF: size_of(payload) &amp;gt; size_limit&lt;br /&gt;
%&lt;br /&gt;
validate_xnet_payload : Self × RegistryVersion × Height × Vec&amp;lt;XNetPayload&amp;gt; × XNetPayload × ℕ → Bool&lt;br /&gt;
validate_xnet_payload(self, registry_version, reference_height, past_payloads, payload, size_limit) :=&lt;br /&gt;
    S = StateManager.get_state_at(reference_height) ∧&lt;br /&gt;
    ∀ (remote_subnet ↦ css) ∈ payload :&lt;br /&gt;
    {&lt;br /&gt;
      slice = StateManager.decode_certified_stream(registry_version,&lt;br /&gt;
                                                   self.own_subnet,&lt;br /&gt;
                                                   remote_subnet,&lt;br /&gt;
                                                   css) ∧&lt;br /&gt;
      ∀ index ∈ min(dom(slice.msgs.elements)) :&lt;br /&gt;
      {&lt;br /&gt;
        (remote_subnet, index) ∈ expected_indexes(S, past_payloads) ∨&lt;br /&gt;
        index = (remote_subnet, StreamIndex::ONE)&lt;br /&gt;
      }&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Maturity&amp;diff=8454</id>
		<title>Maturity</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Maturity&amp;diff=8454"/>
		<updated>2025-07-01T13:18:00Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084120668692-Neurons#01JJ7BJX36NH538SCDQFHSJSVD}}&lt;br /&gt;
&lt;br /&gt;
Maturity represents the voting rewards accumulated in a neuron. Each day the network rewards participants by allocating to every voting neuron a portion of the total reward, based both on its voting power at the time proposals were made, and the number of proposals it voted on.&lt;br /&gt;
&lt;br /&gt;
Please note that different tax authorities may take different views on the taxation status of the voting rewards. Neuron owners who receive voting rewards and convert them to ICP should consult appropriate professionals.&lt;br /&gt;
&lt;br /&gt;
For those who wish to compound the voting power in their neuron, the most natural activity is to &amp;quot;stake maturity&amp;quot; on a regular basis. If you wish to liquidate rewards you earn from the neuron and convert them to ICP, you can &amp;quot;spawn&amp;quot; maturity into a reward neuron.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Main_Page&amp;diff=8453</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Main_Page&amp;diff=8453"/>
		<updated>2025-07-01T13:10:03Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;templatestyles src=&amp;quot;Template:Main_page/styles.css&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Introduction to Internet Computer Protocol (ICP) Blockchain==&lt;br /&gt;
&amp;lt;!-- [[File:IC_logo_vertical_white.png| frame | 320px|ICP Logo|alt=|border|right]] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[Introduction_to_ICP | Internet Computer]] is a general-purpose blockchain that hosts canister smart contracts. It is designed to provide a World Computer that can replace traditional IT and host a new generation of Web 3.0 services and applications that run solely from the blockchain, without the need for traditional IT. It can also play the role of Web 3.0 orchestrator, by interacting with other blockchains.&lt;br /&gt;
&lt;br /&gt;
It has a completely unique design that reflects a ground-up rethink of blockchain architecture and the application of modern cryptography, [https://web.archive.org/web/20150914013643/http://dfinity.io/ which can be traced back to 2015]. It was built by the largest [https://dfinity.org/team ongoing R&amp;amp;D effort in crypto], which has employed many notable cryptographers, computer science researchers and engineers. The blockchain underwent genesis in May 2021 and became part of the public internet. &lt;br /&gt;
&lt;br /&gt;
See more at [[Introduction to ICP]].&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Main Sections ==&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Row #1 --&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;audiences&amp;quot; class=&amp;quot;mainpage_row&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
               &amp;lt;!-- Item #1 --&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;mainpage_box overview&amp;quot; id=&amp;quot;overview&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;h3&amp;gt;&lt;br /&gt;
                    &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon edit-ltr.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                    &amp;lt;span&amp;gt;&#039;&#039;&#039;Overview&#039;&#039;&#039;: ICP Blockchain and ICP Ecosystem&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;/h3&amp;gt;&lt;br /&gt;
                &amp;lt;div id=&amp;quot;mainpage-users&amp;quot; title=&amp;quot;Users&amp;quot; class=&amp;quot;items&amp;quot;&amp;gt;&lt;br /&gt;
* [[Introduction to ICP]] blockchain&lt;br /&gt;
* [[Popular Explainers of ICP |Popular explainers of ICP]] blockchain&lt;br /&gt;
* [https://internetcomputer.org internetcomputer.org website]&lt;br /&gt;
* [https://dashboard.internetcomputer.org ICP Network Dashboard]&lt;br /&gt;
* [[Web3: The bull case for the Internet Computer]]&lt;br /&gt;
* [[ICP Ecosystem Stats |ICP ecosystem stats]]&lt;br /&gt;
* [[ICP Community |ICP community]]&lt;br /&gt;
* [[ICP Tokenomics |ICP tokenomics]]&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
                &lt;br /&gt;
        &amp;lt;!-- Item #2 --&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;mainpage_box users&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;h3 class=&amp;quot;mainpage_box_header_users&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon edit-ltr.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                &amp;lt;span&amp;gt;&#039;&#039;&#039;For Users&#039;&#039;&#039;: Getting Started with ICP&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/h3&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;mainpage-users&amp;quot; title=&amp;quot;Users&amp;quot; class=&amp;quot;items&amp;quot;&amp;gt;&lt;br /&gt;
* Aquire an [[Internet Identity]] (not necessary, but highly recommended)&lt;br /&gt;
* [[Tutorials for acquiring, managing, and staking ICP |Managing and staking ICP tokens]]&lt;br /&gt;
* [https://internetcomputer.org/ecosystem/ Examples of ICP smart contracts and dapps]&lt;br /&gt;
* [https://support.dfinity.org/ DFINITY support center]&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;!-- Item #3 --&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;mainpage_box developers&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;h3&amp;gt;&lt;br /&gt;
                &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon chem.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                &amp;lt;span&amp;gt;&#039;&#039;&#039;For Developers&#039;&#039;&#039;: Building ICP Smart Contracts&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/h3&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;mainpage-devs&amp;quot; title=&amp;quot;Developers&amp;quot; class=&amp;quot;items&amp;quot;&amp;gt;&lt;br /&gt;
* [https://internetcomputer.org/docs/current/home Developer Documentation]&lt;br /&gt;
* [https://forum.dfinity.org/t/announcing-technical-working-groups/11781 Technical working groups]&lt;br /&gt;
* Launching an [[Service Nervous System (SNS) |SNS]] DAO&lt;br /&gt;
* Smart contracts with [[Bitcoin integration]]&lt;br /&gt;
* [[The Internet Computer for Ethereum Developers |ICP for Ethereum developers]]&lt;br /&gt;
* [https://forum.dfinity.org/ Developer forum] for ICP developers.&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Row #2 --&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;misc-news&amp;quot; class=&amp;quot;mainpage_row nodes&amp;quot;&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
        &amp;lt;div class=&amp;quot;mainpage_box&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;h3&amp;gt;&lt;br /&gt;
                &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon ongoingConversation-rtl.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                &amp;lt;span&amp;gt;&#039;&#039;&#039;For Node Providers&#039;&#039;&#039;: Joining ICP Network&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/h3&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;mainpage-help-contribute&amp;quot; title=&amp;quot;Support and Contributing&amp;quot; class=&amp;quot;items&amp;quot;&amp;gt;&lt;br /&gt;
*[[Node Provider Documentation]]&lt;br /&gt;
*[[Node Provider Roadmap]]&lt;br /&gt;
*[[Node Provider Troubleshooting]]&lt;br /&gt;
* Status of the network on [https://dashboard.internetcomputer.org ICP Dashboard]&lt;br /&gt;
* [[Node Provider Matrix channel|IC Node Provider Matrix channel]]&lt;br /&gt;
* ICP is a [[Sovereign Network]] using [[Deterministic Decentralization]] with [[Proof of Useful Work]] consensus&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;div class=&amp;quot;mainpage_box community&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;h3&amp;gt;&lt;br /&gt;
                &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon ongoingConversation-rtl.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                &amp;lt;span&amp;gt;&#039;&#039;&#039;For ICP Community&#039;&#039;&#039;: Participating in ICP&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/h3&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;mainpage-help-contribute&amp;quot; title=&amp;quot;Support and Contributing&amp;quot; class=&amp;quot; items&amp;quot;&amp;gt;&lt;br /&gt;
* [[Governance of the Internet Computer |ICP governance]]&lt;br /&gt;
* [[Contributing to the wiki]]&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;div class=&amp;quot;mainpage_box researchers&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;h3&amp;gt;&lt;br /&gt;
                &amp;lt;!-- &amp;lt;span class=&amp;quot;header_icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;[[File:OOjs UI icon ongoingConversation-rtl.svg|20px|middle|link=]]&amp;lt;/span&amp;gt; --&amp;gt;&lt;br /&gt;
                &amp;lt;span&amp;gt;&#039;&#039;&#039;For ICP Researchers&#039;&#039;&#039;: Deep Dive into ICP&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/h3&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;mainpage-researchers&amp;quot; title=&amp;quot;Deep Dive into ICP&amp;quot; class=&amp;quot; items&amp;quot;&amp;gt;&lt;br /&gt;
* [https://eprint.iacr.org/2022/087 &amp;quot;Internet Computer for Geeks&amp;quot; white paper]&lt;br /&gt;
* [[IC architecture overview]]&lt;br /&gt;
* [https://www.reddit.com/r/dfinity/comments/ozboyi/megathread_technical_amas/ Technical AMAs on Reddit by different IC and DFINITY teams]&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #ffd700; padding: 10px; margin-bottom: 20px;&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;strong&amp;gt;Want to contribute to the IC Wiki? See [[Contributing_to_the_wiki |here]] &amp;lt;/strong&amp;gt; &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Decentralization_in_ICP:_Protocol_Governance&amp;diff=8452</id>
		<title>Decentralization in ICP: Protocol Governance</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Decentralization_in_ICP:_Protocol_Governance&amp;diff=8452"/>
		<updated>2025-06-30T22:02:06Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/33692645961236-Overview}}&lt;br /&gt;
&lt;br /&gt;
==Summary==&lt;br /&gt;
&lt;br /&gt;
As a blockchain protocol, decentralization is very important to the design and implementation of ICP. This article is one of a subset explaining the design intent and the current state of the world when it comes to ICP decentralization. Its main focus is analyzing &#039;&#039;&#039;protocol governance&#039;&#039;&#039;. To see the whole picture, it is recommended to see the following articles:&lt;br /&gt;
&lt;br /&gt;
* [[Decentralization in ICP]]&lt;br /&gt;
* [[Decentralization in ICP: Critical Dapps on the IC]]&lt;br /&gt;
* [[Decentralization in ICP: Infrastructure Governance]]&lt;br /&gt;
&lt;br /&gt;
==Background ==&lt;br /&gt;
&lt;br /&gt;
The [[Network Nervous System]] (NNS) is an open algorithmic governance system that oversees the ICP network and the token economics. This governance system, the NNS, is controlled by a DAO of users all voting. The example below illustrates what this means in practice.&lt;br /&gt;
&lt;br /&gt;
==Design Intent and how users join the NNS DAO ==&lt;br /&gt;
&lt;br /&gt;
The NNS is designed to hold the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Anyone can participate in the NNS DAO&#039;&#039;&#039; by staking ICP into neurons and voting in proposals. Each neuron has a voting power corresponding to the amount of ICP staked, how long it is staked for and how long the neuron has existed.&lt;br /&gt;
* NNS DAO controls everything in the network including software and hardware changes.&lt;br /&gt;
* NNS allows liquid democracy so stakers can have their neurons follow the votes of other neurons.&lt;br /&gt;
* Create a structured way for the network to quickly update itself (in comparison to other blockchains where upgrades can take a lot of time and manual effort).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Example: Upgrading the network’s code ==&lt;br /&gt;
&lt;br /&gt;
ICP is a network of nodes running “replica code” that is identical for each node. At the time of this writing, they were all running replica code version [https://dashboard.internetcomputer.org/proposal/107483 935b417d]. As usual, this [https://dashboard.internetcomputer.org/release/935b417d6f5dd2befa7f9ad7bfc975df32f8c641 particular replica version] has a lot of bug fixes, features, and optimizations. But more importantly, this code was accepted as the new version after a few steps:&lt;br /&gt;
&lt;br /&gt;
1. Developers code up a new replica version&lt;br /&gt;
&lt;br /&gt;
2. Developers submit the new replica version as a [https://dashboard.internetcomputer.org/proposal/107483 proposal to the NNS DAO]&lt;br /&gt;
&lt;br /&gt;
3. NNS DAO votes on the proposal&lt;br /&gt;
&lt;br /&gt;
4. If NNS DAO passes the proposal, the replica code is “blessed” (read: approved) and subsequent proposals update each of the subnets.&lt;br /&gt;
&lt;br /&gt;
The NNS is the system (or “steering wheel” for the network) which is controlled by the DAO, so in the case of the Internet ComputerProtocol governance, what matters most is to evaluate decentralization of the NNS and DAO.&lt;br /&gt;
&lt;br /&gt;
[[File:Nns proposal example.png |800px ]]&lt;br /&gt;
&lt;br /&gt;
==Current State of Decentralization ICP ==&lt;br /&gt;
&lt;br /&gt;
To see the latest measures of NNS decentralization, see: https://medium.com/@dfinity/nns-and-decentralization-5f4963e83df7&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Decentralization in ICP]]&lt;br /&gt;
* [[Decentralization in ICP: Infrastructure Governance]]&lt;br /&gt;
* [[Decentralization in ICP: Critical Dapps on the IC]]&lt;br /&gt;
* [[Weighted average of logs of NCs in Protocol]]&lt;br /&gt;
* [[Weighted average of logs of NCs in infrastructure]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=New_Subnet_Creation&amp;diff=8451</id>
		<title>New Subnet Creation</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=New_Subnet_Creation&amp;diff=8451"/>
		<updated>2025-06-30T22:01:40Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34209955782420-Subnet-Creation}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ever wondered about the meaning behind DFINITY? It’s Decentralized + Infinity. It’s named that way because the Internet Computer is designed to scale infinitely. It means that the Internet Computer can host an unlimited number of canisters (smart contracts), store an unlimited amount of memory, process an unlimited amount of transactions per second. In simple words, Internet Computer is designed to host even large scale social media platforms in a fully decentralized way.&lt;br /&gt;
&lt;br /&gt;
There are two types of widely-used approaches to improve scalability. (1) Vertical Scaling, and (2) Horizontal Scaling. Vertical scaling means adding more CPU, RAM and disk to a single computer. Horizontal scaling means adding more computers to scale. There is a limit to vertical scaling. But with horizontal scaling, one can achieve unlimited scalability. Internet Computer is one of the first blockchains to successfully use horizontal scaling.&lt;br /&gt;
&lt;br /&gt;
The nodes in the Internet Computer are divided into subnets, each containing a few dozen nodes. The set of nodes in a subnet together maintain one blockchain. Each subnet can host a few thousand canisters and process messages received by those canisters. Each subnet has a limited capacity in terms of the number of canisters (a few thousand), amount of storage (a few TB), and bandwidth (a few hundred transactions per second). But as more subnets are added to the Internet Computer, its overall capacity increases proportionately. There is no limit on the number of subnets that can be added, resulting in unlimited scalability.&lt;br /&gt;
&lt;br /&gt;
There are two things needed to create a new subnet. &lt;br /&gt;
* Add/Register new nodes. &lt;br /&gt;
* Create a new subnet with the registered nodes that were not yet assigned to any subnet. &lt;br /&gt;
&lt;br /&gt;
== Adding/Registering New Nodes ==&lt;br /&gt;
This sections describes a series of steps that need to be followed to add a new node to the Internet Computer. &lt;br /&gt;
* Node provider purchases a NitroKey (a Hardware Security Module), generates a public-key/secret-key pair, and submits an NNS proposal to add his public key to the NNS registry. The community votes on the proposal. If the majority accept the proposal, then the node provider&#039;s credentials are added to the NNS registry. From now on, the NNS canisters trust the messages signed by the node provider&#039;s secret key. The entire process is specified in the [https://wiki.internetcomputer.org/wiki/Node_Provider_Onboarding node provider onboarding article].&lt;br /&gt;
* Node provider purchases node hardware with the recommended specifications and places it in a data center rack that meets the recommended specifications. &lt;br /&gt;
* The node doesn&#039;t yet have any operating system. The node provider needs to install the IC-OS operating system on the node. The detailed procedure can be found in the IC-OS installation runbook articles ([https://wiki.internetcomputer.org/wiki/IC_OS_Installation_Runbook_-_Supermicro Installation for SuperMicro], [https://wiki.internetcomputer.org/wiki/IC_OS_Installation_Runbook_-_Dell_Poweredge Installation for Dell Poweredge]).&lt;br /&gt;
* The node provider inserts the NitroKey usb stick into the node machine. The NitroKey contains the secret key of corresponding to the node provider&#039;s registered public key. &lt;br /&gt;
* The node provider then switches on the node to boot the IC-OS operation system, which starts a few processes including orchestrator, crypto and http adapter processes. &lt;br /&gt;
* The crypto process finds that it never generated any cryptographic key material before. The crypto process then generates new cryptographic keys. This includes node signing key, NIDKG key, ECDSA key, TLS key, etc. &lt;br /&gt;
* The cryptographic key material need to be registered with the NNS registry. For this, the crypto process sends the keys to the orchestrator, which then crafts a message containing the key material, signs the message with the node provider&#039;s signing key present in the NitroKey, and sends the message to the NNS registry canister. &lt;br /&gt;
* The NNS registry canister creates a record for the new node and stores its cryptographic key material. &lt;br /&gt;
* The node is now registered in the Internet Computer, but not yet assigned to any subnet.&lt;br /&gt;
&lt;br /&gt;
== Creating a New Subnet == &lt;br /&gt;
This section describes the process of creating a new subnet. To create a new subnet, one just needs to submit an NNS proposal. The proposal specifies a type (create subnet) and a payload ([[#Payload for &#039;Create_Subnet&#039; Proposal]]). A few sample proposals to create a new subnet can be found in the dashboard ([https://dashboard.internetcomputer.org/proposal/57048 Proposal 57048], [https://dashboard.internetcomputer.org/proposal/49018 Proposal 49018], [https://dashboard.internetcomputer.org/proposal/55730 Proposal 55730]). Anyone who staked their ICP can vote on the proposal within a deadline. After the deadline, if the majority of the voters accept the proposal, then the subnet is created as described below. &lt;br /&gt;
&lt;br /&gt;
The NNS has a canister called &amp;quot;registry&amp;quot;, which stores the configuration of the Internet Computer including the configuration of each node and subnet. When the &#039;Create subnet&#039; proposal is accepted, it automatically calls a method of the NNS Registry with input the payload included in the NNS proposal. The registry canister then creates a new subnet configuration based on the information in the payload, and stores the subnet record. &lt;br /&gt;
&lt;br /&gt;
Each node in the Internet Computer maintains a local copy of the NNS registry. Each node runs a &amp;quot;registry replicator&amp;quot; process ([https://github.com/dfinity/ic/tree/master/rs/orchestrator/registry_replicator github]) which is a part of the orchestrator and is responsible for regularly syncing NNS registry and maintaining the local registry copy. Once every few seconds (can be configured by setting &amp;lt;code&amp;gt;poll_delay_duration_ms&amp;lt;/code&amp;gt; variable, which has a default value of 5 seconds), the registry replicator queries the NNS registry for the changes that happened after the recent sync, and applies those changes to the local registry copy. The local registry is stored on the disk and any process running on the node can read the contents of the local registry. &lt;br /&gt;
&lt;br /&gt;
The orchestrator monitors the local registry to see what subnet the node has been assigned to. If the unassigned node has now been assigned to a new subnet according to the registry, the orchestrator first downloads the replica software using the url in the subnet&#039;s registry configuration. The orchestrator now installs the replica software ([[#Installing_the_Replica]]) and restarts the node.&lt;br /&gt;
&lt;br /&gt;
== Payload for &#039;Create Subnet&#039; Proposal == &lt;br /&gt;
The payload for the &#039;Create Subnet&#039; NNS proposal contains the list of parameters to be used by the new subnet. Some of the fields in the payload are as follows. The structure of payloads for every type of NNS proposal can be found on [https://github.com/dfinity/ic/blob/master/rs/registry/canister/canister/registry.did github]. &lt;br /&gt;
* subnet_type - The type of the subnet to be created. Subnets of different type might exhibit different behavior, e.g. being more restrictive in what operations are allowed or privileged compared to other subnet types. There are a few types of subnets. &lt;br /&gt;
** Application subnet - A normal subnet where no restrictions are applied.&lt;br /&gt;
** System subnet - A more privileged subnet where certain restrictions are applied, like not charging for cycles or restricting who can create and install canisters on it.&lt;br /&gt;
** Verified application subnet - A subnet type that is like application subnets but can have some additional features.&lt;br /&gt;
* node_ids - List of node ids of unassigned nodes to be included in the subnet. &lt;br /&gt;
* replica_version_id - The version id of the replica software to be installed in the nodes of the subnet. &lt;br /&gt;
** A replica image has to be first uploaded to a publicly accessible server. &lt;br /&gt;
** Then one needs to create an NNS proposal of type &amp;quot;Elect new binary replica revision&amp;quot; and specify the replica image url and version id in the payload. A sample proposal can be found in the dashboard ([https://dashboard.internetcomputer.org/proposal/92338 proposal 92338]). &lt;br /&gt;
** When the proposal is accepted by the majority of voters, the replica version is stored in the NNS registry. &lt;br /&gt;
** This replica version id can now be specified in any other NNS proposals including &amp;quot;create subnet&amp;quot;. &lt;br /&gt;
* Parameters for the P2P layer - &lt;br /&gt;
**gossip_max_chunk_size - The maximum chunk size supported on this subnet. &lt;br /&gt;
**gossip_retransmission_request_ms - Period for sending retransmission request.&lt;br /&gt;
**gossip_receive_check_cache_size - History size for receive check.&lt;br /&gt;
**gossip_registry_poll_period_ms - Period for polling the registry for updates.&lt;br /&gt;
**gossip_max_duplicity - Max duplicate requests in underutilized networks.&lt;br /&gt;
**gossip_max_chunk_wait_ms - Timeout for an outstanding request.&lt;br /&gt;
**gossip_pfn_evaluation_period_ms - Period for re evaluating the priority function.&lt;br /&gt;
**gossip_max_artifact_streams_per_peer - The maximum number of outstanding request per peer MIN/DEFAULT/MAX.&lt;br /&gt;
**advert_best_effort_percentage - &lt;br /&gt;
* Parameters for the Consensus layer &lt;br /&gt;
** max_block_payload_size - The maximum combined size of the ingress and xnet messages that fit into a block.&lt;br /&gt;
** max_ingress_bytes_per_message - The maximum amount of bytes per message. This is a hard cap, which means ingress messages greater than the limit will be dropped.&lt;br /&gt;
** max_ingress_messages_per_block - The maximum number of ingress messages allowed per block.&lt;br /&gt;
** ingress_bytes_per_block_soft_cap&lt;br /&gt;
** initial_notary_delay_millis - Initial delay for notary (in milliseconds), to give time to rank-0 block propagation.&lt;br /&gt;
** unit_delay_millis - Unit delay for blockmaker (in milliseconds).&lt;br /&gt;
* Parameters for the execution layer &lt;br /&gt;
** max_instructions_per_message - The maximum number of instructions a message can execute.&lt;br /&gt;
** max_instructions_per_round - The maximum number of instructions a round can execute.&lt;br /&gt;
** max_instructions_per_install_code - The maximum number of instructions an &amp;quot;install_code&amp;quot; message can execute.&lt;br /&gt;
** max_number_of_canisters - The maximum number of canisters that may be present on the subnet at any given time. A value of 0 is equivalent to setting no limit. This also provides an easy way to maintain compatibility of different versions of replica and registry.&lt;br /&gt;
* Parameters related to cryptographic keys &lt;br /&gt;
** dkg_dealings_per_block&lt;br /&gt;
** ecdsa_config - This field is optional. It specifies the configuration settings to be used for ECDSA signature scheme. &lt;br /&gt;
** dkg_interval_length - This is the number of rounds in an epoch. At the end of each epoch, the nodes run a distributed key generation protocol to reshare their secret key shares. &lt;br /&gt;
* SSH Access to Subnet&lt;br /&gt;
** ssh_readonly_access - The list of public keys whose owners have &amp;quot;readonly&amp;quot; SSH access to all replicas on this subnet, in case it is necessary to perform subnet recovery.&lt;br /&gt;
** ssh_backup_access - The list of public keys whose owners have &amp;quot;backup&amp;quot; SSH access to nodes on the NNS subnet to make sure the NNS can be backed up.&lt;br /&gt;
* Subnet Features - The list of feature flags to be used for the subnet. This indicates the features that are to be enabled/disabled in the subnet. This includes the following features.&lt;br /&gt;
** Canister sandboxing - This feature flag controls whether canister execution happens in sandboxed process or not. It is disabled by default.&lt;br /&gt;
** Http requests - This feature flag controls whether canisters of this subnet are capable of performing http(s) requests to the web2.&lt;br /&gt;
** Bitcoin testnet feature - Whether or not the subnet is capable of serving requests to the bitcoin testnet canister.&lt;br /&gt;
** Bitcoin - Controls whether the bitcoin feature is enabled and which bitcoin network is supported.&lt;br /&gt;
* is_halted - If &amp;quot;true&amp;quot;, the subnet will be halted: it will no longer create or execute blocks.&lt;br /&gt;
* start_as_nns - If set to yes, the subnet starts as a (new) NNS.&lt;br /&gt;
* subnet_id_override - This field is optional. If a principal id is specified, then that principal id will be used for the new subnet.&lt;br /&gt;
&lt;br /&gt;
== Executing the &#039;Create Subnet&#039; Proposal ==&lt;br /&gt;
When the &#039;Create Subnet&#039; NNS proposal is voted and accepted by the community, the proposal is executed automatically. To execute the proposal, a method in the registry canister is called ([https://github.com/dfinity/ic/blob/master/rs/registry/canister/src/mutations/do_create_subnet.rs github]), which mutates the registry to add configuration information of the new subnet. The registry is a versioned key-value storage. Each mutation to the registry is stored as a new version. &lt;br /&gt;
&lt;br /&gt;
The registry canister performs the following steps. &lt;br /&gt;
* Run the [[Distributed Key Generation]] protocol. &lt;br /&gt;
** The first step is to generate the cryptographic information required for the new subnet to work properly. After every round of the Internet Computer protocol, the nodes of the subnet agree upon and sign their latest [https://wiki.internetcomputer.org/wiki/Replicated_state_structure replicated state]. For this, the subnet utilizes a threshold BLS signature scheme. In a nutshell, each node in the subnet holds a &amp;quot;share&amp;quot; of the subnet&#039;s signing key (none of the nodes know the complete subnet&#039;s signing key). After every round, each of the nodes individually sign their replicated state using their signing key &amp;quot;share&amp;quot;. If at least a &amp;quot;threshold&amp;quot; number of nodes agree upon the same replicated state, their signature &amp;quot;shares&amp;quot; can be combined to obtain the signature of the replicated state using the subnet&#039;s signing key. A subnet also utilizes threshold BLS signature scheme for many other purposes including the generation of random beacon in the consensus layer and generation of random tape in the execution layer. &lt;br /&gt;
** In order to generate the above signing key share for each node in the new subnet, the nodes in the NNS engage in a distributed key generation (DKG) protocol. At the end of the protocol, all the nodes in the NNS agree on a few &amp;quot;dealings&amp;quot; for each node in the new subnet. The dealings of a node can be combined to obtain the signing key share of the node. The dealings for each node are encrypted with the encryption key registered by the node. &lt;br /&gt;
* Create a genesis block and [[Catch-Up Package]]&lt;br /&gt;
** The registry canister creates a genesis block. This is the first block in the blockchain. Structurally, this is a [[Summary Block]] containing the DKG dealings computed above. &lt;br /&gt;
** The registry canister then generates a Catch-Up Package which contains the above genesis block along with other information required for the subnet to start the consensus protocol. &lt;br /&gt;
* Create a Subnet Record&lt;br /&gt;
** Each subnet has a subnet record storing all its configuration information. The subnet record of the new subnet contains all the information present in the payload of the &#039;Create Subnet&#039; proposal. &lt;br /&gt;
* Perform the following 5 mutations to the registry. The registry is a versioned key-value storage. &lt;br /&gt;
** Append to subnet list. &lt;br /&gt;
*** For the key &amp;lt;code&amp;gt;subnet_list&amp;lt;/code&amp;gt;, the registry stores the list of all subnets. Append the new subnet to this list. &lt;br /&gt;
** Store subnet record. &lt;br /&gt;
*** Add a key-value pair with key = &amp;lt;code&amp;gt;subnet_record_{subnet_id}&amp;lt;/code&amp;gt; and value = newly created subnet record, where {subnet_id} is the subnet id of the newly created subnet. &lt;br /&gt;
** Store catch-up package. &lt;br /&gt;
*** Add a key-value pair with key = &amp;lt;code&amp;gt;catch_up_package_contents_{subnet_id}&amp;lt;/code&amp;gt; and value = newly created catch-up package. &lt;br /&gt;
** Store subnet threshold signing key. &lt;br /&gt;
*** Add a key-value pair with key = &amp;lt;code&amp;gt;crypto_threshold_signing_public_key_{subnet_id}&amp;lt;/code&amp;gt; and value = threshold BLS signing key generated above.&lt;br /&gt;
** Routing table mutation.&lt;br /&gt;
*** Each subnet has a range of canister ids that are utilized for canisters in that subnet. The range of canister ids for each subnet is called the routing table. The routing table helps us route canister traffic to the appropriate subnet. When a new subnet is created, the next available set of &amp;lt;code&amp;gt;CANISTER_IDS_PER_SUBNET&amp;lt;/code&amp;gt; (currently set to 2^20) canister ids is assigned as the range for the subnet. This information is stored in the key &amp;lt;code&amp;gt;routing_table&amp;lt;/code&amp;gt; of the registry.&lt;br /&gt;
&lt;br /&gt;
== Installing the Replica ==&lt;br /&gt;
The orchestrator uses a [https://en.wikipedia.org/wiki/Blue-green_deployment blue/green deployment] to start the replica software, which works as follows. The disk is divided into 3 partitions -- 2 partitions for the replica process and 1 partition for the data. If a node is not assigned to any subnet, both the replica partitions are empty. If the node is actively participating in a subnet, one of the replica partitions is used to run the replica process and the other replica partition is empty. To install the new replica software, &lt;br /&gt;
* The orchestrator loads the replica image into an empty replica partition. &lt;br /&gt;
* The orchestrator then modifies the boot loader settings to use the newly loaded replica partition. &lt;br /&gt;
* The orchestrator restarts the node. &lt;br /&gt;
* When the node boots up again, the newly loaded replica partition is used as per the boot loader settings.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Boundary_Nodes&amp;diff=8450</id>
		<title>Boundary Nodes</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Boundary_Nodes&amp;diff=8450"/>
		<updated>2025-06-30T22:01:10Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34212818609684-ICP-Edge-Infrastructure#h_01JJSTH3K32T43FGFWBMP84FVC}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_P2P_(peer_to_peer)_layer&amp;diff=8449</id>
		<title>IC P2P (peer to peer) layer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_P2P_(peer_to_peer)_layer&amp;diff=8449"/>
		<updated>2025-06-30T22:00:47Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34207428453140-Peer-to-peer}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_consensus_layer&amp;diff=8448</id>
		<title>IC consensus layer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_consensus_layer&amp;diff=8448"/>
		<updated>2025-06-30T22:00:24Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34207558615956-Consensus}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_message_routing_layer&amp;diff=8447</id>
		<title>IC message routing layer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_message_routing_layer&amp;diff=8447"/>
		<updated>2025-06-30T22:00:02Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34208241927316-Message-Routing}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Internet Computer (IC) achieves its security and fault tolerance by replicating computation across node machines located in various independent data centers across the world. For scalability reasons, the Internet Computing Protocol (ICP) composes the IC of multiple independent subnets. Each subnet can be viewed as an independent replicated state machine that replicates its state over a subset of all the available nodes.&lt;br /&gt;
&lt;br /&gt;
Roughly speaking, replication is achieved by having the two lower ICP layers (P2P &amp;amp; Consensus) agree on blocks containing batches of messages to be executed, and then having the two upper ICP layers (Message Routing &amp;amp; Execution) execute them. Blocks are organized as a chain, where each block builds on the previous block. Each block has an associated height in the chain and one can look at execution of a batch of messages corresponding to the agreed upon block at height &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; by the upper layers as taking the replicated state of version &amp;lt;math&amp;gt;x-1&amp;lt;/math&amp;gt;, and &amp;quot;applying&amp;quot; the batch to it to obtain replicated state of version &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This document describes the role of the Message Routing layer in deterministic batch processing. Its responsibilities are:&lt;br /&gt;
* &#039;&#039;&#039;Coordinating the deterministic processing of batches:&#039;&#039;&#039; Fetching the right versions of the replicated state and the registry view to process the batch, triggering the deterministic processing, and committing the resulting replicated state.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Deterministic processing of batches:&#039;&#039;&#039; Deterministic processing of batches relative to some replicated state and some registry view, resulting in an updated replicated state.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Transferring message streams from one subnet to another:&#039;&#039;&#039; Moving streams from one subnet to another.&lt;br /&gt;
&lt;br /&gt;
=== Remarks and Required Prior Knowledge ===&lt;br /&gt;
&lt;br /&gt;
* The goal of this document is to provide the next level of detail compared to the material in the [https://internetcomputer.org/how-it-works &amp;quot;How it works&amp;quot; section of internetcomputer.org]. So it is recommended to study the material available there first.&lt;br /&gt;
* This page builds upon definitions made in the page describing the [[IC state manager|state manager]]. Please refer to this page for missing definitions related to the replicated state etc.&lt;br /&gt;
* Also see [https://mmapped.blog/posts/08-ic-xnet.html this] and [https://mmapped.blog/posts/02-ic-state-machine-replication.html this] blog post for some relevant and easier to digest background information.&lt;br /&gt;
* The documentation provided in this page may slightly deviate from the current implementation in terms of API as well as naming of functions, variables, etc. However, it still conveys the high-level ideas required to understand how the component itself works and how it interacts with other components. The implementation also contains several optimizations which are, however, not important for the conceptual overview here and therefore skipped.&lt;br /&gt;
* The notation used in this page is described [[Notation|here]].&lt;br /&gt;
&lt;br /&gt;
=== Replicated vs. Canonical State ===&lt;br /&gt;
While the external API functions defined in this document will always take state in its implementation specific representation, i.e., as &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt;, the operation the message routing component performs on the state based on its canonical representation, i.e., the &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is described. Given the relations between &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; as defined in the specification of the state manager, this will implicitly define how an implementation needs to act on the respective parts of the &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt;. An implicit conversion from &amp;lt;code&amp;gt;ReplicatedState&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is assumed whenever some state passed to this component via an API function is accessed.&lt;br /&gt;
&lt;br /&gt;
== Guarantees Provided by Message Routing ==&lt;br /&gt;
Intuitively, the goal of the message routing layer is to enable transparent communication of canisters across subnets. This means that this layer formally does not add any guarantees the system provides, but simply needs to make sure that system invariants are preserved. Those system invariants include&lt;br /&gt;
&lt;br /&gt;
* guaranteed replies (each canister-to-canister request will eventually receive a reply),&lt;br /&gt;
&lt;br /&gt;
* canister-to-canister ordering (the order of canister-to-canister requests sent from one canister to another canister is preserved), and&lt;br /&gt;
&lt;br /&gt;
* authenticity (only messages that come from canisters on the IC are processed).&lt;br /&gt;
&lt;br /&gt;
To ensure that the system invariants hold, message routing needs to provide the following guarantees:&lt;br /&gt;
&lt;br /&gt;
* Canister-to-canister messages will eventually be passed to the execution layer at the subnet the destination canister lives on exactly once.&lt;br /&gt;
&lt;br /&gt;
* If a message can not be delivered, a synthetic reject response must be produced.&lt;br /&gt;
&lt;br /&gt;
* If a canister &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; sends two messages &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; to a canister &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, then, if none of them gets synthetically rejected, it must be guaranteed that they are put in canister &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&#039;s input queue from &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; in that order.&lt;br /&gt;
&lt;br /&gt;
== Preliminaries ==&lt;br /&gt;
=== Description of the Relevant Parts of the Registry ===&lt;br /&gt;
The registry can be viewed as a central store of configuration information of the IC that is maintained by the NNS DAO. The content of the registry is held by a canister on the NNS subnet, and, roughly speaking, its authenticity is guaranteed by obtaining a certification on the content on behalf of the NNS using the certification mechanism as described in the [[IC state manager|state manager]] wiki page. Throughout this document it is assume that the registry contents are authentic.&lt;br /&gt;
&lt;br /&gt;
The registry entries required by this component are set of all existing subnet ids, as well as a canister-to-subnet mapping subnet_assignment. Note that the actual implementation may choose to represent the required fields differently as long as they are conceptually equivalent.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Registry {&lt;br /&gt;
    subnets : Set&amp;lt;SubnetId&amp;gt;,&lt;br /&gt;
	subnet_assignment: CanisterId ↦ SubnetId&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description of the Relevant Canonical State ===&lt;br /&gt;
This section defined the parts of the canonical state which are relevant for the description of this component together with some constraints imposed on the replicated state. Abstractly the &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is defined as a nested partial map. For easier readability the entries of the outermost map are bundled together in a data structure with multiple fields where the names of the fields represent the keys in the respective partial map, e.g., for some &amp;lt;code&amp;gt;s : CanonicalState&amp;lt;/code&amp;gt; one can use &amp;lt;code&amp;gt;s.ingress_queue&amp;lt;/code&amp;gt; to access &amp;lt;code&amp;gt;s[ingress_queues]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section defines the individual fields of the type &amp;lt;/code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; which are relevant in the context of this document. After that there are more details about the datatypes of the individual fields. There is a distinction made between the parts which are exclusively visible to message routing, and the parts which are also visible to the execution layer.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parts visible to message routing and execution&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CanonicalState {&lt;br /&gt;
    ...&lt;br /&gt;
    ingress_queues  : IngressQueues,&lt;br /&gt;
    input_queues    : InputQueues,&lt;br /&gt;
    output_queues   : OutputQueues,&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parts visible to Message Routing only&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CanonicalState {&lt;br /&gt;
    ...&lt;br /&gt;
    streams               : Streams,&lt;br /&gt;
    expected_xnet_indices : Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Even though there are parts of the state that are accessed by both message routing and execution, one can enforce a conceptual boundary between them. In particular, for input queues, message routing will only ever push messages to them, whereas for output queues, message routing will only ever pull messages from them. The opposite holds for the execution environment.&lt;br /&gt;
&lt;br /&gt;
==== Abstract Queues ====&lt;br /&gt;
Define a generic queue type &amp;lt;code&amp;gt;Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; which has the following fields:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Queue&amp;lt;T&amp;gt; {&lt;br /&gt;
    next_index : ℕ,     // Rolling index; the index of the next message to be inserted&lt;br /&gt;
    elements   : ℕ ↦ T  // The elements currently in the queue&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Define a new queue as &amp;lt;code&amp;gt;new_queue : Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;new_queue.elements = ∅&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;new_queue.next_index = 1&amp;lt;/code&amp;gt;. Furthermore, it has the following associated functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; takes a queue and a partial map of integers mapping to T, and returns a new queue consisting of the old queue with the given values appended. It also updates the next_index field so that it points to the index after the last inserted message.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;push : Self × (ℕ ↦ T) → Self&lt;br /&gt;
push(self, values) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index + |values|&lt;br /&gt;
            └─ elements := self.elements&lt;br /&gt;
                           ∪ { (i - 1 + k ↦ t) | i = self.next_index ∧&lt;br /&gt;
                                                 (j ↦ t) ∈ values ∧&lt;br /&gt;
                                                 k = rank(j, dom(values)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; removes the given elements from the queues keeping the &amp;lt;code&amp;gt;next_index&amp;lt;/code&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% REQUIRE: values ⊆ self.elements&lt;br /&gt;
delete : Self × (ℕ ↦ T) → Self&lt;br /&gt;
delete(self, values) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index&lt;br /&gt;
            └─ elements := self.elements&lt;br /&gt;
                           \ values&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;clear&amp;lt;/code&amp;gt; removes all elements from the queues keeping the next_index&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;clear : Self → Self&lt;br /&gt;
clear(self) :=&lt;br /&gt;
    self with&lt;br /&gt;
            ├─ next_index := self.next_index&lt;br /&gt;
            └─ elements := ∅&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Partial maps of type &amp;lt;code&amp;gt;SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; are often used, in which case the following shorthand notation is used. With &amp;lt;code&amp;gt;q&amp;lt;/code&amp;gt; being a queue of the aforementioned type, and &amp;lt;code&amp;gt;v&amp;lt;/code&amp;gt; being a partial map of type &amp;lt;code&amp;gt;(SomeIdentifier × ℕ) ↦ T&amp;lt;/code&amp;gt;, define the following semantic for the functions &amp;lt;code&amp;gt;f ∈ { push, delete }&amp;lt;/code&amp;gt; associated to &amp;lt;code&amp;gt;Queue&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;f_map : (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;) × ((SomeIdentifier × ℕ) ↦ T) → (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;)&lt;br /&gt;
f_map(q, v) = { (id ↦ queue&#039;) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                                (id ↦ values) ∈ v ∧&lt;br /&gt;
                                queue&#039; = f(queue, values)&lt;br /&gt;
              } ∪&lt;br /&gt;
              { (id ↦ queue&#039;) | (id ↦ values) ∈ v ∧&lt;br /&gt;
                                ∄ (id ↦ ·) ∈ q ∧&lt;br /&gt;
                                queue&#039; = f(Queue&amp;lt;T&amp;gt;::new_queue, values)&lt;br /&gt;
              } ∪&lt;br /&gt;
              { (id ↦ queue) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                               ∄ (id ↦ ·) ∈ v&lt;br /&gt;
              }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the functions &amp;lt;code&amp;gt;f ∈ { clear }&amp;lt;/code&amp;gt; use&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;f_map : (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;) → (SomeIdentifier ↦ Queue&amp;lt;T&amp;gt;)&lt;br /&gt;
f_map(q) = { (id ↦ queue&#039;) | (id ↦ queue) ∈ q ∧&lt;br /&gt;
                             queue&#039; = f(queue)&lt;br /&gt;
           }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Henceforth the &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; postfix will be omitted in &amp;lt;code&amp;gt;f_map&amp;lt;/code&amp;gt; and simply use &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; if it is clear from the input type that the map variant of &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; should be used.&lt;br /&gt;
&lt;br /&gt;
==== Indices ====&lt;br /&gt;
Define an &amp;lt;code&amp;gt;Index&amp;lt;/code&amp;gt; to be an arbitrary length sequence, where every element in the sequence up to the last one can have an arbitrary type, and the last one is a natural number.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Index : X × ... × Y × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition the following semantic is defined:&lt;br /&gt;
&lt;br /&gt;
* Define the prefix of an index Index &amp;lt;code&amp;gt;i := (x, …​, y, seq_nr)&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;prefix(i) := i[1…​|i| - 1] = (x, …​, y)&amp;lt;/code&amp;gt;, i.e., it contains all elements of i except the last one.&lt;br /&gt;
&lt;br /&gt;
* Define the postfix of an Index &amp;lt;code&amp;gt;i := (x, …​, y, seq_nr)&amp;lt;/code&amp;gt; as &amp;lt;/code&amp;gt;postfix(i) := i[|i|] = seq_nr&amp;lt;/code&amp;gt;, i.e., the last element of the index sequence. As already mentioned, the postfix of an index is required to be a natural number.&lt;br /&gt;
&lt;br /&gt;
* For an &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt;, the operation &amp;lt;math&amp;gt;i + 1&amp;lt;/math&amp;gt; is defined as &amp;lt;code&amp;gt;concatenate(prefix(i), postfix(i) + 1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Two indices, &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Index j&amp;lt;/code&amp;gt;, are incomparable if &amp;lt;code&amp;gt;prefix(i) ≠ prefix(j)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* For two indices, &amp;lt;code&amp;gt;Index i&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Index j&amp;lt;/code&amp;gt;, it is the case that &amp;lt;math&amp;gt;i \leq j&amp;lt;/math&amp;gt; if &amp;lt;code&amp;gt;prefix(i) = prefix(j)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;postfix(i) ≤ postfix(j)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Queues ====&lt;br /&gt;
&lt;br /&gt;
Three different types of queues exist in the replicated state: ingress queues, input queues, and output queues. Ingress queues contain the incoming messages from users (i.e., ingress messages). Input queues contain the incoming canister-to-canister messages. Output queues contain the outgoing canister-to-canister messages.&lt;br /&gt;
&lt;br /&gt;
Ingress queues are organized on a per destination basis. Messages in ingress queues are indexed by a concrete instance of Index called &amp;lt;code&amp;gt;IngressIndex&amp;lt;/code&amp;gt;, which is a tuple consisting of the destination canister ID and a natural number, i.e.,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;IngressIndex : CanisterId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Input queues and output queues are organized on a per-source-and-destination basis. Messages in input- and output queues are indexed by a concrete instance of Index called QueueIndex, which is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;QueueIndex : CanisterId × CanisterId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The type representing all of the ingress queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;IngressQueues : CanisterId ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;IngressQueues.elements : IngressIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The type representing all of the input queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;InputQueues : (CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;InputQueues.elements : QueueIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The type representing all of the output queues is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;OutputQueues : (CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;,&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;OutputQueues.elements : QueueIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Streams ====&lt;br /&gt;
Each individual &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; is scoped to a pair of subnets—​the subnet a stream originates from and subnet the stream is targeted at. An individual stream is organized in multiple substreams identified by a &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt;. The concrete definition of &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; is up to the implementation. In the current implementation &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; is defined to be the unit type &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;, i.e., flat streams. Messages in streams are indexed by a concrete instance of &amp;lt;code&amp;gt;Index&amp;lt;/code&amp;gt; called StreamIndex which is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;StreamIndex : SubstreamId × ℕ&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
A &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; is comprised of a sequence of &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; messages &amp;lt;code&amp;gt;signals&amp;lt;/code&amp;gt; and a sequence of canister-to-canister messages &amp;lt;code&amp;gt;msgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Stream {&lt;br /&gt;
    signals : StreamIndex ↦ {ACCEPT, REJECT},&lt;br /&gt;
    msgs    : SubstreamId ↦ Queue&amp;lt;Message&amp;gt;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
which means that &amp;lt;code&amp;gt;Stream.msgs.elements : StreamIndex ↦ Message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
While the subnet the stream originates from is implicitly determined, the target subnet needs to be made explicit. Hence, a data structure Streams is defined holding all streams indexed by destination subnetwork:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Streams : SubnetId ↦ Stream&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notation may be sometimes abused and directly access the fields defined for an individual &amp;lt;code&amp;gt;Stream&amp;lt;/code&amp;gt; on the Streams type, in which case maps of the following type are obtained:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Streams.signals : SubnetId ↦ (StreamIndex ↦ {ACCEPT, REJECT})&lt;br /&gt;
&lt;br /&gt;
Streams.msgs    : SubnetId ↦ (SubstreamId ↦ Queue&amp;lt;Message&amp;gt;)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== (Certified) Stream Slices ====&lt;br /&gt;
&amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt;, respectively, are used to transport streams from one to an other subnet within &amp;lt;code&amp;gt;XNetPayloads&amp;lt;/code&amp;gt; that are part of consensus blocks. Essentially, a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; is a slice of a stream which retains the begin and the end of the original stream. A &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; is wrapped in a &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; for transport so that authenticity can be guaranteed. Neither &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt; nor &amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; are ever explicitly created within message routing, but instead one relies on the encoding and decoding routines provided by the state manager: A &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; is created by calling the respective encoding routine of the state manager. Such a &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt; can then be decoded into a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; using the corresponding decoding routine provided by the state manager.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;StreamSlice {&lt;br /&gt;
    stream    : Stream,&lt;br /&gt;
    begin     : Set&amp;lt;StreamIndex&amp;gt;,&lt;br /&gt;
    end       : Set&amp;lt;StreamIndex&amp;gt;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;CertifiedStreamSlice {&lt;br /&gt;
    payload   : PartialCanonicalState&lt;br /&gt;
    witness   : Witness&lt;br /&gt;
    signature : Certification&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the precise relation of &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CertifiedStreamSlice&amp;lt;/code&amp;gt;, refer to the specification of the state manager.&lt;br /&gt;
&lt;br /&gt;
==== Batch ====&lt;br /&gt;
A batch consists of multiple elements including an &amp;lt;code&amp;gt;ingress_payload&amp;lt;/code&amp;gt; constituting a sequence of ingress messages, and an &amp;lt;code&amp;gt;xnet_payload&amp;lt;/code&amp;gt;.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Batch {&lt;br /&gt;
    batch_number             : Height&lt;br /&gt;
    registry_version         : RegistryVersion&lt;br /&gt;
    ingress_payload          : ℕ ↦ Message&lt;br /&gt;
    xnet_payload             : SubnetId ↦ CertifiedStreamSlice&lt;br /&gt;
    requires_full_state_hash : { TRUE, FALSE }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Decoded Batch ====&lt;br /&gt;
A decoded batch represents a batch where all transport-specific things are decoded into the format suitable for processing and some things which are not required inside the deterministic state machine are stripped off.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;DecodedBatch {&lt;br /&gt;
    ingress_payload : ℕ ↦ Message&lt;br /&gt;
    xnet_payload : SubnetId ↦ StreamSlice&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Currently this only means decoding the &amp;lt;code&amp;gt;CertifiedStreamSlices&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;StreamSlices&amp;lt;/code&amp;gt; because it is assumed that the ingress payload is suitable to be processed right away. Formally there is a function, which, based on the own subnet id and the given batch decodes the batch into a decoded batch:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;decode : SubnetId × Batch → DecodedBatch&lt;br /&gt;
decode(own_subnet, b) :=&lt;br /&gt;
    DecodedBatch {&lt;br /&gt;
        with&lt;br /&gt;
           ├─ ingress_payload := b.ingress_payload&lt;br /&gt;
           └─ xnet_payload :=&lt;br /&gt;
                  { (src_subnet ↦ slice) |&lt;br /&gt;
                      (src_subnet ↦ cert_slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                      slice = StateManager.decode_valid_certified_stream(own_subnet,&lt;br /&gt;
                                                                         cert_slice&lt;br /&gt;
                                                                        )&lt;br /&gt;
                  }&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Message Routing ==&lt;br /&gt;
Message routing is triggered by incoming batches from consensus. For each &amp;lt;code&amp;gt;Batch b&amp;lt;/code&amp;gt;, message routing will perform the following steps:&lt;br /&gt;
[[File:Message Routing Components.png|thumb|Components interacting with message routing during a deterministic processing round]]&lt;br /&gt;
[[File:MR Interactions.png|thumb|Interactions of message routing with other components during a deterministic processing round]]&lt;br /&gt;
&lt;br /&gt;
* Obtain the &amp;lt;code&amp;gt;ReplicatedState s&amp;lt;/code&amp;gt; of the right version w.r.t. &amp;lt;code&amp;gt;Batch b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Submit &amp;lt;code&amp;gt;s&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;decode(own_subnet, b)&amp;lt;/code&amp;gt; for processing by the deterministic state machine comprised of the message routing and execution layer. This includes&lt;br /&gt;
&lt;br /&gt;
** An induction phase (cf. &amp;lt;code&amp;gt;pre_process&amp;lt;/code&amp;gt;), where the valid messages in &amp;lt;code&amp;gt;decode(own_subnet, b)&amp;lt;/code&amp;gt; are inducted. Among others, a message m in a &amp;lt;code&amp;gt;StreamSlice&amp;lt;/code&amp;gt; from subnet &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; is considered valid if &amp;lt;code&amp;gt;registry.get_registry_at(b.registry_version).subnet_assignment&amp;lt;/code&amp;gt; maps &amp;lt;code&amp;gt;m.src&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
** An execution phase (cf. &amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;), which executes messages available in the induction pool.&lt;br /&gt;
&lt;br /&gt;
** An XNet message routing phase (cf. &amp;lt;code&amp;gt;post_process&amp;lt;/code&amp;gt;), which moves the messages produced in the execution phase from the per-session output queues to the subnet-to-subnet streams according to the mapping defined by the subnet assignment in the registry.&lt;br /&gt;
&lt;br /&gt;
* Commit the replicated state, incrementally updated by the previous steps, to the state manager via &amp;lt;code&amp;gt;commit_and_certify&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Deterministic State Machine ===&lt;br /&gt;
As shown in the sequence diagram above, the deterministic state machine implemented by message routing and execution applies batches provided by consensus to the appropriate state, additionally using some meta information provided by the registry. As discussed above, state of type &amp;lt;code&amp;gt;CanonicalState&amp;lt;/code&amp;gt; is used to generally describe the operations of the message-routing-related operations of this component.&lt;br /&gt;
&lt;br /&gt;
[[File:Message-routing-data-flow.png|thumb|Data flow during batch processing]]&lt;br /&gt;
&lt;br /&gt;
The flow diagram below details the operation of the component. Its operation is logically split into three phases.&lt;br /&gt;
&lt;br /&gt;
* The induction phase, where the messages contained in the batch are preprocessed. This includes extracting them from the batch and, subject to their validity and the decision of VSR, added to the induction pool or not.&lt;br /&gt;
&lt;br /&gt;
* The execution phase, where the hypervisor is triggered to perform an execution cycle. The important thing from a message routing perspective is that it will take messages from the input queues and process them, which causes messages to be added to the output queues.&lt;br /&gt;
&lt;br /&gt;
* The XNet message routing phase, where the messages produced in the execution cycle are post-processed. This means that they are taken from the canister-to-canister output queues and routed into the appropriate subnet-to-subnet streams.&lt;br /&gt;
&lt;br /&gt;
All messages will be added to the respective destination queue/stream preserving the order they appear in the respective source stream/queue.&lt;br /&gt;
&lt;br /&gt;
==== API ====&lt;br /&gt;
The deterministic state machine does not provide any external API functions. It only provides the following functions resembling the state transformations implemented by the individual steps of the deterministic state machine depicted above. Refer to the previous section for context regarding when the individual functions are called.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;pre_process(s : CanonicalState, subnet_assignment : (CanisterId ↦ SubnetId), b : DecodedBatch) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the induction phase.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;execute(s : CanonicalState) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the execution phase.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;post_process(s : CanonicalState, subnet_assignment : (CanisterId ↦ SubnetId)) → CanonicalState&amp;lt;/code&amp;gt;: Triggers the XNet message routing phase.&lt;br /&gt;
&lt;br /&gt;
==== Abstractions of Other Parts of the System ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Valid Set Rule (VSR)&#039;&#039;&#039;&lt;br /&gt;
The VSR is a component that makes the decision of whether to &amp;lt;code&amp;gt;ACCEPT&amp;lt;/code&amp;gt; a message or to &amp;lt;code&amp;gt;REJECT&amp;lt;/code&amp;gt; a message. For message routing, &amp;lt;code&amp;gt;ACCEPT&amp;lt;/code&amp;gt; has the semantic that the execution layer takes responsibility for the message, whereas &amp;lt;code&amp;gt;REJECT&amp;lt;/code&amp;gt; has the semantic that the message is dropped and may require action from the message routing layer.&lt;br /&gt;
&lt;br /&gt;
The operation of the VSR on ingress messages is defined as follows, where &amp;lt;code&amp;gt;vsr_check_ingress : CanonicalState × Batch → Set&amp;lt;ℕ&amp;gt;&amp;lt;/code&amp;gt; is a deterministic function returning the indices of the messages in the ingress payload accepted by the VSR, which returns a possibly empty set of index-message tuples corresponding to the accepted messages in the ingress_payload of the batch. The set is determined by the concrete implementation of the VSR.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;VSR(state, batch).ingress :=&lt;br /&gt;
  { ((m_i.dst, j) ↦ m_i) | (i ↦ m_i) ∈ batch.ingress_payload&lt;br /&gt;
                           ∧ i ∈ vsr_check_ingress(state, batch)&lt;br /&gt;
                           ∧ j = Rank(i, vsr_check_ingress(state, batch))&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The VSR for cross-net messages is defined as follows, where &amp;lt;code&amp;gt;vsr_check_xnet : CanonicalState × Batch → Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&amp;lt;/code&amp;gt; is a deterministic function that determines the indices of the messages in the individual substreams contained in &amp;lt;code&amp;gt;xnet_payload&amp;lt;/code&amp;gt; to be inducted.&lt;br /&gt;
&lt;br /&gt;
It is required that the implementation of the VSR (or the layer above) makes sure that all reply messages are accepted by the VSR. Formally this means that for any valid State-Batch combination &amp;lt;code&amp;gt;(s, b)&amp;lt;/code&amp;gt; it holds that for all &amp;lt;code&amp;gt;(subnet, index)&amp;lt;/code&amp;gt; so that &amp;lt;code&amp;gt;b.xnet_payload[subnet].msgs[index]&amp;lt;/code&amp;gt; is a reply message that &amp;lt;code&amp;gt;(subnet, index) ∈ vsr_check_xnet(s, b)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Based on this rule one can straight-forwardly define the interface behavior of the VSR.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;VSR(state, batch).xnet :=&lt;br /&gt;
  { (index ↦ msg) |&lt;br /&gt;
      (index ↦ msg) ∈ batch.xnet_payload.msgs ∧&lt;br /&gt;
      index ∈ vsr_check_xnet(state, batch)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
VSR(state, batch).signals :=&lt;br /&gt;
    { (concatenate(subnet, index) ↦ ACCEPT) |&lt;br /&gt;
      (subnet ↦ stream) ∈ batch.xnet_payload ∧&lt;br /&gt;
      (index ↦ msg) ∈ stream.msgs ∧&lt;br /&gt;
      (subnet, index) ∈ vsr_check_xnet(state, batch)&lt;br /&gt;
    }&lt;br /&gt;
  ∪ { (concatenate(subnet, index) ↦ REJECT) |&lt;br /&gt;
      (subnet ↦ stream) ∈ batch.xnet_payload ∧&lt;br /&gt;
      (index ↦ msg) ∈ stream.msgs ∧&lt;br /&gt;
      (subnet, index) ∉ vsr_check_xnet(state, batch)&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Scheduler and Hypervisor&#039;&#039;&#039;. From the point of view of message routing, one can look at the the scheduler and the hypervisor together as one component. The functionality of scheduler and hypervisor are modeled as a deterministic function &amp;lt;code&amp;gt;schedule_and_execute : CanonicalState → (IngressIndex ↦ Message) × (QueueIndex ↦ Message) × (QueueIndex ↦ Message)&amp;lt;/code&amp;gt; which computes the change set introduced by the Scheduler and the Hypervisor. It takes messages from the input queues, executes them and puts new messages to the output queues.&lt;br /&gt;
&lt;br /&gt;
This function will be used lated when it&#039;s described how the state transition function &amp;lt;code&amp;gt;execute(CanonicalState) → CanonicalState&amp;lt;/code&amp;gt; transforms the state. For the sake of compact notation, the following fields are used to access the individual return values of the schedule_and_execute function.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;consumed_ingress_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;IngressIndex ↦ Message&amp;lt;/code&amp;gt; containing all consumed ingress messages.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;consumed_xnet_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;QueueIndex ↦ Message&amp;lt;/code&amp;gt; containing all consumed cross-net messages.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;produced_messages&amp;lt;/code&amp;gt;, which contains a partial map &amp;lt;code&amp;gt;QueueIndex ↦ Message&amp;lt;/code&amp;gt; containing all produced messages, where the order of the messages implied by the queue index determines the order in which they need to be added to the queues.&lt;br /&gt;
&lt;br /&gt;
==== Description of the State Transitions ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Induction Phase&#039;&#039;&#039;. In the induction phase, one starts off with a &amp;lt;code&amp;gt;CanonicalState S&amp;lt;/code&amp;gt;, some &amp;lt;code&amp;gt;subnet_assignment&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;DecodedBatch b&amp;lt;/code&amp;gt; and applies &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; relative to &amp;lt;code&amp;gt;subnet_assignment&amp;lt;/code&amp;gt; to obtain &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt;, i.e., one computes &amp;lt;code&amp;gt;S&#039; = pre_process(S, subnet_assignment, b)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This section describes things w.r.t. to a version of the VSR which will accept all messages, while in reality the VSR may reject some messages in case canisters migrate across subnets or subnets are split. So while the possibility that messages can be REJECTed by the VSR would require specific action of the message routing layer those actions are omitted here for simplicity as they are not crucial to understand the basic functionality of message routing.&lt;br /&gt;
&lt;br /&gt;
Before defining the actual state transition, a couple of helper functions are defined. First, it is needed to define a function that determines the order of the messages in the queues based on the order of the messages in the incoming stream slices.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% REQUIRES: ∄ (s1 ↦ m1), (s2 ↦ m2) ∈ S :&lt;br /&gt;
%           └─ m1 = m2 ∧ s1 ≠ s2&lt;br /&gt;
%&lt;br /&gt;
% ENSURES: ∀ S satisfying the precondition above,&lt;br /&gt;
%          └─ ∀ (q1 ↦ m1), (q2 ↦ m2) ∈ queue_index(S) :&lt;br /&gt;
%             ├─ ∃ s1, s2 :&lt;br /&gt;
%             │  └─ (s1 ↦ m1) ∈ S ∧ (s2 ↦ m2) ∈ S ∧&lt;br /&gt;
%             └─ (m1.dst = m2.dst ∧ s1 ≤ s2) ==&amp;gt; q1 ≤ q2&lt;br /&gt;
%&lt;br /&gt;
queue_index: ((SubnetId × StreamIndex) ↦  Message) → ((CanisterId × ℕ) ↦ Message))&lt;br /&gt;
queue_index(S) := {&lt;br /&gt;
  % There is no concrete implementation of this function provided as there are&lt;br /&gt;
  % multiple possible implementations and the choice for one also depends on&lt;br /&gt;
  % how priorities/fairness etc. are handled.&lt;br /&gt;
  %&lt;br /&gt;
  % A trivial implementation is to iterate over the given stream slices S per&lt;br /&gt;
  % subnet and for each individual slice iterate over all the messages in the&lt;br /&gt;
  % order they appear in the slice and push each message m on the right queue,&lt;br /&gt;
  % i.e., the one belonging to the destination canister. This is also the way&lt;br /&gt;
  % things are currently implemented.&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Based on this a function can now be defined that maps over the indexes of the valid XNet messages.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;map_valid_xnet_messages : (SubnetId ↦ Slice) ×&lt;br /&gt;
                          (CanisterId ↦ SubnetId) →&lt;br /&gt;
                          ((CanisterId × ℕ) ↦ Message)&lt;br /&gt;
map_valid_xnet_messages(slices, subnet_assignment) :=&lt;br /&gt;
    queue_index({ ((subnet, index) ↦ m) | (subnet ↦ slice) ∈ slices ∧&lt;br /&gt;
                                          (index ↦ m) ∈ slice.msgs ∧&lt;br /&gt;
                                          subnet_assignment[m.src] = subnet ∧&lt;br /&gt;
&lt;br /&gt;
               })&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;pre_process(S, b)&amp;lt;/code&amp;gt; can be defined:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Append the ingress messages accepted by the VSR to the appropriate ingress_queue&lt;br /&gt;
  ingress_queues            := push(S.ingress_queues, VSR(S, b).ingress)&lt;br /&gt;
&lt;br /&gt;
  % Append the canister to canister messages accepted by the VSR to the appropriate&lt;br /&gt;
  % input queue.&lt;br /&gt;
  input_queues              := push(S.input_queues,&lt;br /&gt;
                                    map_valid_xnet_messages(VSR(S, b).xnet, subnet_assignment)&lt;br /&gt;
                                   )&lt;br /&gt;
&lt;br /&gt;
  % Garbage collect the messages which have accepted by the target subnet.&lt;br /&gt;
  % (As soon as the VSR does no longer ACCEPT all messages, one would have&lt;br /&gt;
  %  to make sure that rejected messages are appropriately re-enqueued in&lt;br /&gt;
  %  the streams)&lt;br /&gt;
  streams.msgs              := delete(S.streams.msgs,&lt;br /&gt;
                                 { (concatenate(subnet, index) ↦ msg) |&lt;br /&gt;
                                       (subnet ↦ slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                                       (i ↦ ·) ∈ slice.signals ∧&lt;br /&gt;
                                       index = concatenate(subnet, i)&lt;br /&gt;
                                 }&lt;br /&gt;
                               )&lt;br /&gt;
&lt;br /&gt;
  % Add the signals reflecting the decisions made by the VSR in the current round and&lt;br /&gt;
  % garbage collect the signals which have already been processed on the other subnet&lt;br /&gt;
  % (one knows that a signal has been processed when the message is no longer included&lt;br /&gt;
  % in a given slice).&lt;br /&gt;
  streams.signals           := S.streams.signals&lt;br /&gt;
                               ∪ VSR(S, b).signals&lt;br /&gt;
                               \ { (index ↦ signal) |&lt;br /&gt;
                                       (subnet ↦ slice) ∈ b.xnet_payload ∧&lt;br /&gt;
                                       (i ↦ signal) ∈ S.streams[subnet].signals ∧&lt;br /&gt;
                                       index = concatenate(subnet, i) ∧&lt;br /&gt;
                                       j ∈ slice.begin ∧&lt;br /&gt;
                                       i &amp;lt; j&lt;br /&gt;
                                 }&lt;br /&gt;
&lt;br /&gt;
  % Update the expected XNet indexes so that the block maker can compute which messages&lt;br /&gt;
  % to include in a block referencing this state.&lt;br /&gt;
  expected_xnet_indices     := { index     | index ∈ S.expected_xnet_indices ∧&lt;br /&gt;
                                             ∄ (i ↦ ·) ∈ b.xnet_payload.msgs.elements :&lt;br /&gt;
                                             └─ prefix(index) = prefix(i)&lt;br /&gt;
                               } ∪&lt;br /&gt;
                               { index + 1 | index ∈ max(dom(b.xnet_payload.msgs.elements)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Execution Phase&#039;&#039;&#039;. In the execution phase, one starts off with a &amp;lt;code&amp;gt;CanonicalState S&amp;lt;/code&amp;gt;, schedules messages for execution by the hypervisor, and triggers the hypervisor to execute them, i.e., one computes &amp;lt;code&amp;gt;S&#039; = execute(S)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; is the state after the induction phase. From the perspective of message routing, the state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;execute(S)&amp;lt;/code&amp;gt; looks as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Delete the consumed ingress messages from the respective ingress queues&lt;br /&gt;
  ingress_queues    := delete(S.ingress_queue, schedule_and_execute(S).consumed_ingress_messages)&lt;br /&gt;
&lt;br /&gt;
  % Delete the consumed canister to canister messages from the respective input queues&lt;br /&gt;
  input_queues      := delete(S.input_queues, schedule_and_execute(S).consumed_xnet_messages)&lt;br /&gt;
&lt;br /&gt;
  % Append the produced messages to the respective output queues&lt;br /&gt;
  output_queues     := push(S.output_queues, schedule_and_execute(S).produced_messages)&lt;br /&gt;
&lt;br /&gt;
  % Execution specific state is transformed by the execution environment; the precise transition&lt;br /&gt;
  % function is out of scope here.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XNet Message Routing Phase&#039;&#039;&#039;. In the XNet message routing phase, one takes all the messages from the canister-to-canister output queues and, according to the subnet_assignment, puts them into a subnet-to-subnet stream, i.e., it computes &amp;lt;code&amp;gt;S&#039; = post_process(S, registry)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; is the state after the execution phase and registry represents a view of the registry.&lt;br /&gt;
&lt;br /&gt;
Before defining the state transition, a helper function is defined to appropriately handle messages targeted at canisters that do not exist according to the given subnet assignment.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Remove all messages from output queues targeted at non-existent canisters according&lt;br /&gt;
% to the subnet assignment.&lt;br /&gt;
filter : ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;) × (CanisterId ↦ SubnetId) → ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;)&lt;br /&gt;
filter(queues, subnet_assignment) :=&lt;br /&gt;
    delete(queues, { (q_index ↦ msg) | (q_index ↦ msg) ∈ queues.elements ∧&lt;br /&gt;
                                       q_index = (·, dst, ·) ∧&lt;br /&gt;
                                       dst ∉ dom(subnet_assignment)&lt;br /&gt;
                   }&lt;br /&gt;
          )&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Produce &amp;lt;code&amp;gt;NON_EXISTENT_CANISTER&amp;lt;/code&amp;gt; replies telling the sending canister that the destination canister does not exist.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Produce NON_EXISTENT_CANISTER messages to be pushed to input queues &lt;br /&gt;
% of the senders of messages where the destination does not exist&lt;br /&gt;
non_existent_canister_replies : ((CanisterId × CanisterId) ↦ Queue&amp;lt;Message&amp;gt;) × (CanisterId ↦ SubnetId) → (QueueIndex ↦ Message)&lt;br /&gt;
non_existent_canister_replies(queues, subnet_assignment) :=&lt;br /&gt;
  { ((dst, src, i) ↦ NON_EXISTENT_CANISTER) | (q_index ↦ msg) ∈ queues.elements ∧&lt;br /&gt;
                                              q_index = (src, dst, i) ∧&lt;br /&gt;
                                              dst ∉ dom(subnet_assignment)&lt;br /&gt;
  })&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Non flat streams.&#039;&#039; As already mentioned before, the specification leaves it open whether one flat stream is produced per destination subnet, or whether each of the streams has multiple substreams—​this can be decided by the implementation. To enable this, a &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be a tuple of &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; and a natural number. If there is a flat stream, &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be the unit type &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt; which effectively means that the implementation can use natural numbers as stream index as one does not need to make the &amp;lt;code&amp;gt;SubstreamId&amp;lt;/code&amp;gt; explicit in this case. In contrast, if there is a per-destination (or per-source) substreams, &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt; is defined to be a &amp;lt;code&amp;gt;CanisterId&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Formally, this means that the implementation must fix a mapping function that—​based on a given prefix of a &amp;lt;code&amp;gt;QueueIndex&amp;lt;/code&amp;gt;, i.e., a src-dst tuple—​decides on the prefix of the &amp;lt;code&amp;gt;StreamIndex&amp;lt;/code&amp;gt;, i.e., the SubstreamId.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;substream_id: (CanisterId × CanisterId) → SubstreamId&lt;br /&gt;
&lt;br /&gt;
% Definition of substream_id for flat streams&lt;br /&gt;
substream_id((src, dst)) := ()&lt;br /&gt;
&lt;br /&gt;
% Definition of substream_id for per-destination canister substreams&lt;br /&gt;
substream_id((src, dst)) := dst&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Description of the actual state transition&#039;&#039;. The state &amp;lt;code&amp;gt;S&#039;&amp;lt;/code&amp;gt; resulting from computing &amp;lt;code&amp;gt;post_process(S, subnet_assignment)&amp;lt;/code&amp;gt; is defined as follows:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;S with&lt;br /&gt;
  % Clear the output queues&lt;br /&gt;
  output_queues := clear(S.output_queues)&lt;br /&gt;
&lt;br /&gt;
  % Route the messages produced in the previous execution phase to the appropriate streams&lt;br /&gt;
  % taking into account ordering and capacity management constraints enforced by stream_index.&lt;br /&gt;
  streams.msgs  := {&lt;br /&gt;
    let msgs = S.streams.msgs&lt;br /&gt;
&lt;br /&gt;
    % Iterate over filtered messages preserving order of messages in queues.&lt;br /&gt;
    for each (q_index ↦ msg) ∈ filter(S.output_queues, subnet_assignment)&lt;br /&gt;
      msgs = push(msgs, { (concatenate(substream_id(prefix(q_index)), postfix(q_index)) ↦ msg) })&lt;br /&gt;
&lt;br /&gt;
    return msgs&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  % Push NON_EXISTENT_CANISTER replies to input queues of the respective canisters&lt;br /&gt;
  input_queues := push(S.input_queues,&lt;br /&gt;
                       non_existent_canister_replies(S.output_queues, subnet_assignment))&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ordering of Messages in the Stream &amp;amp; Fairness&#039;&#039;. As long as the invariant that the canister-to-canister ordering of messages is preserved when iterating over the filtered messages in the state transition described above, the implementation can take the freedom to apply alternative orderings.&lt;br /&gt;
&lt;br /&gt;
Also note that, while the state transition defined above empties the output queues completely, this is not crucial to the design and one could hold back messages as long as this does not violate the ordering requirement.&lt;br /&gt;
&lt;br /&gt;
== XNet Transfer ==&lt;br /&gt;
After calling &amp;lt;code&amp;gt;commit_and_certify&amp;lt;/code&amp;gt; at the end of a deterministic processing cycle, the state manager will take care of getting the committed state certified. Once certification is complete, the certified stream slices can be made available to block makers on other subnets. The &amp;lt;code&amp;gt;XNetTransfer&amp;lt;/code&amp;gt; subcomponent is responsible to enable this transfer. It consists of&lt;br /&gt;
&lt;br /&gt;
[[File:Xnet.png|thumb|XNet transfer component diagram]]&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; which is responsible for serving certified stream slices and making them available to &amp;lt;code&amp;gt;XNetPayloadBuilders&amp;lt;/code&amp;gt; on other subnetworks.&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;, which allows the block makers to obtain an &amp;lt;code&amp;gt;XNetPayload&amp;lt;/code&amp;gt; containing the currently available certified streams originating from other subnetworks. The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; obtains those streams by interacting with &amp;lt;code&amp;gt;XNetEndpoints&amp;lt;/code&amp;gt; exposed by other subnets. The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; also provides functionality for notaries to verify &amp;lt;code&amp;gt;XNetPayloads&amp;lt;/code&amp;gt; contained in block proposals.&lt;br /&gt;
&lt;br /&gt;
There are no specifications about the protocol run between the &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; to transfer the streams between two subnetworks. The only requirement is that certified streams made available by an &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; of an honest replica on some source subnetwork, they can be obtained by an &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; of an honest replica on the destination subnetwork and that the information regarding which endpoints to contact is available in the Registry.&lt;br /&gt;
&lt;br /&gt;
=== Properties and Functionality ===&lt;br /&gt;
Assume an XNet transfer component on a replica part of subnet &amp;lt;code&amp;gt;own_subnet&amp;lt;/code&amp;gt;. The interface behavior of the XNet transfer component will guarantee that for any payload payload produced via&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;get_xnet_payload(registry_version, reference_height, past_payloads, size_limit)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For any &amp;lt;code&amp;gt;(remote_subnet ↦ css) ∈ payload&amp;lt;/code&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;StateManager.decode_certified_stream(registry_version, own_subnet, remote_subnet, css)&amp;lt;/code&amp;gt; succeeds, i.e., returns a valid slice slice that is guaranteed to come from remote_subnet.&lt;br /&gt;
&lt;br /&gt;
* Furthermore, for each slice it will hold that a soon as the state corresponding to height &amp;lt;code&amp;gt;h = reference_height + |past_payloads|&amp;lt;/code&amp;gt; is available that &amp;lt;code&amp;gt;concatenate(remote_subnet, min(dom(slice.msgs.elements))) ∈ StateManager.get_state_at(h).expected_indexes&amp;lt;/code&amp;gt;. This means that the streams will start with the expected indexes stored in the previous state, i.e., they gap freely extend the previously seen streams.&lt;br /&gt;
&lt;br /&gt;
Payloads verified using &amp;lt;code&amp;gt;validate_xnet_payload&amp;lt;/code&amp;gt; are accepted if they adhere to those requirements, and are rejected otherwise.&lt;br /&gt;
&lt;br /&gt;
=== XNet Endpoint ===&lt;br /&gt;
The &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; serves the streams available on some subnet to other subnets. For an implementation this will typically mean that there is some client which will handle querying the API of the &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; on the remote subnet in question. The following abstraction is used to avoid explicitly talking about this client: Assume that there is a function &amp;lt;code&amp;gt;get : SubnetId → XNetEndpoint&amp;lt;/code&amp;gt; which will return an appropriate instance of &amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; which can directly be queried using the API described below.&lt;br /&gt;
&lt;br /&gt;
[[File:Xnet-sequence.png|thumb|XNet transfer sequence diagram]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get_stream(subnet_id : SubnetId, begin : StreamIndex, msg_limit : ℕ, size_limit : ℕ) → CertifiedStreamSlice&amp;lt;/code&amp;gt;: Returns the requested certified stream slice in its transport format.&lt;br /&gt;
&lt;br /&gt;
It is required that an honest &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;XNetEndpoint&amp;lt;/code&amp;gt; pair is able to successfully obtain slices over this API.&lt;br /&gt;
&lt;br /&gt;
Looking at the bigger picture, the intuition for why this will yield a secure system is that in each round a new pair of block maker and endpoint will try to pull over a stream, which, in turn, means that eventually an honest pair will be able to obtain the stream and include it into a block.&lt;br /&gt;
&lt;br /&gt;
=== XNet Payload Builder ===&lt;br /&gt;
The &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; builds and verifies payloads whenever requested to do so by the block maker. The rules for whether a payload is considered valid or not must be so that every notary is guaranteed to make the same decision on the same input and that a payload built by an honest payload builder will be accepted by honest validators. Essentially the rules resemble what is described in the section on properties and functionality. However, given that the execution may be behind one can not directly look up the expected indexes in the appropriate state but need to compute it based on the referenced state and the payloads since then. Below, a figure is provided to illustrate the high-level functionality: generally speaking blocks are considered valid if they adhere to the rules described in the figure and are considered invalid otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Payload-building.png|thumb|Rules for payload building]]&lt;br /&gt;
&lt;br /&gt;
This section formally defines the operation of the component. The following helper functions are first defined. Assume that &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt; has an associated field &amp;lt;code&amp;gt;own_subnet&amp;lt;/code&amp;gt; which is passed whenever constructing an &amp;lt;code&amp;gt;XNetPayloadBuilder&amp;lt;/code&amp;gt;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;new : SubnetId → Self&lt;br /&gt;
new(own_subnet) :=&lt;br /&gt;
  XNetPayloadBuilder {&lt;br /&gt;
      with&lt;br /&gt;
         └─ own_subnet := own_subnet&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The API defines the past_payloads as a vector where the past payloads are ordered with respect to the corresponding height in the chain. While this ordering allows for a more efficient implementation of the functions below it does not matter on a conceptual level. Hence resort to looking at it as a set for the sake of simplicity.&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;slice_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, solely based on a set of Slices.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Take the maximum index for each individual (sub-)stream in the given set of slices and add&lt;br /&gt;
% 1 to obtain the next indexes one would expect when solely looking at the past payloads but&lt;br /&gt;
% ignoring the state.&lt;br /&gt;
slice_indexes : (SubnetId ↦ StreamSlice) → Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
slice_indexes(slices) := { i + 1 | i ∈ max(dom(slices.msgs.elements)) }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;state_and_payload_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, taking into account both the expected indices in the given replicated state and the more recent messages in the given slices from the past payloads.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Take the expected indexes from the state, remove whatever index appears in the given&lt;br /&gt;
% slices and add the expected indexes according to the streams in the slices.&lt;br /&gt;
%&lt;br /&gt;
% FAIL IF: ∃ i, j ∈ state_and_payload_indexes(state, slices) :&lt;br /&gt;
%              prefix(i) = prefix(j) ∧ postfix(i) ≠ postfix(j)&lt;br /&gt;
%&lt;br /&gt;
state_and_payload_indexes : ReplicatedState ×&lt;br /&gt;
                            (SubnetId ↦ StreamSlice) →&lt;br /&gt;
                            Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
state_and_payload_indexes(state, slices) := state.expected_xnet_indices&lt;br /&gt;
                                            \ dom(slices.msgs.elements)&lt;br /&gt;
                                            ∪ slice_indexes(slices)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The function &amp;lt;code&amp;gt;expected_indexes&amp;lt;/code&amp;gt; returns the set of expected indices for the block to be proposed, taking into account both the expected indices in the given replicated state and the more recent messages in the given past payloads.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Decode the slices in the given payload and compute the expected indexes using the&lt;br /&gt;
% expected_indexes function above&lt;br /&gt;
expected_indexes : SubnetId ×&lt;br /&gt;
                   ReplicatedState ×&lt;br /&gt;
                   (SubnetId ↦ StreamSlice) →&lt;br /&gt;
                   Set&amp;lt;(SubnetId × StreamIndex)&amp;gt;&lt;br /&gt;
expected_indexes(own_subnet, state, slices) :=&lt;br /&gt;
    state_and_payload_indexes(&lt;br /&gt;
        state,&lt;br /&gt;
        { (src ↦ slice) | payload ∈ slices ∧&lt;br /&gt;
                          (src ↦ cert_slice) ∈ payload ∧&lt;br /&gt;
                          slice = StateManager.decode_valid_certified_stream(own_subnet,&lt;br /&gt;
                                                                             cert_slice)&lt;br /&gt;
        }&lt;br /&gt;
    )&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Creation of XNet Payloads ====&lt;br /&gt;
Based on the functions above, it is possible to define the function &amp;lt;code&amp;gt;get_xnet_payload : Height × Height × Set&amp;lt;XNetPayload&amp;gt; → XNetPayload&amp;lt;/code&amp;gt;. Note that the gap-freeness of streams is an invariant of the datatype, which is why the rule for gap-freeness is not explicitly included here.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Build an xnet payload containing the currently available streams. The begin is either given&lt;br /&gt;
% by the expected index, and, if there is no expected index for a given prefix, the index&lt;br /&gt;
% ONE is expected.&lt;br /&gt;
%&lt;br /&gt;
% ENSURES: size_of(get_xnet_payload(self, ·, ·, ·, size_limit)) ≤ size_limit ∧&lt;br /&gt;
%          each payload output by get_xnet_payload will be accepted by validate_xnet_payload&lt;br /&gt;
%&lt;br /&gt;
get_xnet_payload : Self × RegistryVersion × Height × Vec&amp;lt;XNetPayload&amp;gt; × ℕ → XNetPayload&lt;br /&gt;
get_xnet_payload(self, registry_version, reference_height, past_payloads, size_limit) :=&lt;br /&gt;
    { (remote_subnet ↦ slice) |&lt;br /&gt;
            S = StateManager.get_state_at(reference_height)&lt;br /&gt;
          ∧ subnets = Registry::get_registry_at(registry_version).subnets \ { self.own_subnet }&lt;br /&gt;
          ∧ (remote_subnet, begin_index) ∈&lt;br /&gt;
                  expected_indexes(self.own_subnet, S, past_payloads)&lt;br /&gt;
                ∪ { (subnet_id, StreamIndex::ONE) |&lt;br /&gt;
                        subnet_id ∈ subnets&lt;br /&gt;
                                    \ { s | (s, ·) ∈ expected_indexes(self.own_subnet,&lt;br /&gt;
                                                                      S,&lt;br /&gt;
                                                                      past_payloads)&lt;br /&gt;
                                      }&lt;br /&gt;
                  }&lt;br /&gt;
            % msg_limit and size limit need to be set by the implementation as appropriate&lt;br /&gt;
            % to satisfy the post condition&lt;br /&gt;
          ∧ slice = XNetEndpoint::get(subnet).get_stream(remote_subnet, begin_index, ·, ·)&lt;br /&gt;
          ∧ ERR ≠ StateManager.decode_certified_stream(registry_version,&lt;br /&gt;
                                                       self.own_subnet,&lt;br /&gt;
                                                       remote_subnet,&lt;br /&gt;
                                                       slice)&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Validation of XNet Payloads ====&lt;br /&gt;
Validation of XNetPayloads works analogously to the creation. The function &amp;lt;code&amp;gt;validate_xnet_payload&amp;lt;/code&amp;gt; is defined as follows, where it is assumed that it evaluates to false in case an error occurs. Again, note that the gap-freeness of streams is an invariant of the datatype, which is why the rule for gap-freeness is not explicitly included here.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;% Check whether a given xnet payload was built according to the rules given above.&lt;br /&gt;
%&lt;br /&gt;
% FAIL IF: size_of(payload) &amp;gt; size_limit&lt;br /&gt;
%&lt;br /&gt;
validate_xnet_payload : Self × RegistryVersion × Height × Vec&amp;lt;XNetPayload&amp;gt; × XNetPayload × ℕ → Bool&lt;br /&gt;
validate_xnet_payload(self, registry_version, reference_height, past_payloads, payload, size_limit) :=&lt;br /&gt;
    S = StateManager.get_state_at(reference_height) ∧&lt;br /&gt;
    ∀ (remote_subnet ↦ css) ∈ payload :&lt;br /&gt;
    {&lt;br /&gt;
      slice = StateManager.decode_certified_stream(registry_version,&lt;br /&gt;
                                                   self.own_subnet,&lt;br /&gt;
                                                   remote_subnet,&lt;br /&gt;
                                                   css) ∧&lt;br /&gt;
      ∀ index ∈ min(dom(slice.msgs.elements)) :&lt;br /&gt;
      {&lt;br /&gt;
        (remote_subnet, index) ∈ expected_indexes(S, past_payloads) ∨&lt;br /&gt;
        index = (remote_subnet, StreamIndex::ONE)&lt;br /&gt;
      }&lt;br /&gt;
    }&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_execution_layer&amp;diff=8446</id>
		<title>IC execution layer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_execution_layer&amp;diff=8446"/>
		<updated>2025-06-30T21:59:27Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34208985618836-Execution-Layer}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Trustless_multi-chain_web3_using_the_IC&amp;diff=8445</id>
		<title>Trustless multi-chain web3 using the IC</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Trustless_multi-chain_web3_using_the_IC&amp;diff=8445"/>
		<updated>2025-06-30T21:39:16Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34329023770260-Chain-Fusion}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;On the Internet Computer, you can [https://internetcomputer.org/multichain create smart contracts that directly interact with other blockchains], without trusted centralized bridges that can get hacked and do rug pulls. This has been made possible using [[chain key cryptography]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Decentralized applications and services can delight users by incorporating the assets and functionality of multiple blockchains. Using the Internet Computer, developers gain the technical superpowers necessary to deliver such game-changing experiences, while preserving user safety and convenience.&lt;br /&gt;
&lt;br /&gt;
The web3 environment contains multiple blockchains that have different characteristics and excel in different roles. A key web3 philosophy is [https://en.wikipedia.org/wiki/Service_composability_principle service composability], in which different blockchain services are composed to create new services and functionality. Tokenized assets and liquidity must also be able to move between services, whichever blockchain they are on. The Internet Computer provides a means to fully support this paradigm in a multi-chain environment without need for trusted bridges run by central controllers such as companies.&lt;br /&gt;
&lt;br /&gt;
For example, when building a DeFi framework on the Ethereum blockchain today, a means must be found to create the user experience. Typically, this is built on centralized servers or cloud services today, creating a serious security vulnerability, and exposing the developers who pay for the servers or cloud services to legal liabilities (since regulators can argue that the service built using Ethereum is not running in the mode of a decentralized protocol). Therefore, it would be better if the user experience could be created on the Internet Computer using canister smart contracts, which are controlled by a DAO. A means has been provided to do this (please check developers docs to see what is in production at any one time).&lt;br /&gt;
&lt;br /&gt;
The functionality has been provided by extending the novel [[chain key cryptography]] protocols that power the Internet Computer. These protocols provide each [[Limitless_Scaling#Subnet Architecture|subnet blockchain]] within the overall Internet Computer network with their own public [[chain key]], for which they can create cryptographic signatures  on messages that prove returned results have not been tampered with, and that they are operating correctly (for the technically minded: this functionality involves consensus that depends on [https://en.wikipedia.org/wiki/Threshold_cryptosystem threshold cryptography] and other cryptography schemes, including [https://internetcomputer.org/how-it-works/noninteractive-distributed-key-generation-nidkg/ non-interactive distributed key generation] (NIDKG) and key resharing techniques, which provide for chain keys to be maintained indefinitely, even as network nodes come and go, with signing scaled using [https://en.wikipedia.org/wiki/Merkle_tree Merkle trees]).&lt;br /&gt;
&lt;br /&gt;
The chain key cryptography protocol engine was extended so that hosted smart contracts can maintain [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] public keys, and make corresponding signatures, without need to store a [https://en.wikipedia.org/wiki/Public-key_cryptography private key] on the blockchain in a way that would allow it to be stolen. Crucially, ECDSA is the signature scheme used to sign TX on &#039;&#039;other blockchains&#039;&#039;, and allows smart contracts on the Internet Computer to create TX that other blockchains directly execute. &lt;br /&gt;
&lt;br /&gt;
One application has been the provision of special Bitcoin capabilities to canister smart contracts. This allows them to create bitcoin addresses, and send and receive bitcoin directly &#039;&#039;on&#039;&#039; the Bitcoin ledger, without any need for insecure trusted intermediaries such as bridges. Essentially, smart contracts on the Internet Computer can process bitcoin almost as though they are hosted by the Bitcoin network themselves. This provides a way to use bitcoin within web3 services built on the Internet Computer, without asking users to wrap their bitcoin using a trusted bridge run by central controller, which might get hacked, or do a &amp;quot;rug pull&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Another application is the signing of TX designed to invoke smart contracts on other blockchains, such as Ethereum. For example, to interact with Ethereum, an Internet Computer canister smart contract would first create an ECDSA public key that functions as an [https://ethereum.org/en/developers/docs/accounts/ Ethereum Account] (before use this should be charged with some ETH to pay for gas). Thereafter, the smart contract can invoke smart contract calls on the Ethereum blockchain, by creating and signing appropriate Ethereum TX that will be executed by Ethereum network. The smart contract can then determine the results of the TX by using the [[HTTPS outcalls]] feature to interact with Ethereum local nodes.&lt;br /&gt;
&lt;br /&gt;
Using the power of chain key cryptography, the Internet Computer can thus be used as an orchestration blockchain, or meta blockchain, upon which new services can be built that combine functionality and assets provided by &#039;&#039;other blockchains&#039;&#039; in the web3 universe - all without the need to trust a central party, and without the inconvenience and risk of using wrapping and bridges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pro tip: At the time of writing, there are no other blockchains in existence that can create TX on other blockchains for their smart contracts. Blockchains that talk about &amp;quot;native integrations&amp;quot; are usually talking about a bridge run by the company that backs them.&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Network_Nervous_System&amp;diff=8444</id>
		<title>Network Nervous System</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Network_Nervous_System&amp;diff=8444"/>
		<updated>2025-06-30T21:38:40Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/33692645961236-Overview}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Chain_key_cryptography&amp;diff=8443</id>
		<title>Chain key cryptography</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Chain_key_cryptography&amp;diff=8443"/>
		<updated>2025-06-30T21:38:17Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/references/t-sigs-how-it-works}}&lt;br /&gt;
&lt;br /&gt;
Please see this description of [https://medium.com/dfinity/chain-key-technology-one-public-key-for-the-internet-computer-6a3644901e28 chain key cryptography].&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Replace_traditional_IT_with_a_World_Computer&amp;diff=8442</id>
		<title>Replace traditional IT with a World Computer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Replace_traditional_IT_with_a_World_Computer&amp;diff=8442"/>
		<updated>2025-06-30T21:37:50Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34574399808788-ICP-and-the-Internet}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The Internet Computer aims to realize the [[World Computer]] vision first mooted within the [[Ethereum]] community in 2014. It is an open and decentralized platform that provides an alternative to the traditional IT stack, which is comprised of things such as [[cloud computing]] services, server computers, database servers, web servers, middleware, backup systems, and security infrastructure such as firewalls. The Internet Computer network provides an alternative platform that can be used to build and run almost any online system or service.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How, you might ask, can a public network provide an alternative to the $5-trillion-dollar-a-year IT industry (according to Gartner). The answer is that the Internet Computer is a radical new form of blockchain made possible by [[chain key cryptography|novel cryptography]] and math. Unlike traditional blockchains, it does not need to indefinitely store old blocks of transactions, does not need [[local node]]s in its network, and can scale its capacity to host compute, with orders of magnitude more efficiency.&lt;br /&gt;
&lt;br /&gt;
On the Internet Computer, developers can build almost any online system or service desired, just by writing [[canister smart contract]] code. Canisters are [[smart contract]]s with breakthrough levels of efficiency, have the speed to process HTTP requests and serve interactive web experiences directly to end users, and can be composed to &#039;&#039;build almost any system or service&#039;&#039;. Furthermore, their data is weakly private, with stronger privacy options in the works. Yet, while they work differently, for example running in parallel, they also have the key magical properties of traditional [[smart contract]]s.&lt;br /&gt;
&lt;br /&gt;
For example, [[canister]]s are unstoppable, and also tamperproof, which means that when their code is invoked, the Internet Computer is guaranteed to run the correct logic against the correct data. Furthermore, they can be made to run autonomously if required, and can process tokens.&lt;br /&gt;
&lt;br /&gt;
===No firewalls or security infrastructure necessary===&lt;br /&gt;
&lt;br /&gt;
One obvious advantage that the Internet Computer provides over traditional IT is security.&lt;br /&gt;
&lt;br /&gt;
Systems and services running from the Internet Computer, which have been built using canister smart contracts, don&#039;t need to be protected by firewalls. This is similar to how DeFi smart contracts on [[Ethereum]] don&#039;t need to be protected by firewalls. Instead, they are secure by default, which is the exact opposite of systems built using traditional software that run on traditional IT, which have no security by default, and must be protected by teams of security administrators, special configurations, and special security tech such as [https://en.wikipedia.org/wiki/Firewall_(computing) firewalls] and [https://en.wikipedia.org/wiki/Security_information_and_event_management SIEM logging].&lt;br /&gt;
&lt;br /&gt;
[https://www.vox.com/recode/22428774/ransomeware-pipeline-colonial-darkside-gas-prices When systems and services are built using traditional IT, just one simple mistake can allow a hacker can steal data, or encrypt systems using ransomware, with catastrophic results], and it happens all the time. In 2022, worldwide expenditure on IT security will be $172 billion dollars (according to Gartner), but the intangible costs of constant hacks and potential business disruption is much higher.&lt;br /&gt;
&lt;br /&gt;
Traditional IT is in the midst of a security meltdown, and the Internet Computer provides a way out. Because systems built on the Internet Computer using canisters are secure by default, the costs involved with security tech and its operation can be avoided, as can the vast majority of the intangible costs of hacks, and the damage they cause.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Where Web3 services and applications are concerned, which involve token assets that can be stolen, security is even more critical. Here it&#039;s possible to go one step further, by placing the canisters behind the service or application under the full control of a [[DAO]], so that if a developer goes rogue and wishes to hack the system, they are unable to do so because they cannot change its code in an unmoderated manner.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Build on a public network, not on a Big Tech fly trap===&lt;br /&gt;
&lt;br /&gt;
The game-changing advantages of the Internet Computer go far beyond security. In the 1990s, there was an ongoing debate regarding whether the public internet, or walled-garden networks, such as AOL, Compuserve and the [https://www.microsoft.com/en-us/research/publication/on-ramp-prospects-for-the-information-superhighway-dream/ &amp;quot;Information Superhighway&amp;quot; Microsoft imagined], would prevail. Eventually the internet easily won out because it was permissionless, and provided a free market, and nobody wanted to be fed content that was carefully curated for them by mega corporations.&lt;br /&gt;
&lt;br /&gt;
It was a free market because, if Alice and Bob created profitable but competing websites, say, then Alice could not call up the owner of the internet and say &amp;quot;if you slow down the public&#039;s access to Bob&#039;s website, I will give you stock in my company.&amp;quot; The permissionless free market provided the foundations for social impact and freedoms, innovation and massive economic growth.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The internet provided decentralized, permissionless and global network connectivity that now connects almost everyone and everything. The industry now needs to go one step further and do the same for computation using a [[World Computer]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The lives of the nearly 8 billion people on this planet could not be supported without the massive computing power that automates our global society&#039;s infrastructure. For example, it automates markets and supply chains that facilitate farming through the manufacture of fertilizer and tractors, and then the efficient transport of farm produce to supermarkets. Meanwhile, online interactions have created a social and business fabric that is an indispensable part of our personal and work lives.&lt;br /&gt;
&lt;br /&gt;
Given how pivotal society&#039;s information infrastructure has become to human existence, it makes no sense to build it out on the back of a few anointed Big Tech services, such as [[Amazon Web Services]], who will then make us all captive. Moreover, when compared to what the Internet Computer can provide as a blockchain, these platforms have serious disadvantages.&lt;br /&gt;
&lt;br /&gt;
To use traditional IT, developers must combine and integrate a veritable menagerie of components — such as servers or cloud instances, cloud orchestration layers, databases, web servers, memcached, backup systems, content distribution networks, middleware, security tools and much more — creating systems and services that resemble [https://en.wikipedia.org/wiki/Rube_Goldberg_machine Rube Goldberg machines] that are fragile and unnecessarily complex.&lt;br /&gt;
&lt;br /&gt;
Managing this complexity is the source of the biggest cost of all. Of the $5 trillion dollar global IT spend, 80% of that is spent on IT operations, which is comprised from human beings spending much of their time managing complexity. Organizations operating an important but simple website, say, will often hire systems administrators, database administrators and security administrators just to keep it running. This costs crazy amounts of money. These complex systems also cannot be updated quickly, creating opportunity costs.&lt;br /&gt;
&lt;br /&gt;
Meanwhile, when building on traditional IT, the reward is typically to become a captive customer of a [[cloud computing]] service provider and other vendors. Those building using the proprietary and complex stack provided by [[Amazon Web Services]], for example, often eventually find themselves in a similar predicament to those building using the Microsoft software stack twenty years ago, and get stuck there because the re-engineering costs involved with moving are too great. Cloud computing services keep releasing new platform features, and a large part of the reason, is to better trap those lured into building there.&lt;br /&gt;
&lt;br /&gt;
The Internet Computer now provides a clear alternative in the form of a public network. On this open platform, you build using canister smart contract code that is unstoppable and secure without firewalls, and which greatly simplifies the construction and maintenance of systems and services. &lt;br /&gt;
&lt;br /&gt;
===Build on the internet to emit less CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Traditional IT evolved in a time when computers were vastly less powerful, and the internet vastly slower, embedding architectural decisions that are no longer relevant at the root of an evolutionary branch of technology that is increasingly wrong-headed in the modern world.&lt;br /&gt;
&lt;br /&gt;
Even though the Internet Computer is an advanced blockchain, it may come as a surprise that when used as an alternative to traditional IT, it can reduce CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; emissions. That is because its architecture, cryptography and network governance, is able to configure the replication of computation and data within its network (a key source of inefficiency within traditional blockchain networks), in a ways that constrain the order of replication to the minimum needed to provide the strong liveness (unstoppability) and security guarantees expected of a blockchain.&lt;br /&gt;
&lt;br /&gt;
Very deliberately, the Internet Computer&#039;s architecture and math embraces the replication of computation and data, using it to provide a platform for unstoppable and secure tamperproof code, while also scaling certain kinds of computation, such as data queries and web serving. &lt;br /&gt;
&lt;br /&gt;
By contrast, traditional IT is replete with accidental, tacked-on replication. When you create a system or service, very often data is replicated across several database nodes, backup systems, middleware, and more copies are kept handy by the code producing web pages, for example using memcached. Then the web pages and other content served are further replicated by [[Content Distribution Network (CDN)|CDNs (content distribution networks)]].&lt;br /&gt;
&lt;br /&gt;
When systems and services built using traditional IT components are considered as a whole, this accidental hidden replication is often very substantial. However, despite all the hidden replication involved, when systems and services are built using traditional IT, they are not unstoppable or secure and tamperproof.&lt;br /&gt;
&lt;br /&gt;
The Internet Computer challenges deeply held misconceptions about blockchain science. In the popular imagination, it is defined by computationally expensive [https://en.wikipedia.org/wiki/Proof_of_work proof-of-work networks], which Satoshi introduced in his 2008 paper. These sometimes use as much power as a small country, yet can only process a handful of transactions a second.&lt;br /&gt;
&lt;br /&gt;
The Internet Computer flips this narrative. It is a blockchain that can play the role of an end-to-end platform, which provides an alternative to traditional IT that will arguably be more efficient with respect to electricity consumption.&lt;br /&gt;
&lt;br /&gt;
===Web3 and cloud are incompatible===&lt;br /&gt;
&lt;br /&gt;
Today, if you ask much of the public and journalists what Web3 is, they will mostly propose that it is something to do with [[NFT]]s. But those working at the forefront of the field understand it as something much more profound and impactful. Web3 is about replacing today&#039;s Web 2.0 services, which are mostly run by big corporations, with an infrastructure that engages users through the tokenization of assets and participation rights, and by assigning full control over these services to [[DAO]]s (decentralized autonomous organizations), so they can be run by their communities.&lt;br /&gt;
&lt;br /&gt;
In the future, Web3 online services will run rather like open economies. They will be controlled by DAOs, which in turn will be controlled by voting using [[governance tokens]]. These tokens will be held by founders, core developers, investors and, most importantly, the end users of the services themselves. Algorithms will be give them out to users who contribute, perhaps because they are prolific creators of popular content, refer other users to the service, or help with content moderation. Users will be the owners of services, and also part of the team that runs them — which will enable them to scale fast, and make them more viral and sticky.&lt;br /&gt;
&lt;br /&gt;
Entire metaverse world&#039;s will run entirely from the blockchain. For example, one metaverse project being built on the Internet Computer today enables users to create their own 3D island, in the style of Minecraft, which they can share via a URL on their social media profiles. That world is itself an NFT, but they can also import ready-crafted objects into their metaverse islands, such as a castle or art gallery, by acquiring NFTs, then use the space to sell art NFTs. Island owners can create gateways to other islands, as a means to share traffic, and then sell the gateways as NFTs. This only scratches the surface of what is being done: The metaverse is an economy. &lt;br /&gt;
&lt;br /&gt;
Meanwhile, in Web3, everything blends with DeFi. For example, social media can blend with DeFi to become [[SocialFi]]. Open Chat ([https://oc.app oc.app]) is a messaging service that runs entirely from the Internet Computer blockchain, where smart contracts process and store text messages and media messages such as video. But this is no normal messaging service. A user account can also play the role of a crypto wallet, which maintains bitcoin, [[ICP Tokenomics#Uses_of_ICP_token|ICP]] and other tokens that can be sent along with chat messages. On top, it is being integrated by other Web3 developers, and special group chats now provide users with easy ways to vote on DAO governance proposals, among other things.&lt;br /&gt;
&lt;br /&gt;
The question of how security and regulation are handled by these new services is critical. Users do not want to lose their NFTs in a hack, especially if they confer ownership of a valuable and highly trafficked metaverse they created, say, and they also do not want to have their cryptocurrency and other tokens stolen. Furthermore, the developers of such services, do not want to find themselves classified as [https://en.wikipedia.org/wiki/Money_transmitter money transmitters], say, because they were constructed using centralized traditional IT.&lt;br /&gt;
&lt;br /&gt;
Any reasonable analysis shows that the only practical way to solve these problems is to run Web3 services in the mode of protocols, just like blockchains themselves. This can be done by building them exclusively using smart contracts that are then placed under the &#039;&#039;full and exclusive control of community DAOs&#039;&#039;. Once control has been transferred to a community DAO, and the service runs 100% from the blockchain without the use of traditional IT, the developers cannot arbitrarily change the code in an unmoderated way to steal crypto balances. Nor can anyone else steal the crypto balances unless their code is flawed.&lt;br /&gt;
&lt;br /&gt;
Moreover, when a Web3 service truly runs autonomously in cyberspace, under the exclusive control of a community DAO, then its management and ownership is no longer rooted in a jurisdiction and it runs in the manner of a decentralized protocol. There is no centralized entity such as a person, group of developers, or corporation that is responsible for its ongoing operations. This is very different to a Web3 service built using a cloud computing service, or other traditional IT, which roots it in a jurisdiction and directly transfers legal responsibility to those who control and own the cloud account. This responsibility is also transitively transferred to any shadow controllers.&lt;br /&gt;
&lt;br /&gt;
The Internet Computer provides for any Web3 service or application to be built entirely on chain using smart contracts, without need for cloud computing, server computers, or any other traditional IT. Furthermore, services and applications can be placed under the full control of DAOs, either using the built-in [[Service Nervous System]] DAO framework, or third party DAO frameworks.&lt;br /&gt;
&lt;br /&gt;
===Web3 TL;DR===&lt;br /&gt;
&lt;br /&gt;
However you plan to build a Web3 service or application, you need to ditch the cloud and traditional IT. You can either build exclusively on the Internet Computer, or [[Extend_Bitcoin,_Ethereum_and_other_blockchains|combine smart contract code on the Internet Computer with smart contract code on other chains such as Ethereum]].&lt;br /&gt;
&lt;br /&gt;
Today, finally, thanks to years of work by engineers, computers science researchers and cryptographers, &#039;&#039;blockchain is the stack&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[https://internetcomputer.org/developers Get started building systems, applications and services using canister smart contracts running on a real World Computer].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Canister_smart_contract&amp;diff=8441</id>
		<title>Canister smart contract</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Canister_smart_contract&amp;diff=8441"/>
		<updated>2025-06-30T21:37:28Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34210839162004-Canister-Smart-Contracts}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_architecture_overview&amp;diff=8440</id>
		<title>IC architecture overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_architecture_overview&amp;diff=8440"/>
		<updated>2025-06-30T21:37:04Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34206453538964-Blockchain-Protocol}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:IC-protocol-stack.png|500px]]&lt;br /&gt;
&lt;br /&gt;
As illustrated in the above diagram, the Internet Computer Protocol consists of four layers:&lt;br /&gt;
* [[IC execution layer]]&lt;br /&gt;
* [[IC message routing layer]]&lt;br /&gt;
* [[IC consensus layer]] &lt;br /&gt;
* [[IC P2P (peer to peer) layer]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Description of specific features:&lt;br /&gt;
*[[IC Smart Contract Memory]]&lt;br /&gt;
*[[Bitcoin integration]]&lt;br /&gt;
*[[HTTPS outcalls]]&lt;br /&gt;
* [[Subnet splitting]]&lt;br /&gt;
&lt;br /&gt;
Canisters serving the web:&lt;br /&gt;
* [[HTTP asset certification]]&lt;br /&gt;
* [[Boundary Nodes]]&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=DAO&amp;diff=8439</id>
		<title>DAO</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=DAO&amp;diff=8439"/>
		<updated>2025-06-30T21:36:38Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34574082263700-Tokenomics-Governance}}&lt;br /&gt;
&lt;br /&gt;
A Decentralized Autonomous Organization, or DAO for short, is a system that allows many parties to jointly control an entity.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;what-is-a-dao&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== What is a DAO? ==&lt;br /&gt;
Let’s first clarify what &#039;&#039;decentralized&#039;&#039; means in this context. First, an application can run on a &#039;&#039;decentralized platform&#039;&#039;. This means that the platform itself is controlled by many different parties and, in particular, that even if some of these parties fail or turn malicious, the application will still keep running successfully. The IC is such a platform as it is run by many nodes that are owned by independent node providers. Therefore, applications that run on the IC are called &#039;&#039;decentralized applications&#039;&#039; or &#039;&#039;dapps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A second kind of decentralized denotes who is in control of changing a dapp, or a smart contract more generally. In general, dapps running on the IC or smart contracts on other decentralized platforms can still be controlled by a single, central entity and thus still be under centralized control. As motivated below, it is often beneficial if a dapp is also under &#039;&#039;decentralized control&#039;&#039;. This means that no single party can decide how the dapp is evolved. Instead, the dapp can only be changed according to decisions that many parties jointly make. This decentralized control of a dapp is what a DAO achieves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;motivation-why-a-dao&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Motivation: why a DAO? ==&lt;br /&gt;
&lt;br /&gt;
The following discusses the main motivations for DAOs from the point of view of two main actors on the IC: the dapp developers, who build dapps on the IC, and the end-users, who interact with and invest in dapps.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;dapp-users&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Dapp users ===&lt;br /&gt;
&lt;br /&gt;
Dapps on the IC are realized as a set of canister smart contracts. Canisters define a &#039;&#039;controller&#039;&#039; specifying which principals can modify them. Most dapp canisters are either controlled by some developers or have no controller at all. Both situations have downsides  for a dapp’s users. In the case where a dapp is controlled by a centralized group of developers, users of the dapp must trust these developers not to stop the application and not to modify the application in an undesirable way, e.g., that favors the developers. In the case where the canister has no controller, it cannot be upgraded at all. This not only prevents evolving the dapp regarding new requirements but might also be a problem when it is necessary to fix security bugs.&lt;br /&gt;
&lt;br /&gt;
DAOs provide a third option, namely to hand over the control over a dapp to a community that can jointly decide how to evolve a dapp in an open governance system, i.e., to &#039;&#039;decentralize a dapp’s control&#039;&#039;. This protects users as the control is now in the hand of a community rather than in the hand of a few parties. Moreover, dapp users can join the open governance themselves and thereby directly impact how the dapp is evolved.&lt;br /&gt;
&lt;br /&gt;
===limitations of DAO concept===&lt;br /&gt;
As the ICP ecosystem scales, many new dapps are appearing which need to be integrated with each other. Only focusing on the functions and features of a single dapp will not make ICP successful. Therefore, the overall architecture of all ICP dapps need to be considered and smart integrations need to be designed ([https://nuance.xyz/manitas/11754-434go-diaaa-aaaaf-qakwq-cai/a-true-world-computer-or-a-couple-of-isolates-apps-hosted-on-a-blockchain- linked research paper]).  &lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_staking_options&amp;diff=8438</id>
		<title>ICP staking options</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_staking_options&amp;diff=8438"/>
		<updated>2025-06-30T21:36:10Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084120668692-Neurons}}&lt;br /&gt;
&lt;br /&gt;
Depending on how you custody your ICP, you have different staking options.&lt;br /&gt;
&lt;br /&gt;
== 3rd Party Solutions ==&lt;br /&gt;
There are currently no 3rd party staking solution.&lt;br /&gt;
&lt;br /&gt;
== Self Custody==&lt;br /&gt;
&lt;br /&gt;
=== NNS Frontend dapp ===&lt;br /&gt;
If you custody with NNS frontend dapp, see [[ICP staking with NNS frontend dapp]].&lt;br /&gt;
&lt;br /&gt;
=== Ledger Nano ===&lt;br /&gt;
If you custody with Ledger Nano, see [https://medium.com/dfinity/integrating-ledger-nano-with-the-nns-front-end-dapp-user-manual-9c5600925e16 Integrating Ledger Nano With the NNS Front-End Dapp: User Manual]&lt;br /&gt;
&lt;br /&gt;
=== Air-gapped machine===&lt;br /&gt;
If you custody with Ledger Nano, see [[ICP staking with seed phrase and air-gapped computer]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Managing ICP holdings]]&lt;br /&gt;
* [[ICP custody options]]&lt;br /&gt;
* [[ICP custody with seed phrase and air-gapped machine]]&lt;br /&gt;
* [[ICP staking with NNS frontend dapp]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Governance_of_the_Internet_Computer&amp;diff=8437</id>
		<title>Governance of the Internet Computer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Governance_of_the_Internet_Computer&amp;diff=8437"/>
		<updated>2025-06-30T21:35:47Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/33692645961236-Overview}}&lt;br /&gt;
&lt;br /&gt;
The Internet Computer blockchain is governed by the [[Network Nervous System]] (NNS) &amp;lt;ref&amp;gt;https://medium.com/dfinity/the-network-nervous-system-governing-the-internet-computer-1d176605d66a&amp;lt;/ref&amp;gt;. The NNS is an algorithmic governance system that oversees the network and the token economics that make it possible to build DeFi dapps, open internet services and enterprise systems.&lt;br /&gt;
&lt;br /&gt;
Holders of the Internet Computer’s [[ICP Tokenomics | ICP utility tokens]] can lock their tokens in [[Neurons 101 | neurons]] to participate in governance and contribute to decision-making, such as voting to determine whether or not a new collection of nodes (also called a subnet) should be added to the network. &lt;br /&gt;
&lt;br /&gt;
=== Why the Internet Computer needs a Network Nervous System&amp;lt;ref&amp;gt;https://medium.com/dfinity/the-network-nervous-system-governing-the-internet-computer-1d176605d66a&amp;lt;/ref&amp;gt; ===&lt;br /&gt;
The Internet Computer is a distributed protocol run by a [[Sovereign Network | network of node machines]], which are hosted in different data centers. The nodes communicate with one another over the internet to achieve a [[Proof of Useful Work | consensus]] on what the Internet Computer’s state should be. A collection of nodes engaging in consensus is called a subnet. On top of this underlying communication and consensus protocol, the Internet Computer hosts [[Canister Smart Contracts]] called &#039;&#039;canisters&#039;&#039;, which are stateful programs that can also communicate with each other. The state of all of the canisters has to be replicated across all of the nodes. Therefore, to allow the Internet Computer to scale indefinitely, the network is made up of not just one subnet, but multiple subnets.&lt;br /&gt;
&lt;br /&gt;
Different [[Subnet_blockchain | subnets]] can communicate with one another, enabling [[Canister Smart Contracts]] that are hosted on different subnets to also communicate with each other. For the Internet Computer to scale on-demand, the network must be able to add new subnets over time to increase compute capacity. Moreover, the robustness of the subnets can be improved by adding new nodes to them over time. Eventually, the Internet Computer will run millions of nodes at scale. This means that there needs to be a mechanism by which the nodes and subnets are organized, tracked, and managed. For example, decisions must be made about when subnets and nodes should be added or removed. In addition, the Internet Computer was launched with an initial feature set, which evolves over time. Therefore, the Internet Computer needs to be able to make decisions on how to evolve the protocol in a distributed manner.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[ICP Tokenomics]]&lt;br /&gt;
* [[Tutorials for acquiring, managing, and staking ICP]]&lt;br /&gt;
* [[Staking, voting and rewards]]&lt;br /&gt;
* [[Network Nervous System]]&lt;br /&gt;
* [[Total supply, circulating supply, and staked ICP]]&lt;br /&gt;
* [[NNS neuron operations related to maturity]]&lt;br /&gt;
* [[Roll-over of NNS voting rewards]]&lt;br /&gt;
* [[Maturity]]&lt;br /&gt;
* [[Replica Upgrades]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Proof_of_Useful_Work&amp;diff=8436</id>
		<title>Proof of Useful Work</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Proof_of_Useful_Work&amp;diff=8436"/>
		<updated>2025-06-30T21:33:02Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34207558615956-Consensus}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
&lt;br /&gt;
When Satoshi designed Bitcoin, he wrestled with two primary problems. Firstly, he needed to find a way to prevent what is known as a &amp;quot;Sybil attack&amp;quot;, which would allow an adversary (i.e. the bad guys) to add additional nodes to the decentralized network, until they could take control. Secondly, he needed to find a way to bring the network to consensus regarding changes to the ledger (i.e. what transactions were processed, and in which order).&lt;br /&gt;
&lt;br /&gt;
His solution was proof-of-work (now sometimes shortened to PoW). Although often described as a decentralized consensus protocol, it is both a decentralized Sybil-resistance scheme, and a consensus protocol. In order to participate in &amp;quot;mining&amp;quot; bitcoin, it is necessary for miners to run special hardware that creates large numbers of cryptographic hashes of blocks they wish to propose, until a &amp;quot;winning&amp;quot; hash is found, whereupon they can submit the block to the network. In practice, the relative number of blocks that each miner produces, and the rewards they earn, is proportional to the amount of hashes that their hardware can perform.&lt;br /&gt;
&lt;br /&gt;
Proof-of-work solves the Sybil problem because vast volumes of hashes have to be calculated to have a chance of producing a block, which involves the dedication of expensive mining hardware, and copious amounts of electricity. As participation in the Bitcoin network grew, it quickly became too expensive for any adversary to acquire and run sufficient hashing hardware that they could perform a large enough share of the network&#039;s hashing that they might gain control (for example to double-spend). By fortune, the Sybil-resistance scheme also helped solved consensus, since hashes are random numbers, and winning hashes are discovered randomly only through brute force, and thus a random miner is assigned the job of creating each block.&lt;br /&gt;
&lt;br /&gt;
A great advantage of proof-of-work is that it results in a chain that is produced by relatively stable, dedicated hardware, creating a secure network. Essentially, the Bitcoin network that produces blocks can be thought of as a giant decentralized hashing factory. However, the downside is that the scheme essentially works as a hashing competition, in which the total money miners spend on hashing hardware, and the large amounts of electricity necessary to keep it running, tends towards the value of the block rewards that Bitcoin provides. Moreover, the scheme does not reach consensus quickly.&lt;br /&gt;
&lt;br /&gt;
As a result of the expense, the blockchain industry worked on proof-of-stake (often shortened to PoS) schemes, in which individual network nodes would be joined to the network by staking (&amp;quot;locking&amp;quot;) some amount of cryptocurrency, then producing blocks, and earning rewards, in proportion to the amount of cryptocurrency that they have staked. This replaced the expense of the dedicated hashing hardware, and the electricity used to run it, with the cost of capital involved in staking. Ethereum 2.0 migrated the network from a PoW architecture to a PoS architecture. Not only did this allow the network to run much faster, because it could use alternative consensus schemes, but it prevented the environmentally-costly expenditure of electricity to power the hashing hardware.&lt;br /&gt;
&lt;br /&gt;
However, PoS has numerous challenges, which are becoming increasingly apparent. Firstly, once the need for dedicated hardware was removed, a block-producing network node (or &amp;quot;client&amp;quot;) could simply be spun up anywhere, including the corporate cloud, and activated just by staking some cryptocurrency. As a result, the vast majority of nodes on PoS networks, run in the cloud. The dangers of running a blockchain in the cloud were recently brought into sharp relief – the Hetzner cloud, in Europe, [https://decrypt.co/113429/is-solana-decentralized-cloud-provider-hetzner-ban-raises-questions recently suddenly banned Solana nodes], immediately causing 40% of its network to disappear in the blink of an eye. A PoS network running in the cloud is very different to a sovereign network, and the potential exists for cloud providers to interfere with nodes, as well as to close them down.&lt;br /&gt;
&lt;br /&gt;
Another challenge with PoS is that cryptocurrency, by its nature, is highly liquid, raising the possibility of swift changes in network architecture and the distribution of power, which is something an attacker can potentially exploit. For example, clever manipulations of DeFi, or the catastrophic hack of an exchange, might provide an attacker with sufficient stake that they can break the network – allowing them to profit after suitably hedging their staked cryptocurrency. PoS networks often provide frameworks that make it easy to spin up new nodes on the cloud in an instant, allowing a suitably financed adversary to launch an attack by running a script. &lt;br /&gt;
&lt;br /&gt;
==Proof of useful work==&lt;br /&gt;
&lt;br /&gt;
Proof-of-useful-work (PoUW) is the Internet Computer&#039;s answer to these kinds of considerations, and is more complex than the foregoing schemes. It involves a blockchain being produced by dedicated hardware called &amp;quot;node machines&amp;quot; that are of very similar, standardized specification. On the Internet Computer, these run highly sophisticated consensus protocols that lean into the power of advanced cryptography, often referred to as Chain Key Crypto. PoUW is concerned with membership in the network.&lt;br /&gt;
&lt;br /&gt;
Naturally, as per PoW, the purchase, hosting and operation of node machine hardware acts as the stake. However, these machines don&#039;t do hashing, and simply produce and process blocks of transactions that represent smart contract computations. The reason that combined node machines must be built to the same standardized specification, is that rather than compete to perform hashing, they must try not to &amp;quot;statistically deviate&amp;quot; by producing more or less blocks. In essence, rather than trying to perform more computation, they try to perform the same amount of computation, and can be punished for deviating from the group.&lt;br /&gt;
&lt;br /&gt;
A key ingredient of the scheme is the [[Network Nervous System]] (or NNS), a sophisticated permissionless DAO that is integrated with the Internet Computer&#039;s protocols. This fully controls the network, configuring it, and upgrading the software run by node machines. Amoung its responsibilities, it combines node machines to create &amp;quot;subnet blockchains,&amp;quot; which themselves are combined into a single blockchain using Chain Key Crypto. This achieves two important things. Firstly, expense aside, it is not possible for an adversary simply to add nodes to a subnet blockchain, since the NNS carefully selects nodes by looking at the node provider, the data center the node is installed within, and its geography and jurisdiction, in a scheme of &amp;quot;deterministic decentralization.&amp;quot; Secondly, the NNS can remove (or &amp;quot;slash&amp;quot;) nodes that statistically deviate.&lt;br /&gt;
&lt;br /&gt;
By applying deterministic decentralization, the NNS creates a highly secure scheme in which the Internet Computer runs on a sovereign network of dedicated hardware, formed from node machines, which machinery can be tightly held to correct behavior in order to continue its participation in block production (through which its owners, the node providers, earn rewards). In PoUW, the repetitive hashing work of PoW, whose purpose relates primarily to network operation, has been replaced by useful smart contract computation. Since this is work that must be performed anyway, a supremely efficient network is produced. &lt;br /&gt;
&lt;br /&gt;
==Useful historical resources==&lt;br /&gt;
&lt;br /&gt;
Project founder Dominic Williams was an early pioneer in the study of crypto Sybil resistance and consensus. Here in May 2015 [https://www.youtube.com/watch?v=dfGDhDR_3Gc he gives a talk discussing Sybil resistance and consensus at San Francisco Bitcoin Devs], in which he discusses the &amp;quot;3 E&#039;s of Sybil Resistance.&amp;quot; Other interesting historical material that provides insights into the development of PoUW, include a [https://www.youtube.com/watch?v=1KaQsrqC94s panel on scalability with Vitalik Buterin and Gavin Wood], and a talk [https://www.youtube.com/watch?v=3iSw03pJ-gk introducing consensus theory], at Ethereum&#039;s DEVCON1 later that year.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Deterministic Decentralization]]&lt;br /&gt;
* [[Sovereign Network]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Deterministic_Decentralization&amp;diff=8435</id>
		<title>Deterministic Decentralization</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Deterministic_Decentralization&amp;diff=8435"/>
		<updated>2025-06-30T21:32:41Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34207558615956-Consensus}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Deterministic Decentralization is the idea that ICP should measure and maximize the the diversity and decentralization of each subnet, rather than &#039;&#039;optimistically&#039;&#039; hope for decentralization by allowing any node to join network. Deterministic Decentralization tries to maximize the decentralization of every sub-layer of the infrastructure layer. This means, for example, maximizing the following:&lt;br /&gt;
&lt;br /&gt;
# Number of unique node providers&lt;br /&gt;
# Number of unique data centers&lt;br /&gt;
# Number of unique jurisdictions&lt;br /&gt;
&lt;br /&gt;
==Design Intent==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
* An empirical pattern from studying other blockchains: infrastructure layers tend towards high-concentration (2-4 entities) controlling 51% of the infrastructure and 1-2 jurisdictions (e.g. US, China) controlling 51% of the infrastructure. In practice, permissionless (even without a DAO) infrastructure layers tend to a concentration where the “anyone can run a node from home” tends to be a figleaf for concentration of a few big players.&lt;br /&gt;
&lt;br /&gt;
* Networks like BTC or ETH have protocol-level limitations where the protocol will have the same throughput of transactions whether it has 10 nodes or 10,000 nodes. These do not scale by adding more nodes.&lt;br /&gt;
&lt;br /&gt;
* Many networks have inconsistent node uptime/availability as miners switch off/on their nodes due to unpredictable crypto markets, sometimes making nodes unprofitable to run.&lt;br /&gt;
&lt;br /&gt;
* A lot of the node’s computation in other blockchains is used up in puzzles (e.g. Proof of Work) rather than useful computation.&lt;br /&gt;
&lt;br /&gt;
===ICP is designed to have the following properties===&lt;br /&gt;
&lt;br /&gt;
* The IC&#039;s method of &amp;quot;manicured&amp;quot; subnets, even though less decentralized in theory, actually gives you better decentralization in practice.&lt;br /&gt;
&lt;br /&gt;
* ICP compute capacity grows by adding more nodes&lt;br /&gt;
&lt;br /&gt;
* To balance ICP minting rate and developer demand for compute, the NNS DAO decides how many more nodes to add &lt;br /&gt;
&lt;br /&gt;
* To maximize decentralization, NNS DAO measures and maximizes decentralization, rather than leave it to chance &lt;br /&gt;
&lt;br /&gt;
*  To incentivize ICP to have maximum availability, the node reward has predictable rewards for each node&lt;br /&gt;
&lt;br /&gt;
* To incentivize general availability, the NNS DAO rewards nodes for being part of the system and removes them if they start to deviate consistently.&lt;br /&gt;
&lt;br /&gt;
* To maximize reliability and health of the network, NNS DAO can remove nodes that consistently deviate (maybe they are faulty or are malicious).&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
* [[Sovereign Network]]&lt;br /&gt;
* [[Decentralization in ICP: Infrastructure Governance]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Sovereign_Network&amp;diff=8434</id>
		<title>Sovereign Network</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Sovereign_Network&amp;diff=8434"/>
		<updated>2025-06-30T21:32:21Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34206453538964-Blockchain-Protocol}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The Internet Computer blockchain network is hosted by special [[Glossary#node|node machines]], which are hardware devices that are dedicated to the task (thus creating a sovereign network). This is conceptually similar to how the internet is hosted by network routing devices.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
==Design Intent==&lt;br /&gt;
&lt;br /&gt;
Traditional blockchains are different. Their network nodes are created using simple software, which interacts with other nodes and maintains a copy of blockchain state. Today, software programs are very easy to spin up on [[cloud computing]] &amp;quot;instances&amp;quot; using services such as [[Amazon Web Services]]. A consequence has been that the majority of nodes in traditional blockchains are cloud computing instances. Because these can be spun up in an instant, the investment required to create or destroy a node is minimal (notwithstanding any cryptocurrency stake that might be required to add a node to the network).&lt;br /&gt;
&lt;br /&gt;
A grave risk with these kinds of architectures is that control over the blockchain network is handed to a small number of giant corporations. These corporations might decide they must switch off the nodes, owing to changes in regulation, or competitive threats, or malicious insiders might use their access to the physical cloud infrastructure to steal keys, or otherwise disrupt the networks.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;These issues do not exist with the Internet Computer, because it runs on a sovereign network.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Every node in the Internet Computer network is a dedicated physical device, called a [[Glossary#node | node machine]], which is run by an independent [[Node providers|node provider]], typically from rack space in an independent [[data center]]. The nodes cannot therefore be switched off or tampered with by a small number of corporate cloud computing service providers.&lt;br /&gt;
&lt;br /&gt;
While this is an important advantage, there are other technical reasons that special [[Glossary#node | node machine]]s are required to participate in hosting the Internet Computer network. The node machines are built to standardized public hardware specifications. This means that when the network is under load, they do not fall behind other nodes inside the same [[subnet blockchain]], which statistical deviation the network&#039;s decentralized governance DAO might notice, and sanction them for.&lt;br /&gt;
&lt;br /&gt;
==Joining The Network== &lt;br /&gt;
&lt;br /&gt;
===Decentralization===&lt;br /&gt;
The blockchain uses [[Deterministic Decentralization | deterministic decentralization]] to maximize the [[Decentralization in ICP: Infrastructure Governance | infrastructure decentralization]] of the network.&lt;br /&gt;
&lt;br /&gt;
===Node Providers===&lt;br /&gt;
[[Node providers]] invest in and operate the node hardware which powers the ICP network. Running these nodes in data centers provides the high performance and the cost-effectiveness of the Internet Computer. Every node provider is allowed a limited amount of nodes.&lt;br /&gt;
* [[Node Provider Onboarding]]&lt;br /&gt;
* [[Node Provider Remuneration]]&lt;br /&gt;
* [[Node Provider Self-declaration]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Proof of Useful Work]]&lt;br /&gt;
* [[Deterministic Decentralization]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Roll-over_of_NNS_voting_rewards&amp;diff=8433</id>
		<title>Roll-over of NNS voting rewards</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Roll-over_of_NNS_voting_rewards&amp;diff=8433"/>
		<updated>2025-06-30T21:31:50Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34142993417108-Voting-Rewards}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Background &amp;amp; goal==&lt;br /&gt;
* The automation of exchange rate proposals is planned to be released in May ‘23.&lt;br /&gt;
* Post this release, on some days (in particular on weekends) no NNS proposals might be submitted. Previously this was not possible as exchange rate proposals were submitted every 10 minutes. &lt;br /&gt;
* As a consequence, there might be days during which no NNS proposals will settle. Since the distribution of NNS rewards is linked to the ballots of settled proposals, on those days no rewards are distributed. Rather, rewards will roll over to the following day. &lt;br /&gt;
* On this page the roll-over mechanism is explained.&lt;br /&gt;
&lt;br /&gt;
==Reward roll-over mechanism== &lt;br /&gt;
* For any given day t_0 the NNS determines the total amount of available rewards R(t_0) for that day as a function of total supply and the voting reward function. For further background information on voting rewards see [https://internetcomputer.org/docs/current/tokenomics/nns/nns-staking-voting-rewards/#voting-rewards here]. &lt;br /&gt;
* Now assume that on day t_0, no proposal settled and thus no rewards could be distributed. &lt;br /&gt;
* As a consequence, the NNS will roll over the rewards to the following day t_1. This means that on day t_1 a total amount of R(t_0) + R(t_1) is available for distribution. &lt;br /&gt;
* If at least one proposal settled on day t_1 then this triggers a reward distribution. Otherwise rewards will again roll over to the following day and so on. &lt;br /&gt;
&lt;br /&gt;
==How this will be displayed in the NNS dapp==&lt;br /&gt;
The NNS dapp will provide users information about the last time voting rewards were distributed, as you can see from the below screenshot.&lt;br /&gt;
&lt;br /&gt;
[[File:NNS dapp roll-over.png|800px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the indicated date is more than one day in the past, then NNS rewards are currently rolling over.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=NNS_neuron_operations_related_to_maturity&amp;diff=8432</id>
		<title>NNS neuron operations related to maturity</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=NNS_neuron_operations_related_to_maturity&amp;diff=8432"/>
		<updated>2025-06-30T21:31:14Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34140499557908-Neuron-Attributes}}&lt;br /&gt;
&lt;br /&gt;
== Background &amp;amp; goal ==&lt;br /&gt;
&lt;br /&gt;
* Maturity is an attribute of a neuron; it is not a tradable asset. Neurons receive voting rewards in the form of maturity.&lt;br /&gt;
* Whenever you burn maturity to create newly minted ICP, [https://wiki.internetcomputer.org/wiki/Maturity_modulation maturity modulation] is applied.&lt;br /&gt;
* Maturity modulation introduces uncertainty in the conversion process from maturity to ICP, depending on the ICP price trend.&lt;br /&gt;
* This article explains how the maturity modulation interacts with neuron operations related to maturity, in particular spawn maturity and stake maturity.&lt;br /&gt;
* For further background on neurons and the NNS, please see [https://medium.com/dfinity/the-network-nervous-system-governing-the-internet-computer-1d176605d66a#:~:text=The%20Network%20Nervous%20System%2C%20or,how%20to%20update%20this%20information. here].&lt;br /&gt;
&lt;br /&gt;
== Spawning maturity ==&lt;br /&gt;
&lt;br /&gt;
* If a user triggers spawn maturity, a new neuron will be immediately spawned; however, this newly spawned neuron will have no ICP at start, only maturity.&lt;br /&gt;
* Spawned neurons have a dissolve delay of 7 days and are dissolving.&lt;br /&gt;
* After 7 days when the neuron is dissolved, the amount of ICP, determined by the maturity modulation function, will be minted and be available to the user.&lt;br /&gt;
&lt;br /&gt;
== Staking maturity ==&lt;br /&gt;
&lt;br /&gt;
* A user can stake maturity which locks the maturity until the neuron is dissolved. Once a neuron is dissolved, staked maturity is unlocked and becomes normal maturity.  &lt;br /&gt;
* Staked maturity contributes to the voting power of the neuron as determined by Voting Power = (ICP staked + maturity staked) x Dissolve Delay Bonus x Age Bonus&lt;br /&gt;
* No ICP is (or can be) produced from staked maturity until the neuron is dissolved and the maturity is spawned (as described in the section above), at which point it is subject to maturity modulation.&lt;br /&gt;
&lt;br /&gt;
== Auto-staking of maturity ==&lt;br /&gt;
&lt;br /&gt;
* Daily voting rewards may be received either as staked maturity or maturity.&lt;br /&gt;
* This choice can be changed for future rewards at any time.&lt;br /&gt;
* If rewards are received automatically as staked maturity, voting rewards accumulate over time as voting power of the neuron increases with every reward event.&lt;br /&gt;
&lt;br /&gt;
== Outlook on maturity operations ==&lt;br /&gt;
* Merge maturity (which adds maturity of a neuron to the ICP stake) is deprecated in the NNS II UX, NNS hardware wallet and NNS quill. &lt;br /&gt;
* Spawn maturity is planned to be replaced by a new operation called disburse maturity (this is already implemented for the SNS). &lt;br /&gt;
** This operation begins a 7 day clock that completes with a modulation of the amount of minted ICP to be received.&lt;br /&gt;
** This final amount of newly minted ICP is then transferred into the account of a neuron holder.&lt;br /&gt;
* The community has requested to enhance the proposed disburse maturity functionality, to support automatic re-staking of the newly minted ICP. This would provide a similar functionality to the previous merge function , but with the 7 day delay &amp;amp; modulation applied. DFINITY is looking into how best to support this.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Total_supply,_circulating_supply,_and_staked_ICP&amp;diff=8431</id>
		<title>Total supply, circulating supply, and staked ICP</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Total_supply,_circulating_supply,_and_staked_ICP&amp;diff=8431"/>
		<updated>2025-06-30T21:30:11Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34090810571284-Tokenomics}}&lt;br /&gt;
&lt;br /&gt;
For a crypto community to understand the [[Governance of the Internet Computer | governance]] and [[ICP Tokenomics | tokenomics]] of ICP, understanding the supply of ICP is important.&lt;br /&gt;
&lt;br /&gt;
==Definitions==&lt;br /&gt;
&lt;br /&gt;
===Total supply===&lt;br /&gt;
&lt;br /&gt;
Total supply is the sum of all tokens currently in the system (whether they are locked/staked or not). &lt;br /&gt;
&lt;br /&gt;
The total supply changes over time due to inflation and deflation. Its current value can be seen on the [https://dashboard.internetcomputer.org/circulation IC Circulation page] of the IC dashboard.&lt;br /&gt;
&lt;br /&gt;
===Circulating supply===&lt;br /&gt;
&lt;br /&gt;
The circulating supply is all tokens except liquid (non-staked) tokens owned by the DFINITY Foundation.  The circulating supply definition was updated to its current definition on 18APR23 through an approved vote by the NNS on [https://dashboard.internetcomputer.org/proposal/117360 proposal 117360.]&lt;br /&gt;
&lt;br /&gt;
The current circulating supply can be seen on the [https://dashboard.internetcomputer.org/circulation IC Circulation page] of the IC dashboard.&lt;br /&gt;
&lt;br /&gt;
===Staked ICP===&lt;br /&gt;
&lt;br /&gt;
Staked ICP supply is the sum of all the tokens that are locked or dissolving in neurons at any given time that are earning rewards. At this time, there is a minimum lockup period of 6 months to accrue voting rewards. &lt;br /&gt;
&lt;br /&gt;
The total amount of staked ICP changes over time. Its current value can be seen on the [https://dashboard.internetcomputer.org/neurons Neurons page] of the IC dashboard.&lt;br /&gt;
&lt;br /&gt;
==Numbers==&lt;br /&gt;
&lt;br /&gt;
===At network Genesis===&lt;br /&gt;
&lt;br /&gt;
May 10, 2021:&lt;br /&gt;
* Total supply: 469 million&lt;br /&gt;
* Circulating supply: 123 million&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
As of March 17th, 2025:&lt;br /&gt;
* Total supply: 530.6 million ICP&lt;br /&gt;
* Circulating supply: 481.7 million (90.8% of total supply)&lt;br /&gt;
* Staked ICP: 234.1 million (44.1% of total supply).&lt;br /&gt;
** 87.2% of ICP staked is staked with more than a 1-year dissolve delay&lt;br /&gt;
** 61.5% of ICP staked is staked for an 8-year dissolve&lt;br /&gt;
** One can see the breakdown of staked ICP by dissolve delays in [https://dashboard.internetcomputer.org/neurons IC neuron dashboard].&lt;br /&gt;
&lt;br /&gt;
* As outlined in the section above Circulating supply represents ICP that was ever liquid. A subset of the circulating supply is locked in neurons as staked ICP.&lt;br /&gt;
&lt;br /&gt;
==Inflationary mechanisms==&lt;br /&gt;
&lt;br /&gt;
The NNS mints ICP tokens for two reasons:&lt;br /&gt;
* For voting rewards (Governance).&lt;br /&gt;
* For node provider rewards.&lt;br /&gt;
&lt;br /&gt;
The amount of ICP minted since Genesis can be seen in the [https://dashboard.internetcomputer.org/circulation &amp;quot;Total Rewards&amp;quot; chart] on the IC dashboard.&lt;br /&gt;
&lt;br /&gt;
===Paying staking rewards===&lt;br /&gt;
&lt;br /&gt;
Voting rewards are generated by minting ICP, although this minting only happens at the moment rewards are spawned, maturity is merged, or the neuron is disbursed.&lt;br /&gt;
&lt;br /&gt;
The voting rewards rate schedule is designed with the goal that 90% of the token supply is staked in neurons. With this goal in mind, in the first year, the NNS allocates 10% of the total supply to generate voting rewards. Note the term &amp;quot;allocates&amp;quot; rather than &amp;quot;mints&amp;quot;, because rewards are not minted (increasing the total supply) until they are spawned, merged, or the neuron is disbursed. &lt;br /&gt;
&lt;br /&gt;
As the network becomes more stable over time, this allocation rate drops quadratically until it reaches 5% by year 8. See chart below from the [https://dashboard.internetcomputer.org/circulation IC Circulation page] on the IC dashboard.:&lt;br /&gt;
&lt;br /&gt;
[[File:NNS minting % by year.png|800px|frameless]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Like all parameters in the NNS, this rate schedule can be changed via NNS proposals.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See more in [[Staking, voting and rewards]].&lt;br /&gt;
&lt;br /&gt;
===Node provider rewards===&lt;br /&gt;
&lt;br /&gt;
Node providers are rewarded for running the node machines that power the Internet Computer.&lt;br /&gt;
&lt;br /&gt;
==Deflationary mechanisms==&lt;br /&gt;
&lt;br /&gt;
The NNS burns ICP tokens for three reasons:&lt;br /&gt;
&lt;br /&gt;
* To mint cycles, used to pay for compute and storage.&lt;br /&gt;
* For transaction fees.&lt;br /&gt;
* For failed NNS proposal fees.&lt;br /&gt;
&lt;br /&gt;
The amount of ICP burned since Genesis can be seen in the [https://dashboard.internetcomputer.org/circulation &amp;quot;Total ICP Burned&amp;quot; chart] on the IC dashboard.&lt;br /&gt;
&lt;br /&gt;
===Paying for compute and storage===&lt;br /&gt;
&lt;br /&gt;
Dapp and smart contract developers pay computation and storage costs with cycles. Cycles are acquired from the NNS by converting ICP to cycles, which burns the converted ICP.&lt;br /&gt;
&lt;br /&gt;
The cycles costs for IC computation and storage can be seen at [https://smartcontracts.org/docs/developers-guide/computation-and-storage-costs.html Computation and Storage Costs].&lt;br /&gt;
&lt;br /&gt;
===Transaction fees===&lt;br /&gt;
&lt;br /&gt;
Transferring ICP across accounts incurs a transaction fee of 0.0001 ICP, which is burned.&lt;br /&gt;
&lt;br /&gt;
===Failed NNS proposals===&lt;br /&gt;
&lt;br /&gt;
It costs 25 ICP to submit a proposal. If the proposal passes, the 25 ICP is returned to the proposer. If the proposal is rejected, the 25 ICP is burned. Note that this only happens at disbursement or merging of neurons, so accumulated failed proposal fees can persist for a while before finally contributing to deflation.&lt;br /&gt;
&lt;br /&gt;
==Historical factors affecting circulating supply==&lt;br /&gt;
&lt;br /&gt;
The Internet Computer blockchain is a result of several years of unyielding R&amp;amp;D. By Genesis, the DFINITY foundation, a major contributor to the Internet Computer was over 200 full-time members. Over the past several years the foundation raised financing in three main rounds and also allocated ICP tokens to the community in the form of an airdrop event.&lt;br /&gt;
&lt;br /&gt;
For a breakdown of the different rounds and vesting schedules, see Messari&#039;s report [https://messari.io/article/an-introduction-to-dfinity-and-the-internet-computer?referrer=asset:internet-computer &amp;quot;Introduction to ICP&amp;quot;]. The unlocking of neurons has been the &#039;&#039;&#039;largest contributing factor&#039;&#039;&#039; to circulating supply since Genesis, so it&#039;s important to understand the context. &lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Seed Round, Feb-2017 (Public ICO):&#039;&#039;&#039; This round was advertised by a tweet and open to the public by downloading a web extension. DFINITY raised CHF3.9 million (US$3.9 million) from 370 participants, at a valuation of $16 million, or a price of $0.03 per token. It held a portion of these funds in ETH and BTC during the 2017 crypto bull run. Seed round participants received all of their tokens at genesis but are staked inside 49 neurons. Each neuron has a different dissolve delay counting from 0 to 48 months. So this is practically equivalent to a 48-month &amp;quot;vesting schedule&amp;quot; see [https://medium.com/dfinity/how-to-access-seed-and-airdrop-icp-tokens-and-participate-in-the-internet-computer-network-e6cd663a0c3c How to Access ‘Seed’ and ‘Airdrop’ ICP Tokens and Participate in the Internet Computer Network].&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Strategic Round, Jan-2018:&#039;&#039;&#039; DFINITY raised $20.54 million for 7.00% of the initial supply (the number has been revised from the previously cited 6.84%). This allocation vests monthly over three years starting from mainnet launch (May 2021). Participants include Polychain Capital, Andreessen Horowitz, CoinFund, Multicoin Capital, and Greycroft Partners. This round marks the first token a16z invested in. Polychain and DFINITY later collaborated to create the &amp;quot;DFINITY Ecosystem Venture Fund&amp;quot; (later renamed [https://dfinity.org/ecosystem/fund/ &amp;quot;Beacon Fund&amp;quot;]) of an undisclosed size. The goal is to fund new projects that would grow the IC&#039;s application ecosystem. The media reported that DFINITY raised a much larger amount of $61 million, some of which related to funds committed to projects building on the Internet Computer. &lt;br /&gt;
&lt;br /&gt;
3. &#039;&#039;&#039;Presale, Aug-2018:&#039;&#039;&#039; 110 participants contributed $97 million for 4.96% of the initial supply, sold at 4 CHF (around $4 at the time) per ICP token. This number has been revised from 4.75% previously reported. This allocation came with a monthly vesting schedule of one year from mainnet launch. Vesting began one month after the initial token distribution event on May 10, 2021. Participants in this round include Andreessen Horowitz, Polychain Capital, SV Angel, Aspect Ventures, Electric Capital, ZeroEx, Scalar Capital, and Multicoin Capital.&lt;br /&gt;
&lt;br /&gt;
4. &#039;&#039;&#039;Airdrop, May-2018:&#039;&#039;&#039; $35 million worth of ICP tokens (formerly DFN), or 0.80% of the initial supply, was airdropped to early supporters by being part of their mailing list, forums, and community. At this time, valuations reached $1.89 billion. Airdrop participants received the IOU version of their ICP tokens in September 2020. This allocation came with a monthly distribution schedule of one year from mainnet launch, which began on May 10, 2021.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ultimately, the NNS is controlled by the community so it can vote to change any of the parameters. The parameters and mechanisms described are the current ones.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ICP token has a Total Supply of 530.6MM, Circulating Supply of 481.7MM as of March 2025. 234.1MM ICP (44.1% of total supply) is staked by token holders in the form of neurons with over 87.2% locked for over 1 year.&lt;br /&gt;
 &lt;br /&gt;
The number of tokens is constantly changing. The rewards paid out to the node providers and governance participants contribute to the inflation in token supply while factors like compute/storage fees and transaction fees cause deflation in the total supply.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Neurons_101&amp;diff=8430</id>
		<title>Neurons 101</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Neurons_101&amp;diff=8430"/>
		<updated>2025-06-30T21:29:37Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084120668692-Neurons}}&lt;br /&gt;
&lt;br /&gt;
On the Internet Computer, a neuron is a unit that holds tokens and can vote on governance proposals. Simply put, you can lock ICP in the NNS into neurons that can vote on NNS proposals. Switching to the SNS tab, you can lock SNS1 tokens in the SNS into neurons to vote on SNS-1 proposals (using OpenChat or DSCVR).Neurons have different properties and can perform different actions. To clear up any confusion let’s go through these properties and actions. NOTE: not all of these are available in the SNS yet on the NNS frontend dapp.&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
* &#039;&#039;&#039;Stake&#039;&#039;&#039; (NNS / SNS) - The amount of tokens that a neuron holds. You can always increase this stake, however you only will get access to these tokens again, once the neuron’s “Dissolve Delay” (see below) hits 0.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Dissolve Delay&#039;&#039;&#039; | Remaining (NNS / SNS) - Every neuron has a dissolve delay (also displayed as “remaining”). This is the time it would take your tokens in the neuron to become liquid (unlocked) after you “Start Dissolving”. The higher the dissolve delay, the higher the voting power (and voting rewards in case it’s configured).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Age Bonus&#039;&#039;&#039; (NNS / SNS) - Age Bonus is a multiplier that gets applied to your voting power. The longer you keep your neuron locked the higher this multiplier is. Clicking “Start Dissolving” resets this number to 0 immediately.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Voting Power&#039;&#039;&#039; (NNS / SNS) - Voting power is how much your locked tokens count when used for voting. Voting power depends on the stake, dissolve delay and age bonus. Example: 10 ICP locked for 8 years that has 0 age bonus, will have a voting power of 20. The way voting power is calculated can be changed by the DAO.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Maturity&#039;&#039;&#039; (NNS) - Maturity is the voting rewards you collected that are not yet minted. You can use maturity in two ways: “Stake Maturity” or “Disburse MaturitySpawn Neuron” (see below). Voting rewards are configured to be 0 for SNS-1, this can be changed by the SNS-1 DAO through a proposal.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Minimum Staking Period for Voting&#039;&#039;&#039; (NNS / SNS) -The minimum dissolve delay your neuron needs to have in order to be eligible to vote on proposals.&lt;br /&gt;
** NNS - 6 months&lt;br /&gt;
** SNS-1 - 1 month&lt;br /&gt;
&lt;br /&gt;
==Actions==&lt;br /&gt;
* &#039;&#039;&#039;Vote&#039;&#039;&#039; (NNS / SNS) - Neurons can vote on governance proposals. In the NNS, you have a tab called “Voting” where you can see all proposals. In SNS-1, you can vote using OpenChat or DSCVR.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Start/Stop Dissolving&#039;&#039;&#039; (NNS / SNS) - When a neuron is dissolving, the time it is locked for is ticking down. Once it goes down to 0, your tokens become liquid. The reason why you would want to keep your neuron locked and not dissolving is so that it stays above minimum required dissolve delay to vote and so that it accrues age bonus increasing its voting power.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Increase Dissolve Delay&#039;&#039;&#039; (NNS/SNS) - You can always increase a neuron’s dissolve delay, but only decrease it by dissolving.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Stake Maturity&#039;&#039;&#039; (NNS)- Staking maturity locks your voting rewards for the same period as the dissolve delay which will contribute to the neuron’s voting power. Once your neuron is completely dissolved, you get both your original stake and the staked maturity. Staking maturity allows for compounding rewards.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Add Hotkey&#039;&#039;&#039; (SNS/NNS) - Adding a hotkey to a neuron allows another principal to vote with your neuron. If you add your OpenChat or DSCVR principal as a hotkey, you will be able to vote using OpenChat’s or DSCVR’s UI.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Follow Neurons&#039;&#039;&#039; (NNS / SNS): An advantage of the liquid democracy implemented in the NNS is that neurons can follow other neurons. This way you can delegate your voting to other neurons and still receive voting rewards. This will soon be added to SNS.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Disburse&#039;&#039;&#039; (NNS/SNS) - Make the tokens inside a neuron liquid.&lt;br /&gt;
&lt;br /&gt;
SNS-1 tokens need to be locked for at least 30 days for them to be eligible to vote. Clicking “Start Dissolve“ will start the timer, however once it dips below 30 days, the neuron will not be eligible to vote.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [https://dscvr.one/post/6958037/neurons-101 neurons 101 on DSCVR]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Decentralization_in_ICP:_Infrastructure_Governance&amp;diff=8429</id>
		<title>Decentralization in ICP: Infrastructure Governance</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Decentralization_in_ICP:_Infrastructure_Governance&amp;diff=8429"/>
		<updated>2025-06-30T21:29:05Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34574082263700-Tokenomics-Governance}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Summary==&lt;br /&gt;
&lt;br /&gt;
As a blockchain protocol, decentralization is very important to the design and implementation of ICP. This article is one of a subset explaining the design intent and the current state of the world when it comes to ICP decentralization. &#039;&#039;&#039;Its main focus is analyzing ICP as a [[sovereign network]] with a DAO controlling infrastructure governance&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To see the whole picture, it is recommended to see the following articles:&lt;br /&gt;
&lt;br /&gt;
* [[Decentralization in ICP]]&lt;br /&gt;
* [[Decentralization in ICP: Critical Dapps on the IC]]&lt;br /&gt;
* [[Decentralization in ICP: Protocol Governance]]&lt;br /&gt;
&lt;br /&gt;
==Background: Sovereign Network using Deterministic Decentralization==&lt;br /&gt;
&lt;br /&gt;
The infrastructure layer of ICP is best summarized as:&lt;br /&gt;
* ICP is a [[sovereign network]] composed of [https://dashboard.internetcomputer.org/subnets subnets] that follow [[Deterministic Decentralization]]&lt;br /&gt;
* Each subnet is composed of nodes (owned and controlled by node providers), which are remunerated in ICP by the network minting ICP&lt;br /&gt;
* Each node lives in an independent data center (not cloud providers), which the node provider pays to upkeep and maintain. An example of data centers include Equinix in Spain.&lt;br /&gt;
&lt;br /&gt;
==Current State of Infrastructure Decentralization==&lt;br /&gt;
&lt;br /&gt;
To best understand current state of ICP topology and node diversification, the following forum posts lay the most information:&lt;br /&gt;
&lt;br /&gt;
1. [https://forum.dfinity.org/t/ic-topology-series-node-diversification-part-i/23402 IC node diversification (Part 1)]&lt;br /&gt;
&lt;br /&gt;
2. [https://forum.dfinity.org/t/ic-topology-node-diversification-part-ii/23553 IC node diversification (Part 2)]&lt;br /&gt;
&lt;br /&gt;
==Example: Adding a node to the network==&lt;br /&gt;
&lt;br /&gt;
For a concrete example, adding a node to the network takes the following steps:&lt;br /&gt;
&lt;br /&gt;
===1. Node provider submits a proposal to [https://dashboard.internetcomputer.org/proposal/107568|become a node provider]===&lt;br /&gt;
&lt;br /&gt;
[[File:Node provider submits a proposal to become a node provider.png |800px ]]&lt;br /&gt;
&lt;br /&gt;
===2. NNS DAO decides if they want to add this node provider===&lt;br /&gt;
&lt;br /&gt;
===3. If accepted by the NNS DAO, submit proposal to add node to subnet or data center===&lt;br /&gt;
&lt;br /&gt;
* Node provider submits a proposal to add a node in a specific subnet in a [https://dashboard.internetcomputer.org/proposal/107569 specific data center] in a specific location&lt;br /&gt;
&lt;br /&gt;
[[File:Proposal_to_add_data_center.png  |800px ]]&lt;br /&gt;
&lt;br /&gt;
===4. NNS DAO evaluates whether to accept the proposal based on questions like===&lt;br /&gt;
* Does ICP need more nodes?&lt;br /&gt;
* Does this node provider have too many nodes already?&lt;br /&gt;
* Does this subnet need more nodes?&lt;br /&gt;
* Does this data center have too many nodes?&lt;br /&gt;
* Does this location have too many nodes?&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Decentralization in ICP]]&lt;br /&gt;
* [[Decentralization in ICP: Protocol Governance]]&lt;br /&gt;
* [[Decentralization in ICP: Critical Dapps on the IC]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Troubleshooting_Failed_NNS_proposals&amp;diff=8428</id>
		<title>Troubleshooting Failed NNS proposals</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Troubleshooting_Failed_NNS_proposals&amp;diff=8428"/>
		<updated>2025-06-30T21:25:38Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084113508500-Proposals}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Background ===&lt;br /&gt;
Occasionally, a proposal on the Network Nervous System (NNS) may be adopted but fail during execution. This usually happens due to violations of certain invariants (constraints) in the NNS Registry.&lt;br /&gt;
&lt;br /&gt;
==== Example of a Failed Proposal ====&lt;br /&gt;
An instance of such a failure can be seen in https://dashboard.internetcomputer.org/proposal/125578.&lt;br /&gt;
&lt;br /&gt;
==== Screenshot ====&lt;br /&gt;
A screenshot of the failed proposal as displayed on the dashboard, for future reference, of https://dashboard.internetcomputer.org/proposal/125578&lt;br /&gt;
[[File:Failed-nns-proposal.png|center|thumb|791x791px|Screenshot of a failed NNS proposal in the dashboard]]&lt;br /&gt;
&lt;br /&gt;
=== Identifying the Cause of Failure ===&lt;br /&gt;
As of now, the specific reasons for a proposal&#039;s failure are not directly accessible on the proposal page. To find out why a proposal failed, you need to interact with the governance canister directly.&lt;br /&gt;
&lt;br /&gt;
==== Steps to Follow ====&lt;br /&gt;
&lt;br /&gt;
# Visit the governance canister page https://dashboard.internetcomputer.org/canister/rrkah-fqaaa-aaaaa-aaaaq-cai.&lt;br /&gt;
# Scroll down to the section labeled &amp;lt;code&amp;gt;get_proposal_info&amp;lt;/code&amp;gt;&lt;br /&gt;
# Use the toggle field to input the proposal number and click &amp;quot;Call&amp;quot;.[[File:Failed-proposal-get-info.png|center|thumb|654x654px|Get info on the failed NNS proposal, on the public dashboard]]&lt;br /&gt;
# Once the result appears, select &amp;quot;JSON&amp;quot; to view it in Json format.&lt;br /&gt;
# The failure reason will be detailed in the output. &lt;br /&gt;
&lt;br /&gt;
==== Example Output ====&lt;br /&gt;
Below is an example JSON output for a failed proposal. In this case, the proposal failed because an existing Node Operator record was being duplicated. &lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
&lt;br /&gt;
Open that toggle field, enter the proposal number, and click &amp;quot;Call&amp;quot;. Once you get the result, you can click on &amp;quot;JSON&amp;quot; to get the Json format, and you can read the failure reason in the output. In this case, the same Node Operator record was already present in the registry when the proposal attempted to re-add the same record.&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;id&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;id&amp;quot;: 125578&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;status&amp;quot;: 5,&lt;br /&gt;
     &amp;quot;topic&amp;quot;: 5,&lt;br /&gt;
     &amp;quot;failure_reason&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;error_message&amp;quot;: &amp;quot;Error executing ExecuteNnsFunction proposal. Rejection message: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: Panicked at &#039;[Registry] Verification of the mutation type failed with the following errors: [Registry Canister Error. Msg: Key already present: node_operator_record_mbnsu-w4xfc-pmdok-r2lwo-wxfr4-gigu5-4idcm-5uuuy-znvby-biiny-jqe].&#039;, rs/registry/canister/src/registry.rs:293:13&amp;quot;,&lt;br /&gt;
         &amp;quot;error_type&amp;quot;: 12&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;ballots&amp;quot;: [&lt;br /&gt;
       [&lt;br /&gt;
         &amp;quot;14315117116521128082&amp;quot;,&lt;br /&gt;
         {&lt;br /&gt;
           &amp;quot;vote&amp;quot;: 0,&lt;br /&gt;
           &amp;quot;voting_power&amp;quot;: 196565756&lt;br /&gt;
         }&lt;br /&gt;
       ]&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;proposal_timestamp_seconds&amp;quot;: 1699617467,&lt;br /&gt;
     &amp;quot;reward_event_round&amp;quot;: 0,&lt;br /&gt;
     &amp;quot;deadline_timestamp_seconds&amp;quot;: [&lt;br /&gt;
       1699963110&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;failed_timestamp_seconds&amp;quot;: 1699878752,&lt;br /&gt;
     &amp;quot;reject_cost_e8s&amp;quot;: 1000000000,&lt;br /&gt;
     &amp;quot;derived_proposal_information&amp;quot;: [],&lt;br /&gt;
     &amp;quot;latest_tally&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;no&amp;quot;: 66258822305525,&lt;br /&gt;
         &amp;quot;yes&amp;quot;: &amp;quot;45221535235544100&amp;quot;,&lt;br /&gt;
         &amp;quot;total&amp;quot;: &amp;quot;45541158736625569&amp;quot;,&lt;br /&gt;
         &amp;quot;timestamp_seconds&amp;quot;: 1699878752&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;reward_status&amp;quot;: 1,&lt;br /&gt;
     &amp;quot;decided_timestamp_seconds&amp;quot;: 1699878752,&lt;br /&gt;
     &amp;quot;proposal&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;url&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
         &amp;quot;title&amp;quot;: [&lt;br /&gt;
           &amp;quot;Add mbnsu as a Node Operator of Node Provider: 4jjya&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;action&amp;quot;: [&lt;br /&gt;
           {&lt;br /&gt;
             &amp;quot;ExecuteNnsFunction&amp;quot;: {&lt;br /&gt;
               &amp;quot;nns_function&amp;quot;: 8,&lt;br /&gt;
               &amp;quot;payload&amp;quot;: &amp;quot;4449444c056c06a795f3ad04018af3a2b108029bf499bd0878bbf187b70c03dddfde9b0d02dba7aaae0d716e716e686d046c020071017901000001011d97289ec1b951d2eceb5cb1e1906a77881899da5298cb6a1c05086e13020a000000000000000001011d78c0a5ff79e51f8d11fa75ad5db01d3d7cee8fecd6658d81c6deb6a20203726731&amp;quot;&lt;br /&gt;
             }&lt;br /&gt;
           }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;summary&amp;quot;: &amp;quot;Node provider “MB Patrankos šūvis” is adding 10 nodes in the rg1 data center&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;proposer&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;id&amp;quot;: &amp;quot;1482125923012887388&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;executed_timestamp_seconds&amp;quot;: 0&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Service_Nervous_System_(SNS)&amp;diff=8427</id>
		<title>Service Nervous System (SNS)</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Service_Nervous_System_(SNS)&amp;diff=8427"/>
		<updated>2025-06-30T21:20:17Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084394684564-SNS-Service-Nervous-System}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly to how the Network Nervous System (NNS) is the open tokenized [[DAO]] that controls the Internet Computer blockchain (IC), service nervous systems (SNSs) are algorithmic [[DAO]]s that allow developers to hand over control of their dapp to decentralized, token-based governance systems. This means, each dapp that would like to be under decentralized control will have a separate SNS.&lt;br /&gt;
&lt;br /&gt;
Developers can now hand over their Web3 service to an SNS there are also [https://wiki.internetcomputer.org/wiki/How_to_get_a_DAO_on_the_IC other alternatives of how developers can get a DAO]. The community can get governance tokens to take ownership and control through the SNS DAO and shape the dapp’s future.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sns-canisters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== SNS canisters ==&lt;br /&gt;
&lt;br /&gt;
The SNS consists of a governance canister, a ledger canister with archive canisters and an index canister, a root canister, and a decentralization swap canister that is explained in the next section.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;ledger canister&#039;&#039; implements the [https://github.com/dfinity/ICRC-1 ICRC-1 standard] and contains SNS tokens, which are unique tokens for each SNS. It stores which accounts own how many SNS tokens and the history of transactions between the principals.&lt;br /&gt;
The archive canisters stores the history of the ledger transactions and the index canister allows one to find all the transactions associated with an account.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;governance canister&#039;&#039; enables decentralized decision making. It stores &#039;&#039;proposals&#039;&#039; that are suggestions on how to evolve the dapp that the SNS governs and &#039;&#039;neurons&#039;&#039; that define who the governance participants are. Neurons facilitate stake-based voting as they contain staked SNS tokens. Everyone can become a government participant by staking SNS tokens in a neuron. &lt;br /&gt;
&lt;br /&gt;
The root canister is responsible for upgrading the other SNS canisters and the dapp canisters that the SNS controls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sns-lifecycle&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== SNS lifecycle ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sns-launch&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== SNS launch process ===&lt;br /&gt;
SNS canisters are [https://wiki.internetcomputer.org/wiki/How_to_get_a_DAO_on_the_IC maintained and blessed by the IC community]. In more detail, the blessed SNS versions and upgrade paths are stored on an NNS canister called the [[SNS wasm modules canister]] SNS-W. &lt;br /&gt;
&lt;br /&gt;
An SNS is launched by developers handing over their dapp to the NNS. An NNS proposal then defines the exact parameters with which an SNS is created and the conditions of the launch. If this proposal is adopted, an SNS is created and the dapp is handed over to this SNS. If the proposal is rejected, then the dapp is given back to the developer’s control.&lt;br /&gt;
&lt;br /&gt;
===== SNS decentralization swap =====&lt;br /&gt;
A crucial part of launching an SNS is how it can be decentralized. That is, the newly created tokens must be distributed to a large community to ensure proper decentralization of voting power. There are of course many ways to do so. The first SNS version provides one simple way to achieve this: a developer can hand over their dapp to the NNS and ask it to start a decentralization swap. In the decentralization swap, a fixed number of newly created SNS tokens are given away. The swap collects ICP tokens and, in the end, the conversion rate is computed as the number of ICP collected by the number of SNS tokens - the tokens are swapped. After a successful decentralization swap, SNS tokens are thus owned by a large community and therefore the SNS governance control is decentralized. Moreover, the ICP that were collected in the decentralization swap provide initial funding for the SNS project. &lt;br /&gt;
&lt;br /&gt;
If you are looking to decentralize a dapp, you can find more information in the [https://internetcomputer.org/docs/current/developer-docs/integrations/sns/ developer documentation]. If you want to participate, you can find more information on [https://internetcomputer.org/sns the SNS website].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sns-maintenance&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== SNS DAO  ===&lt;br /&gt;
&lt;br /&gt;
There are some important maintenance tasks that have to be performed by an SNS community, such as deciding and voting on when an SNS should be upgraded to a new blessed version, adjusting the SNS parameters when needed, and making sure that the SNS canisters do not run out of cycles.&lt;br /&gt;
There is more information about how to [https://internetcomputer.org/sns participate in an SNS DAO] and more technical details of how to contribute to [https://internetcomputer.org/docs/current/developer-docs/integrations/sns/managing/manage-sns-intro managing an SNS DAO] as a community member.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Staking,_voting_and_rewards&amp;diff=8426</id>
		<title>Staking, voting and rewards</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Staking,_voting_and_rewards&amp;diff=8426"/>
		<updated>2025-06-30T21:19:40Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34084120668692-Neurons}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_Tokenomics&amp;diff=8425</id>
		<title>ICP Tokenomics</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_Tokenomics&amp;diff=8425"/>
		<updated>2025-06-30T21:16:01Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34090810571284-Tokenomics}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Web3:_The_bull_case_for_the_Internet_Computer&amp;diff=8424</id>
		<title>Web3: The bull case for the Internet Computer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Web3:_The_bull_case_for_the_Internet_Computer&amp;diff=8424"/>
		<updated>2025-06-30T21:15:30Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/33152818663444-What-is-ICP}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next wave of innovative applications, business, digital personas, finance, and entertainment will be built on decentralized infrastructure. Their creation will come &#039;&#039;from&#039;&#039; the community, &#039;&#039;for&#039;&#039; the community and further will be &#039;&#039;controlled by&#039;&#039; the community. Such are the promises of Web3.&lt;br /&gt;
&lt;br /&gt;
== Once upon a time in Web1 ==&lt;br /&gt;
In the 90&#039;s, &#039;&#039;surfing the web&#039;&#039; often entailed getting over-excited the sound of a dial-up internet connection and the count of results from early search engines. For the first time the world had access to information like never before. Looking back, it seems primitive, but the revolutionary nature of the network that came together to form Web1 should not be discarded. &lt;br /&gt;
&lt;br /&gt;
Considering the history of the internet, the two major contributions of web1 were&lt;br /&gt;
* The &#039;&#039;&#039;creation of the network&#039;&#039;&#039; itself&lt;br /&gt;
* &#039;&#039;&#039;Read access&#039;&#039;&#039; - users access and read materials from a select bunch of early internet contributors. &lt;br /&gt;
&lt;br /&gt;
== Enter Web2 == &lt;br /&gt;
Web2 will largely be remembered as the iteration of the internet that introduced social media, advertising, and digital content in general. Web2 brought many great applications that enabled users to engage in a more meaningful way with the internet. Through the platformization of services, users moved from the era of &#039;read-only&#039; web to one where they could &#039;read and write&#039; and begin to digitize their lives. &lt;br /&gt;
&lt;br /&gt;
With more and more information being created and stored on the web, questions of security and privacy became much more prevalent. Two of the greatest contributions to Web2 were TLS (which allows information to flow across the internet in an encrypted manner) and the Signal protocol (which allows end-to-end encrypted messaging (in the Signal app, Whatsapp, and Facebook messenger, to name a few.)) While these security advances provided greater integrity for data flows on the internet, it was left to the discretion of centralized organizations to implement and use them, if and when they chose to. While information flows may not be visible to the public, large amounts of data are visible to the owner of the platform. This means that the core of the services and applications on the internet remain in the hands of a few organizations, rather than with the users who provide and consume the content.&lt;br /&gt;
&lt;br /&gt;
Furthering the history of the internet, the major contributions of Web2 are&lt;br /&gt;
* &#039;&#039;&#039;Monetization&#039;&#039;&#039; of apps&lt;br /&gt;
* The possibility of &#039;&#039;&#039;security and privacy&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Read and write access&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Growing to Web3 == &lt;br /&gt;
Web3 aims to overcome the issues found in web2 by removing the central point of trust and shifting control to the people who build, contribute to, and use the internet and its services. There are a number of ways in which this can be achieved, but the most promising is by leveraging decentralization of information and computing offered by blockchains.&lt;br /&gt;
&lt;br /&gt;
It has become widely know that blockchains support tokens, often in the form of cryptocurrencies, but other tokens are emerging which enable users to take a more active role in the applications they use. With tokenization, users can move to a &#039;read, write and own&#039; iteration of the internet. &lt;br /&gt;
&lt;br /&gt;
An important point to note is that in the transition to web3, to truly overcome the pitfalls of web2, users should aim to build applications that are decentralized at every point in the stack. If any part of developing, operating, or governing is not decentralized then it remains the case that there is a single party who can control our use of the dapp.&lt;br /&gt;
&lt;br /&gt;
When looking back on the evolution of the internet, it&#039;s expected to see Web3 contributions as&lt;br /&gt;
* Integrating &#039;&#039;&#039;identity&#039;&#039;&#039;&lt;br /&gt;
* Systems with &#039;&#039;&#039;native payments&#039;&#039;&#039;&lt;br /&gt;
* The incubator for the birth of &#039;&#039;&#039;DAOs (Decentralized Autonomous Organizations)&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;read, write, and own&#039;&#039;&#039; model of the internet.&lt;br /&gt;
&lt;br /&gt;
=== Identity on Web3 ===&lt;br /&gt;
* Users should be able to use a dapp without requiring tokens: no entrance barrier with Internet Identity&lt;br /&gt;
* [[Internet Identity]] - allows to interact with dapps without the need for tokens&lt;br /&gt;
&lt;br /&gt;
=== The rise of DAOs ===&lt;br /&gt;
* It should be possible to easily tokenize dapps so that users can participate in ownership, success, and governance, while developers have  a sustainable way to raise funds&lt;br /&gt;
* [[Network Nervous System|Network Nervous System]] - allows users to stake tokens, and earn rewards for participating in governance of the Internet Computer&lt;br /&gt;
* &#039;&#039;&#039;[[Service Nervous System (SNS)| Service nervous system]]&#039;&#039;&#039; - allows developers to easily tokenize dapps to raise funds, giving ownership to the users, and to crowdsource decision making&lt;br /&gt;
&lt;br /&gt;
=== Native payments ===&lt;br /&gt;
One suggested reason why Web2 ended up being so centralized is that there was no native system for making (micro and/or web) payments. This made it difficult for digital creators and entrepreneurs to build a business without relying on large centralized organizations and platforms to build upon. Given that decentralized applications are generally built on blockchain platforms, it&#039;s often the case that there is a native token and payment mechanism. This eases the flow of funds between peers. &lt;br /&gt;
&lt;br /&gt;
The ease of token/fund transfer, coupled with the formation of DAOs makes it substantially more convenient to raise funds to start a business and grow different types of economies.&lt;br /&gt;
&lt;br /&gt;
== Decentralized Future == &lt;br /&gt;
Right now the world is still working its way into Web3. The industry is figuring out what it means to remove trust from a single organization and pass it on to a group. Builders are debating between different models of authentication, tokenization, control, buisness, infrastructure and much more. &lt;br /&gt;
Some of the things are are needed for a decentralized Web3 are &lt;br /&gt;
* &#039;&#039;&#039;Automation &amp;amp; upgradability&#039;&#039;&#039; - Currently, even given the rise of DAOs and digital liquid democracy, it is often the case that decentralized decisions are passed on to a single authority to execute the decision. Trust removal falls at the final hurdle. For a true Web3 experience, DAOs should be, as their name applies, autonomous. Read more about the [[Network Nervous System]] of the IC. &lt;br /&gt;
* &#039;&#039;&#039;Interoperability&#039;&#039;&#039; - As the ecosystem grows it becomes increasingly important to maintain interoperability between applications and chains in s secure (i.e. bridge-free) manner. Read more about [[Bitcoin integration]]. &lt;br /&gt;
* &#039;&#039;&#039;Censorship resistance&#039;&#039;&#039; - it should be the case the users have the right to write, the right to read, and the right to own.&lt;br /&gt;
* &#039;&#039;&#039;Accessability&#039;&#039;&#039; - * Developers should be able to build dapps that are fully onchain. It should be the case that a dapp can serve content directly into users browser. The operational cost of running a dapp should be comparable to running a web2 application (e.g. on AWS). Read more about [[Canister smart contracts]] allow to serve webpages without the need for centralized services.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Subnet_blockchain&amp;diff=8423</id>
		<title>Subnet blockchain</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Subnet_blockchain&amp;diff=8423"/>
		<updated>2025-06-30T20:21:06Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34209955782420-Subnet-Creation}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A subnet (subnetwork) is a collection of nodes that run their own instance of the consensus algorithm to produce a subnet blockchain that interacts with other subnets of the IC using chain key cryptography.&lt;br /&gt;
&lt;br /&gt;
==Subnet Architecture==&lt;br /&gt;
The IC is designed to be highly scalable and efficient in terms of hosting and executing canister smart contracts. The top-level building blocks of the IC are subnetworks, or subnets: the IC as a whole consists of many subnets, where each subnet is its own blockchain that operates concurrently with and independently of the other subnets (but can communicate asynchronously with other subnets). Each subnet hosts canister smart contracts, up to a total of hundreds of gigabytes of replicated storage. A subnet consists of node machines, or nodes. Each node replicates all the canisters, state, and computation of the subnet using blockchain technology. This makes a subnet a blockchain-based replicated state machine, that is, a virtual machine that holds state in a secure, fault-tolerant, and non-tamperable manner: the computations of the canisters hosted on a subnet will proceed correctly and without stopping, even if some of the nodes on the subnet are faulty (either because they crash, or even worse, are hacked by a malicious party) New subnets can be created from nodes added to the IC to scale the IC, analogous to how traditional infrastructures such as public clouds scale out by adding machines. Such a scale-out architecture is rather the exception than the rule in the blockchain space and allows for limitless scaling, i.e., combining the security and resiliency properties of blockchains with the scalability properties enjoyed by the public cloud.&lt;br /&gt;
&lt;br /&gt;
==List of Subnets==&lt;br /&gt;
&lt;br /&gt;
All of the subnets, with their corresponding topologies and activities are listed on the IC dashboard: [https://dashboard.internetcomputer.org/subnets ICP subnets].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[New Subnet Creation]]&lt;br /&gt;
* [[Sovereign Network]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Limitless_Scaling&amp;diff=8422</id>
		<title>Limitless Scaling</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Limitless_Scaling&amp;diff=8422"/>
		<updated>2025-06-30T20:20:12Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34209955782420-Subnet-Creation}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The Internet Computer (IC) can scale its capacity without limit, simply by adding additional nodes to fuel new subnets. Nodes are added via the Network Nervous System (NNS) which forms new subnets almost on a weekly basis since genesis. In contrast, most other blockchains have transaction limits baked into the protocol (e.g. adding more servers to Bitcoin does not increase the throughput) and need cumbersome layers to address scaling.&lt;br /&gt;
&lt;br /&gt;
See Internet Computer Dashboard for current scale and performance numbers: https://dashboard.internetcomputer.org/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subnet Architecture ===&lt;br /&gt;
&lt;br /&gt;
Please see [https://internetcomputer.org/docs/current/concepts/nodes-subnets Subnet architecture]&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Principal&amp;diff=8421</id>
		<title>Principal</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Principal&amp;diff=8421"/>
		<updated>2025-06-30T16:24:37Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/getting-started/identities}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;principal&#039;&#039;&#039; is an identifier for an entity on the IC such as a user, a canister (dapps/smart contracts), or a subnet.  &lt;br /&gt;
&lt;br /&gt;
Motoko’s shared functions support a simple form of &#039;&#039;&#039;caller identification&#039;&#039;&#039; that allows to inspect the Internet Computer principal associated with the caller of a function. The principal associated with a call is a value that identifies a &#039;&#039;unique&#039;&#039; user or canister.&lt;br /&gt;
Using the principal associated with the caller of a function allows to implement a basic form of &#039;&#039;&#039;access-control&#039;&#039;&#039; in a program.&lt;br /&gt;
&lt;br /&gt;
== Types of principals ==&lt;br /&gt;
There are several types of principals.&lt;br /&gt;
&lt;br /&gt;
=== Management principal ===&lt;br /&gt;
The management principal is used to reference the management canister.&lt;br /&gt;
&lt;br /&gt;
=== Opaque principal ===&lt;br /&gt;
An opaque principal is chosen by the protocol. This kind of principal is used to reference any canister that is not the management canister.&lt;br /&gt;
&lt;br /&gt;
=== Self-Authenticating principal ===&lt;br /&gt;
A self-authenticating principal is a hash of a public signature key. This kind of principal is for instance used to reference a subnet or user.&lt;br /&gt;
&lt;br /&gt;
=== Derived principal ===&lt;br /&gt;
The principal is derived from a registering principal. This type of principal is currently not used.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous principal ===&lt;br /&gt;
The anonymous principal is used to reference an anonymous user.&lt;br /&gt;
&lt;br /&gt;
== Representation ==&lt;br /&gt;
&lt;br /&gt;
=== Binary ===&lt;br /&gt;
A principal consists of a variable-length byte array of up to 29 bytes. The last byte is used to indicate the type. The table below gives the type inferred from the last byte.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Byte&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Type&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|none&lt;br /&gt;
|Management &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;0x01&amp;lt;/code&amp;gt;&lt;br /&gt;
|Opaque&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;0x02&amp;lt;/code&amp;gt;&lt;br /&gt;
|Self-Authenticating&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;0x03&amp;lt;/code&amp;gt;&lt;br /&gt;
|Derived&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;0x04&amp;lt;/code&amp;gt;&lt;br /&gt;
|Anonymous&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;0x05&amp;lt;/code&amp;gt;&lt;br /&gt;
|Unassigned&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Textual ===&lt;br /&gt;
A principal is shown in textual format by prepending it with its [[wikipedia:Cyclic_redundancy_check#CRC-32_algorithm|CRC-32]] value in big-endian byte order, applying [[wikipedia:Base32|Base32]] encoding without padding, grouping characters by length five, and separating them by a hyphen. The maximal length of the encoding, including hyphens, is 63 characters. The table below gives some common principals.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Principal&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;aaaaa-aa&amp;lt;/code&amp;gt;&lt;br /&gt;
|[[Management Canister|management canister]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;rrkah-fqaaa-aaaaa-aaaaq-cai&amp;lt;/code&amp;gt;&lt;br /&gt;
|[[Governance Canister|governance canister]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ryjl3-tyaaa-aaaaa-aaaba-cai&amp;lt;/code&amp;gt;&lt;br /&gt;
|[[Ledger Canister|ledger canister]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe&amp;lt;/code&amp;gt;&lt;br /&gt;
|[[Network Nervous System|network nervous system]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;2vxsx-fae&amp;lt;/code&amp;gt;&lt;br /&gt;
|anonymous user&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Further Information == &lt;br /&gt;
* Check the [https://internetcomputer.org/docs/current/motoko/main/base/Principal/ Motoko Base Library] to see how to use principal functions.&lt;br /&gt;
* See the [https://internetcomputer.org/docs/current/motoko/main/caller-id/ principals and caller identification] documentation for a more in-depth guide to the uses of principals on the IC.&lt;br /&gt;
* See the [https://internetcomputer.org/docs/current/developer-docs/backend/motoko/access-control/ access-control with identity] tutorial to add extra functionality to a dapp.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Tutorials_for_acquiring,_managing,_and_staking_ICP&amp;diff=8420</id>
		<title>Tutorials for acquiring, managing, and staking ICP</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Tutorials_for_acquiring,_managing,_and_staking_ICP&amp;diff=8420"/>
		<updated>2025-06-30T16:24:13Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://youtu.be/XU54fbCzFmE?feature=shared}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__NUMBEREDHEADINGS__&lt;br /&gt;
The governance of the Internet Computer depends on people staking their [[ICP Tokenomics | ICP token]] and voting on proposals. To do this, there are four steps. Each step has different sets of options (with trade-offs):&lt;br /&gt;
&lt;br /&gt;
# Acquire ICP&lt;br /&gt;
# Custody &lt;br /&gt;
# Staking&lt;br /&gt;
# Voting&lt;br /&gt;
&lt;br /&gt;
This article is an entry point into these four topics. For a simple, opinionated tutorial that makes choices to maximize simplicity, see [[Staking for dummies]].&lt;br /&gt;
&lt;br /&gt;
==Acquire ICP==&lt;br /&gt;
&lt;br /&gt;
To get started, you first need to acquire ICP tokens. You can do this buying them in an exchange or by having someone you send you ICP.&lt;br /&gt;
&lt;br /&gt;
===Buy ICP from Crypto Onramps===&lt;br /&gt;
Crypto onramps allow you to buy ICP directly from your credit card or bank account without having to open an account. They don&#039;t store your tokens, instead send them directly to your wallet address (see [[ICP custody options|Wallet &amp;amp; Custody options]]).&lt;br /&gt;
&lt;br /&gt;
*[https://banxa.com Banxa]&lt;br /&gt;
*[https://guardarian.com Guardarian]&lt;br /&gt;
*[https://ramp.alchemypay.org/ AlchemyPay]&lt;br /&gt;
*[https://transak.com Transak]&lt;br /&gt;
*[https://onramp.money Onramp.money]&lt;br /&gt;
*[https://www.simplex.com Simplex]&lt;br /&gt;
* [https://bity.com/ Bity]&lt;br /&gt;
&lt;br /&gt;
===Buy/Sell ICP at Exchanges===&lt;br /&gt;
Please check below for a list of exchanges where you can buy/sell ICP &lt;br /&gt;
&lt;br /&gt;
*[https://coinmarketcap.com/currencies/internet-computer/#Markets CoinMarketCap list of ICP exchanges]&lt;br /&gt;
*[https://www.coingecko.com/en/coins/internet-computer CoinGecko list of ICP exchanges]&lt;br /&gt;
&lt;br /&gt;
===Seed Round Contributors===&lt;br /&gt;
&lt;br /&gt;
Seed round participants who wish to claim their neurons (from 2021) should first see: [[How-To: Claim neurons for seed participants]].&lt;br /&gt;
&lt;br /&gt;
==Custody==&lt;br /&gt;
&lt;br /&gt;
Custody is the act of managing your ICP. There are many options, each with different security and usability trade-offs. For a summary of the range of options available to you depending on your comfort level, see [[ICP custody options]]. &lt;br /&gt;
&lt;br /&gt;
==Staking==&lt;br /&gt;
&lt;br /&gt;
Once you decide on your custody, staking is the action of locking ICP within a [[neuron]] with a [[dissolve delay]]. [[Staking and voting]] are critical to [[Governance of the Internet Computer]].&lt;br /&gt;
&lt;br /&gt;
By staking you can vote on NNS Proposals and collect NNS rewards. There are many options for staking, each with different security and usability trade-offs. See [[ICP staking options]].&lt;br /&gt;
&lt;br /&gt;
==Voting==&lt;br /&gt;
&lt;br /&gt;
Voting is the act of voting on [[NNS proposals]] using neurons. See [[ICP voting options]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
*&#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;br /&gt;
*[[Governance of the Internet Computer]]&lt;br /&gt;
*[[Staking and voting]]&lt;br /&gt;
*[[Staking for dummies]]&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
&lt;br /&gt;
*https://www.dfinitycommunity.com/best-exchanges-to-buy-icp/&lt;br /&gt;
*https://medium.com/dfinity/the-community-led-governance-of-the-internet-computer-b863cd2975ba&lt;br /&gt;
*https://medium.com/dfinity/earn-substantial-voting-rewards-by-staking-in-the-network-nervous-system-7eb5cf988182&lt;br /&gt;
*https://medium.com/dfinity/introducing-the-ledger-internet-computer-icp-app-for-nano-wallets-eed38c549f0d&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_custody_with_Ledger_Nano&amp;diff=8419</id>
		<title>ICP custody with Ledger Nano</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_custody_with_Ledger_Nano&amp;diff=8419"/>
		<updated>2025-06-30T16:23:49Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://www.youtube.com/watch?v=0-nSOBC3bxE}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ledger Nano ==&lt;br /&gt;
&lt;br /&gt;
The [https://www.ledger.com/ Ledger] Nano is one of the world’s most popular hardware wallets for safely storing crypto assets. A Ledger wallet combined with the Ledger Live app gives users complete control over their crypto, ensuring ownership over their assets while providing maximum security.&lt;br /&gt;
&lt;br /&gt;
== ICP and Ledger Nano==&lt;br /&gt;
&lt;br /&gt;
To use the Ledger Nano to manage your ICP follow these instructions, you need three things:&lt;br /&gt;
&lt;br /&gt;
* Networked computer  &lt;br /&gt;
* [https://identity.ic0.app/ Internet Identity] with [https://nns.ic0.app/v2/ NNS frontend dapp]&lt;br /&gt;
* Ledger Nano&lt;br /&gt;
&lt;br /&gt;
You can follow the user manual here: [https://medium.com/dfinity/integrating-ledger-nano-with-the-nns-front-end-dapp-user-manual-9c5600925e16 Integrating Ledger Nano With the NNS Front-End Dapp]. If you prefer using CLI, there is a [[Hardware Wallet CLI]] that you can also use to manage any ICRC-1 token.&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
&lt;br /&gt;
The Ledger Nano + NNS dapp integration supports the following actions:&lt;br /&gt;
&lt;br /&gt;
* Receive/send ICP&lt;br /&gt;
* Stake a neuron&lt;br /&gt;
* View neurons&lt;br /&gt;
* Add neurons as hotkeys&lt;br /&gt;
* Dissolve neurons&lt;br /&gt;
* Disburse neurons&lt;br /&gt;
* Increase dissolve delay of neurons&lt;br /&gt;
* View NNS proposals&lt;br /&gt;
* Vote on NNS proposals&lt;br /&gt;
* Choose neurons to follow for voting&lt;br /&gt;
&lt;br /&gt;
==Benefits==&lt;br /&gt;
&lt;br /&gt;
* Maximum control of one&#039;s seed phrase (NNS frontend dapp does not access one&#039;s seed phrase)&lt;br /&gt;
* Has all the functionality one needs for custody, staking, voting&lt;br /&gt;
* Ideal for people who want to want to combine easy web experience with to control of their seedphrase ICP&lt;br /&gt;
&lt;br /&gt;
==Trade-offs and risks==&lt;br /&gt;
&lt;br /&gt;
If you use this combination, you are accepting the following trade-offs:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Risk of losing access&#039;&#039;&#039; - If you only have lose access your Ledger Nano AND forget seed phrase, you lose access to your ICP.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Risk your devices do not support it&#039;&#039;&#039; - Not all devices and browsers support WebAuthn, so this option is sometimes not available.  Supported browsers for Ledger Nano integration currently include Chrome (desktop) v89+, Edge v89+, and Opera v76+.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
The Ledger Internet Computer (ICP) app was built by a collaboration between the [https://zondax.ch/ Zondax] team of engineers and cryptographers and the DFINITY Foundation. It was released and announced on December 3, 2021 [https://medium.com/dfinity/introducing-the-ledger-internet-computer-icp-app-for-nano-wallets-eed38c549f0d].&lt;br /&gt;
&lt;br /&gt;
The Ledger Internet Computer (ICP) app has undergone a third-party audit and has been reviewed and approved by Ledger. You can access the Ledger Internet Computer (ICP) app repository here: https://github.com/Zondax/ledger-icp.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Managing ICP holdings]]&lt;br /&gt;
* [[ICP custody options]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=World_Computer&amp;diff=8418</id>
		<title>World Computer</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=World_Computer&amp;diff=8418"/>
		<updated>2025-06-30T16:23:21Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/what-is-the-ic}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Ethereum]] was the first blockchain that could host [https://en.wikipedia.org/wiki/Turing_completeness Turing complete] [[smart contract]]s, which are secure units of code that process and store data &#039;&#039;on&#039;&#039; the blockchain itself. Back in 2014, the dramatic realization that a blockchain could play the role of a computer, led to someone proposing the concept of a &amp;quot;World Computer.&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The original idea was that Ethereum would become a &amp;quot;World Computer&amp;quot;, but over time the concept faded into obscurity within the Ethereum community. Clearly, a true World Computer blockchain would have to be capable of hosting most of the world&#039;s computation and data to live up to its name, whereas the design trajectory of Ethereum meant this was truly out of reach.&lt;br /&gt;
&lt;br /&gt;
During these early years, Ethereum follower and supporter Dominic Williams was working on applied cryptography and distributed computing math with the aim of speeding up blockchains, and allowing them to scale infinitely. He was deeply struck by the concept of a World Computer, and pivoted his work towards the idea.&lt;br /&gt;
&lt;br /&gt;
During 2015, he researched techniques that might be used to create a World Computer, even tentatively producing an unfinished [https://web.archive.org/web/20150914013643/http://dfinity.io/ website to share his ideas in the Fall]. He has described hoping his work would have been used to create Ethereum 2.0, but eventually realizing the Ethereum project&#039;s path was incompatible with creating a World Computer.&lt;br /&gt;
&lt;br /&gt;
Dominic then founded the Dfinity Foundation in Switzerland in late 2016, to develop a &amp;quot;World Computer&amp;quot; blockchain having received support from a Palo Alto incubator, String Labs, during the summer. The project raised initial funds by selling its token February 24, 2017.&lt;br /&gt;
&lt;br /&gt;
Creating a &amp;quot;World Computer&amp;quot; was an enormously complex endeavor, and the Dfinity Foundation had to build-out the largest R&amp;amp;D operation in blockchain, which currently employs more cryptographers than any other organization in tech. The [[Internet Computer]] blockchain — the first true realization of the World Computer vision — finally underwent network genesis, May 10th 2021.&lt;br /&gt;
&lt;br /&gt;
The Internet Computer has a different architecture to traditional blockchains, which is enabled by [[Chain key cryptography|novel cryptography]]. It has numerous unique capabilities, which allows it to play the role of a World Computer. For example, the [[canister smart contract]]s it hosts can process HTTP requests to serve interactive web experiences directly to users.&lt;br /&gt;
&lt;br /&gt;
The purpose of the Internet Computer is to provide a World Computer that will eventually replace traditional IT, and host all of humanity&#039;s systems and services, as well as enabling Web3 that is fully on-chain.&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Popular_Explainers_of_ICP&amp;diff=8417</id>
		<title>Popular Explainers of ICP</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Popular_Explainers_of_ICP&amp;diff=8417"/>
		<updated>2025-06-30T16:22:35Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/what-is-the-ic}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a protocol, ICP has many ways of describing not just its design intent, but also its usage. The ICP community has written various introductions to ICP (including this wiki) which people have found helpful:&lt;br /&gt;
&lt;br /&gt;
==Popular places to start==&lt;br /&gt;
* &#039;&#039;&#039;[https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;br /&gt;
** This is the website for the project, and its itself hosted on ICP&lt;br /&gt;
* [[Introduction to ICP]]&lt;br /&gt;
* [https://www.youtube.com/watch?v=IfM3I8pudFs&amp;amp;t=327s Internet Computer overview video from 2022 IC hackathon]&lt;br /&gt;
* [https://internetcomputer.org/icig.pdf Internet Computer Infographic (PDF)]&lt;br /&gt;
* [[Glossary | Glossary of ICP terms]]&lt;br /&gt;
&lt;br /&gt;
==For a more technical audience==&lt;br /&gt;
* [https://eprint.iacr.org/2022/087 &amp;quot;Internet Computer for Geeks&amp;quot; paper]&lt;br /&gt;
* [[IC architecture overview]]&lt;br /&gt;
* The [https://internetcomputer.org/howitworks &amp;quot;How it works&amp;quot; series] with videos and in-depth articles on various topics.&lt;br /&gt;
* [https://www.reddit.com/r/dfinity/comments/ozboyi/megathread_technical_amas/ Technical AMAs on Reddit by different IC and DFINITY teams]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_Community&amp;diff=8416</id>
		<title>ICP Community</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_Community&amp;diff=8416"/>
		<updated>2025-06-30T16:21:06Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/education-hub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- START COMMENT&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Introduction&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We have a strong and constantly growing ICP Community comprised of developers, users &amp;amp; owners of ecosystem dapps, ICP fans,  blockchain, web3 enthusiasts, and influencers. Our community is geographically well-distributed and represented across continents. &lt;br /&gt;
&lt;br /&gt;
Relevant online places or thought leaders&lt;br /&gt;
&lt;br /&gt;
Our main Twitter account has 6M + followers and the community is quite active on this platform, additionally, DFINITYour Founder and Chief Scientist Dominic Williams has 1.95k Million followers. Our community is very active on the ICP Dev and Community Forum, and we also have a Community Run blog. We also nurture a community on CoinMarket Cap that is 96k strong. There is a growing ICP community on Discord as well. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Active Independent Communities&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ICP community members have created many different forums for coming together basis interests, geography, etc. Here are some examples of the independently formed communities&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Geographic Communities&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ICPL, China : https://twitter.com/icpleague_com&lt;br /&gt;
&lt;br /&gt;
ICP Vietnam: https://twitter.com/ICPVietnam&lt;br /&gt;
&lt;br /&gt;
Dfinity Indonesia: https://twitter.com/dfinity_id&lt;br /&gt;
&lt;br /&gt;
IC Japan Community: https://twitter.com/IC_JP_Community&lt;br /&gt;
&lt;br /&gt;
ICP India: https://twitter.com/DfinityIndia&lt;br /&gt;
&lt;br /&gt;
ICP Manila: https://twitter.com/ICPManila&lt;br /&gt;
&lt;br /&gt;
ICP Africa: https://twitter.com/ICP_Africa&lt;br /&gt;
&lt;br /&gt;
ICP France: https://twitter.com/icpfrance&lt;br /&gt;
&lt;br /&gt;
ICP Italia: https://twitter.com/icp_italia&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Global ICP Communities &lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
https://twitter.com/ICPSquad&lt;br /&gt;
&lt;br /&gt;
https://t.me/icpmaximalistnetwork&lt;br /&gt;
&lt;br /&gt;
https://twitter.com/8YearGangDAO - For 8 Year Stakers on OpenChat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ICP.Hubs&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ICP.Hubs are glocal communities being built up in strategic locations to bring together the communities in those geographies. These are communities building from the ground up to enable Web3 and ICP adoption. The current hubs are : &lt;br /&gt;
&lt;br /&gt;
ICP.Hub India - https://twitter.com/crewspherein&lt;br /&gt;
&lt;br /&gt;
ICP.Hub LATAM  - https://twitter.com/icphublatam&lt;br /&gt;
&lt;br /&gt;
ICP.Hub East Africa - https://twitter.com/ICPKushites?s=20&lt;br /&gt;
&lt;br /&gt;
ICP.Hub Italy - https://icpitalia.icp.page/	&lt;br /&gt;
&lt;br /&gt;
ICP.Hub Dubai - Upcoming&lt;br /&gt;
&lt;br /&gt;
ICP.Hub North America - Upcoming &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling Community Growth through Grants&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
DFINITY Foundation actively runs a Community Grant program to provide support to those who are driving the expansion of the ICP ecosystem and the industry at large. All details can be found here :&lt;br /&gt;
&lt;br /&gt;
https://dfinity.org/community-grants/&lt;br /&gt;
&lt;br /&gt;
END COMMENT --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_Ecosystem_Stats&amp;diff=8415</id>
		<title>ICP Ecosystem Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_Ecosystem_Stats&amp;diff=8415"/>
		<updated>2025-06-30T16:20:35Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/education-hub}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Index_of_dapps_on_the_Internet_Computer_ecosystem&amp;diff=8414</id>
		<title>Index of dapps on the Internet Computer ecosystem</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Index_of_dapps_on_the_Internet_Computer_ecosystem&amp;diff=8414"/>
		<updated>2025-06-30T16:20:13Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/ecosystem}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Index of dapps on the Internet Computer =&lt;br /&gt;
&lt;br /&gt;
The most actively updated source of dapps on the Internet Computer is the [https://internetcomputer.org/ecosystem ICP ecosystem page].&lt;br /&gt;
&lt;br /&gt;
==Additional List of IC ecosystem aggregators==&lt;br /&gt;
* [https://n7ib3-4qaaa-aaaai-qagnq-cai.raw.ic0.app/?locale=en#/ ICApps]&lt;br /&gt;
* [https://dfinity.org/showcase/ DFINITY Showcase]&lt;br /&gt;
* [https://zire.github.io/awesome-IC/ The Awesome IC Repository]&lt;br /&gt;
* [https://internetcomputer.today/ Internet Computer Today]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Glossary&amp;diff=8413</id>
		<title>Glossary</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Glossary&amp;diff=8413"/>
		<updated>2025-06-30T16:19:38Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/references/glossary}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=IC_Smart_Contract_Memory&amp;diff=8412</id>
		<title>IC Smart Contract Memory</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=IC_Smart_Contract_Memory&amp;diff=8412"/>
		<updated>2025-06-30T16:19:16Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/motoko/orthogonal-persistence/modes}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overall Architecture==&lt;br /&gt;
Canister smart contracts running on the Internet Computer (IC) store data just like most other programs would. To this end, the IC offers developers two types of memory where data can be stored, as depicted in Figure 1. The first is the regular &#039;&#039;&#039;heap memory&#039;&#039;&#039; that is exposed as the Web Assembly virtual machine heap. This should be used as a scratch, temporary memory that will be cleared after any canister upgrade. The second type of memory is the &#039;&#039;&#039;stable memory&#039;&#039;&#039;, which is a larger memory (several orders of magnitude larger than the heap) used for permanent data storage. &lt;br /&gt;
&lt;br /&gt;
[[File:Canister memory 2.png|alt=|512x512px|Figure 1. The two memories that can be accessed by the canister smart contracts.|center|frameless]]&lt;br /&gt;
&lt;br /&gt;
==Orthogonal Persistence==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
use ic_cdk_macros::{query, update};&lt;br /&gt;
use std::{cell::RefCell, collections::HashMap};&lt;br /&gt;
&lt;br /&gt;
thread_local! {&lt;br /&gt;
    static STORE: RefCell&amp;lt;HashMap&amp;lt;String, u64&amp;gt;&amp;gt; = RefCell::default();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[update]&lt;br /&gt;
fn insert(key: String, value: u64) {&lt;br /&gt;
    STORE.with(|store| store.borrow_mut().insert(key, value));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[query]&lt;br /&gt;
fn lookup(key: String) -&amp;gt; u64 {&lt;br /&gt;
    STORE.with(|store| *store.borrow().get(&amp;amp;key).unwrap_or(&amp;amp;0))&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IC offers orthogonal persistence, an illusion given to programs to run forever: the heap of each canister is automatically preserved and restored the next time it is called. For that, the execution environment needs to determine efficiently which memory pages have been dirtied during message execution so that the modified pages are tracked and periodically persisted to disk. The listing above shows an example key-value store that illustrates how easy it is to use orthogonal persistence. The key-value store in this case is backed by a simple Rust HashMap stored on the heap by means of a thread-local variable. A RefCell is used to provide interior mutability. The example would also be possible without it, but mutating the thread-local variable would be unsafe in that case, as the Rust compiler cannot guarantee exclusive access to it.&lt;br /&gt;
&lt;br /&gt;
==Main Memory==&lt;br /&gt;
Canisters running on the IC are programmed either in Rust or Motoko. The canisters are then compiled down to web assembly (Wasm). All the variables and data structures defined in these higher-level languages are then stored in the Wasm heap. All accesses to data structures and variables defined in the higher-level languages are then translated to memory copy operations in Wasm (e.g., load, store, copy, grow). The Wasm main memory (also known as heap memory) has a maximum size of 4GiB, due to the 32-bit address space that backs the Wasm programs. The memory pages are persistent between calls to a canister (changes made by calls that throw exceptions are reverted, so these pages never enter an inconsistent state). However, they are reset when the canister&#039;s software bytecode is upgraded. Typically, canisters that need to be upgraded, serialize data in main memory to stable memory to perform upgrades. More precisely, because possible changes in data structures and in Wasm (and high-level language) compilers, the heap layout might change (i.e., data structure layouts) which could leave the canister in an unusable state when a canister is upgraded. Thus, the heap should not be used as a permanent memory, but rather as a (faster) scratch, temporary memory.&lt;br /&gt;
&lt;br /&gt;
==Stable Memory==&lt;br /&gt;
Next to the heap memory, canister developers can make use of the stable memory. This is an additional 64-bit addressable memory, which is currently 400GiB in size, with plans to increase it further in the future. Programs written in either Rust or Motoko need to explicitly use stable memory by using the API. This API offers primitives to copy memory back and forth between the Wasm heap and the stable memory. An alternative to using this lower level API directly is to use the stable structures API, which offers developers a collection of Rust data structures (e.g., B-trees) that operate directly in stable memory. Next to using the stable memory through stable data structures, a pattern often used by developers is to persist heap state between canister upgrades. This is achieved via serializing heap memory (or data structures), saving it to stable memory and applying the opposite operations (copying back and deserializing) when the upgrade is done.&lt;br /&gt;
&lt;br /&gt;
==Behind the scenes: Implementation==&lt;br /&gt;
To serve memory contents to canister smart contracts, the IC software stack has the following design. First, it is important to mention that every N (consensus) rounds, canister state (heap, stable memory and other data structures) are checkpointed on disk. This is called a checkpoint file. Whenever a canister executes messages after a checkpoint, all its memory resides in the checkpoint file. Therefore, all memory requested will be served from the checkpoint file. Memory modifications (i.e., dirtied pages in terms of operating systems) are saved in a data structure called the heap delta. The following paragraphs describe how this design enables orthogonal persistence.&lt;br /&gt;
&lt;br /&gt;
[[File:Screen_Shot_2022-12-01_at_14.30.58.png|512px|thumb|Figure 2. The memory faulting architecture which encompasses the checkpoint file and the heap delta.&lt;br /&gt;
.]]&lt;br /&gt;
&lt;br /&gt;
Any implementation of orthogonal persistence has to solve two problems: (1) How to map the persisted memory into the Wasm memory?; and (2) How to keep track of all modifications in the Wasm memory so that they can be persisted later. Page protection is used to solve both problems.The entire address space of the Wasm memory is divided into 4KiB pages. All pages are initially marked as inaccessible using the page protection flags of the operating system.&lt;br /&gt;
&lt;br /&gt;
The first memory access triggers a page fault, pauses the execution, and invokes a signal handler. The signal handler then fetches the corresponding page from persisted memory and marks the page as read-only. Subsequent read accesses to that page will succeed without any help from the signal handler. The first write access will trigger another page fault, however, and allow the signal handler to remember the page as modified and mark the page as readable and writable. All subsequent accesses to that page (both r/w) will succeed without invoking the signal handler.&lt;br /&gt;
&lt;br /&gt;
Invoking a signal handler and changing page protection flags are expensive operations. Messages that read or write large chunks of memory cause a storm of such operations, degrading performance of the whole system. This can cause severe slowdowns under heavy load.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Versioning: Heap Delta and Checkpoint Files==&lt;br /&gt;
&lt;br /&gt;
A canister executes update messages sequentially, one by one. Queries, in contrast, can run concurrently to each other and to update messages. The support for concurrent execution makes the memory implementation much more challenging. Imagine that a canister is executing an update message at (blockchain) block height H. At the same time, there could still be a previous long-running query that started earlier, at block height H-K. This means the same canister can have multiple versions of its memory active at the same time; this is used for the parallel execution of queries and update calls.&lt;br /&gt;
&lt;br /&gt;
A naive solution to this problem would be to copy the entire memory after each update message. That would be slow and use too much storage. Thus, our implementation takes a different route. It keeps track of the modified memory pages in a persistent tree data-structure  called Heap Delta that is based on Fast Mergeable Integer Maps. At a regular interval (i.e., every N rounds), there is a checkpoint event that commits the modified pages into the checkpoint file after cloning the file to preserve its previous version. Figure 2 shows how the Wasm memory is constructed from Heap Delta and the checkpoint file.&lt;br /&gt;
&lt;br /&gt;
====Memory-related performance optimizations====&lt;br /&gt;
&#039;&#039;&#039;Optimization 1:&#039;&#039;&#039; Memory mapping the checkpoint file pages.&lt;br /&gt;
This reduces the memory usage by sharing the pages between multiple calls being executed concurrently. This optimization also improves performance by avoiding page copying on read accesses. The number of signal handler invocations remains the same as before, so the issue of signal storms is still open after this optimization.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optimization 2:&#039;&#039;&#039; Page Tracking in Queries&lt;br /&gt;
All pages dirtied by a query are discarded after execution. This means that the signal handler does not have to keep track of modified pages for query calls. As opposed to update calls, queries saw the introduction of a fast path that marks pages as readable and writable on the first access. This low-hanging fruit optimization made queries 1.5x-2x faster on average.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optimization 3:&#039;&#039;&#039; Amortized Prefetching of Pages&lt;br /&gt;
The idea behind the most impactful optimization is simple: to reduce the number of page faults, more work is needed per signal handler invocation. Instead of fetching a single page at a time, the signal handler tries to speculatively prefetch pages. The right balance is required here because prefetching too many pages may degrade performance of small messages that access only a few pages. The optimization computes the largest contiguous range of accessed pages immediately preceding the current page. It uses the size of the range as a hint for prefetching more pages. This way the cost of prefetching is amortized by previously accessed pages. As a result, the optimization reduces the number of page faults in memory intensive messages by an order of magnitude.&lt;br /&gt;
&lt;br /&gt;
A downside of this approach is that prefetched page content needs to be compared with previous content after message execution to determine if a page was modified instead of relying on tracking write accesses via signal handlers.&lt;br /&gt;
&lt;br /&gt;
These optimizations bring substantial benefits for the performance of the memory faulting component of the execution environment. The optimizations allow the IC to improve its throughput for memory-intensive workloads.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* &#039;&#039;&#039;The Internet Computer project website (hosted on the IC): [https://internetcomputer.org/ internetcomputer.org]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=HTTPS_outcalls&amp;diff=8411</id>
		<title>HTTPS outcalls</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=HTTPS_outcalls&amp;diff=8411"/>
		<updated>2025-06-30T16:18:30Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/network-features/using-http/https-outcalls/overview}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=HTTP_asset_certification&amp;diff=8410</id>
		<title>HTTP asset certification</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=HTTP_asset_certification&amp;diff=8410"/>
		<updated>2025-06-30T16:18:02Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://learn.internetcomputer.org/hc/en-us/articles/34276431179412-Asset-Certification}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This content has moved to the learn hub ([https://learn.internetcomputer.org/hc/en-us/articles/34276431179412-Asset-Certification Asset Certification] and [https://learn.internetcomputer.org/hc/en-us/articles/34211943471892-HTTP-Gateway-Protocol HTTP Gateway Protocol]) and the [https://internetcomputer.org/docs/references/http-gateway-protocol-spec HTTP Gateway Protocol Specification].&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_voting_with_NNS_frontend_dapp&amp;diff=8409</id>
		<title>ICP voting with NNS frontend dapp</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_voting_with_NNS_frontend_dapp&amp;diff=8409"/>
		<updated>2025-06-30T16:17:00Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/governing-apps/nns/using-the-nns-dapp/nns-dapp-voting-on-proposals}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can choose the proposal types and proposal topics that you see and vote on—either directly or by [[How-To:_Set_your_neuron_to_follow_another_neuron|following other neuron stakeholders—using filters in the Network Nervous System dapp]]. For example, if you want to review and vote on all proposals that involve network participants such as data center identities and node operators, but aren’t interested in viewing proposals related to the current market value of ICP, as measured by an International Monetary Fund (IMF) Special Drawing Right (SDR), you can select the Participant Management topic filter and deselect the Exchange Rate topic filter.&lt;br /&gt;
&lt;br /&gt;
[[How-To:_Set_your_neuron_to_follow_another_neuron|To vote by following another neuron.]] &lt;br /&gt;
&lt;br /&gt;
To manually vote on proposals:&lt;br /&gt;
&lt;br /&gt;
1. Open a browser and navigate to the Network Nervous System (NNS) dapp.&lt;br /&gt;
&lt;br /&gt;
2. Click Login to connect using your Internet Identity.&lt;br /&gt;
&lt;br /&gt;
3. Verify your identification number, then click Login to authenticate using the device and authentication method you have registered.&lt;br /&gt;
&lt;br /&gt;
4. Click Proceed to access to the Network Nervous System (NNS) dapp.&lt;br /&gt;
&lt;br /&gt;
5. Click Voting.&lt;br /&gt;
&lt;br /&gt;
You can click any of the proposals listed to view information about the proposal, including a brief description of the proposal, a link for viewing additional information about the proposal, the number of votes that were cast to adopt or reject the proposal, and the votes cast by your neurons.&lt;br /&gt;
&lt;br /&gt;
6. Use the Topics, Reward Status, and Proposal Status filters to control the list of proposals displayed.&lt;br /&gt;
&lt;br /&gt;
For example, open the Topics list to see if there are any proposal topics that you want to include in the proposal list that are not currently displayed and open the Proposal Status to verify that you are viewing all open proposals.&lt;br /&gt;
&lt;br /&gt;
7. Click any Open proposal to see its details and the voting power for the neurons associated with your identity.&lt;br /&gt;
&lt;br /&gt;
8. Select the neuron identifiers with voting power that you want to use to cast your vote.&lt;br /&gt;
&lt;br /&gt;
9. Click Adopt or Reject to cast your vote.&lt;br /&gt;
&lt;br /&gt;
For more information about maturity and spawning new neurons, see the following articles:&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/dfinity/earn-substantial-voting-rewards-by-staking-in-the-network-nervous-system-7eb5cf988182 Earn Substantial Voting Rewards by Staking in the Network Nervous System]&lt;br /&gt;
&lt;br /&gt;
*[https://medium.com/dfinity/understanding-the-internet-computers-network-nervous-system-neurons-and-icp-utility-tokens-730dab65cae8 Understanding the Internet Computer’s Network Nervous System, Neurons, and ICP Utility Tokens]&lt;br /&gt;
&lt;br /&gt;
*[https://medium.com/dfinity/getting-started-on-the-internet-computers-network-nervous-system-app-wallet-61ecf111ea11 Getting Started on the Internet Computer’s Network Nervous System App &amp;amp; Wallet]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_voting_options&amp;diff=8408</id>
		<title>ICP voting options</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_voting_options&amp;diff=8408"/>
		<updated>2025-06-30T16:16:33Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/governing-apps/nns/using-the-nns-dapp/nns-dapp-voting-on-proposals}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voting an in important part of ICP governance as it is is how the community controls the Internet Computer.&lt;br /&gt;
&lt;br /&gt;
==NNS Rewards==&lt;br /&gt;
&lt;br /&gt;
Every day the NNS mints [[NNS Rewards]] and these rewards are apportioned to those neurons who voted that day.&lt;br /&gt;
&lt;br /&gt;
==Viewing Proposals==&lt;br /&gt;
&lt;br /&gt;
Two most common ways of viewing proposals are:&lt;br /&gt;
&lt;br /&gt;
* [https://dashboard.internetcomputer.org/governance Internet Computer Dashboard: Governance]&lt;br /&gt;
* &#039;&#039;&#039;Voting&#039;&#039;&#039; tab on [https://nns.ic0.app/#/accounts NNS Frontend dapp]&lt;br /&gt;
&lt;br /&gt;
==How to Vote==&lt;br /&gt;
&lt;br /&gt;
There are two forms of voting: manual voting and following neurons.&lt;br /&gt;
&lt;br /&gt;
=== Manual Voting===&lt;br /&gt;
Users can vote on proposals manually by using the NNS Frontend dapp, see: [[ICP voting with NNS frontend dapp]].&lt;br /&gt;
&lt;br /&gt;
===Following neurons===&lt;br /&gt;
A neuron can follow any neuron. See [[How-To:_Set_your_neuron_to_follow_another_neuron|instructions]]. See [[Editing following for neurons]]&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Managing ICP holdings]]&lt;br /&gt;
* [[ICP custody options]]&lt;br /&gt;
* [[ICP staking with NNS frontend dapp]]&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Editing_following_for_neurons&amp;diff=8407</id>
		<title>Editing following for neurons</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Editing_following_for_neurons&amp;diff=8407"/>
		<updated>2025-06-30T16:15:58Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/governing-apps/nns/using-the-nns-dapp/nns-dapp-following-other-neurons}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=How-To:_Set_your_neuron_to_follow_another_neuron&amp;diff=8406</id>
		<title>How-To: Set your neuron to follow another neuron</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=How-To:_Set_your_neuron_to_follow_another_neuron&amp;diff=8406"/>
		<updated>2025-06-30T16:15:39Z</updated>

		<summary type="html">&lt;p&gt;Jessie.mongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#externalredirect: https://internetcomputer.org/docs/building-apps/governing-apps/nns/using-the-nns-dapp/nns-dapp-following-other-neurons}}&lt;/div&gt;</summary>
		<author><name>Jessie.mongeon</name></author>
	</entry>
</feed>