SNS deployment and upgrades | design proposal

Hi all!

I am back with a new design proposal for the next stage of the service nervous systems (SNSs). Let’s use this thread to discuss how SNSs should be deployed and upgraded. This is our proposal:

Objective

Similarly to how the Network Nervous System (NNS) is the open tokenized governance system that controls the Internet Computer blockchain (IC), service nervous systems (SNSs) are algorithmic DAOs that will allow developers to create decentralized, token-based governance systems for their dapps.

Decentralized control and tokenization enables the introduction of new incentive systems and use cases that have the potential to set dapps apart from traditional applications. We refer to this article for more background on how SNSs will empower dapps to leverage the full potential of the IC.

The goal of this discussion is to introduce a concrete first design for how SNSs can be deployed and upgraded.

Background & context with other projects

We presented the first proposed SNS design in October 2021. The community’s feedback was that they wish for a less complex SNS design that also leaves more freedom for developers and SNS communities to configure a DAO to their needs. Moreover, some developers mentioned that they have a particular DAO or use case in mind and are only interested in a ledger or governance canister implementation, which they plan to integrate with existing canisters / dapps.

The goal of SNSs is also to eventually provide an open governance solution “on the press of a button”, where even users that are not experienced developers can get an SNS as a system functionality that is automatically upgraded and maintained as part of the IC.

Motivated by this, we proposed to release smaller SNS features in stages, such that the different parts or canisters can be used by the community early. This new overall approach has been adopted in a motion proposal in December 2021.

So far, the following stages have already started:

  1. Improve the NNS ledger canister so that it can be used for any tokens, e.g., in SNSs. This is scheduled for the Titanium release on the roadmap.
  2. Implement a governance canister. The proposed design for the governance canister has been presented and discussed in this forum thread and been approved by the community in this motion proposal. In addition, this stage will also deliver a root canister that is needed for governance upgrades. This implementation has started and is ongoing.

The design presented here is the next proposed stage:

  1. Tooling and support for the deployment and upgrade of SNSs. At a high level, in this design, a SNS consists of a ledger canister, a governance canisters, and a root canister that are mostly from the previous two stages but may require small changes. In addition, this stage entails changes to the NNS canisters and a new canister that helps with deploying SNSs.

Other SNS features that we envision going forward are frontend support, support for initial token distribution, integration with the community fund, etc.

Proposed design for deploying and upgrading SNSs

The SNS Canisters

We propose that in this initial design an SNS consists of three canisters:

  1. the governance canister which enables decentralized decision making,
  2. the ledger canister which determines for a SNS-specific governance token the balances and transactions, and
  3. the root canister which is responsible for upgrading the other SNS canisters and the dapp that the SNS controls.

Canister code and blessed deployments

One of the key features of the IC is that it can continuously be upgraded by proposals through the NNS. The same is true for the NNS canisters themselves, which have been upgraded many times since genesis. Similarly, we propose to start with one version of each of the SNS canisters, which can then be continuously evolved.

As with the NNS, the code of all SNS canisters will be public. That is, anyone can deploy any version of the canisters at any point in time. However, it may be that not all canister versions can be upgraded to all other canister versions without breaking some functionality, e.g., due to incompatibility during state migration. For example, it is possible that the governance canister can be upgraded from version v1 to version v2 and from version v2 to version v3, but that it cannot be upgraded from version v1 to version v3 directly. Moreover, it is possible that newer versions of one canister may not be compatible with some older versions of a different canister, e.g., a new ledger version is not compatible with an old version of the governance canister.

Therefore, we propose to have blessed SNS deployments in the NNS registry. These new entries in the NNS registry then define

  1. which versions of the SNS canisters are compatible and
  2. from which deployment one can safely upgrade to which next deployment.

The IC community would thoroughly test these facts for some releases and “bless” this information in the registry by proposal. SNSs can then just follow the suggested path of upgrades and know that all the relevant upgrades along the way have been well-tested.

Two paths to deploy & upgrade a SNS

With the suggested design, there are at least two possibilities for how to deploy and continuously upgrade a SNS:

  1. A SNS that is a system functionality, which is automatically maintained by the IC and where the SNS canisters are hosted on a new SNS subnet. To deploy an SNS, a user sends a command to the IC that defines the initial settings of the SNS. Afterwards, the IC will ensure that the SNS is kept on the latest available version. This has the advantage that the SNS community does not need to take any actions to keep the SNS canisters up to date (e.g., when bugs are fixed) nor do they need to understand the details of the canisters’ implementation. Especially, the SNS canisters are automatically upgraded following the blessed deployment path. To achieve better security guarantees through higher replications, the new SNS subnet will have more nodes than application subnets currently do.
  2. A SNS that is self-deployed, manually upgraded, and hosted on an application subnet. Any SNS community can choose to deploy the SNS code, which is open source, on an application subnet. They can then choose to follow the blessed upgrade path or deviate from this path, e.g., leaving out some versions, or even modify the canisters’ code in a completely different way. In this option, canister upgrades require active actions of the SNS community (i.e., the submission of a proposal) and the SNS community has to ensure that the upgrades are secure. This includes ensuring that alternative canister versions are compatible and that upgrades to newer versions do not break any functionality. Application subnets currently have less nodes than the SNS subnet and are therefore less secure.

These two possibilities allow SNS communities to choose between using SNSs that are provided as a service by the IC, where maintenance is as automated as possible, and SNSs that have full flexibility of how they can be evolved. Because of the fact that the possibilities for Option 2 are unbounded and that it is likely that this option will mainly be used by those who want to explore new designs themselves, we focus on Option 1 in the remainder of this design proposal.

Proposed deployment & upgrade process

The following canisters, on three different subnets, are involved in the proposed design:

  • On the NNS subnet, the registry canister holds the blessed deployment path, as described above, which includes the hash of the SNS canisters’ wasm modules.
  • On a new SNS subnet, a new SNS wasm module canister holds the actual SNS canisters’ wasm modules.
  • On an application subnet, there is a cycles wallet controlled by a developer that wants to initialize a SNS.

The following protocol describes the steps to initialize a SNS:

  1. Using the cycles wallet, the developer calls the SNS wasm module canister to deploy an SNS. They specify the initial parameters that the SNS should have (e.g., initial accounts on the ledger and initial neurons, token name etc). Also, along with the call, they send an initial cycle amount to pay for the SNS.
  2. Upon receiving this call, the SNS Wasm module canister checks if the chosen initial parameters are well-formed (e.g., there are ledger accounts for all neurons etc) and if there is still space for more SNSs on the subnet.
  3. If all these checks are successful, the SNS wasm module canister initiates the deployment of the three SNS canisters governance, ledger, and root.

The following describes how the IC automatically maintains SNSs as part of the system:

  1. The NNS community can at any time bless new SNS deployments.
    a) To do so, anyone can make a proposal in the NNS which, upon adoption, adds a new blessed SNS deployment to the registry. As mentioned above, this registry entry refers to the SNS canisters by specifying the hash of their wasm modules.
    b) Anyone can then upload the actual canister wasm modules to the SNS wasm module canister on the SNS subnet. The SNS wasm module canister will only accept wasm modules for which the hash is mentioned in a blessed deployment on the registry.

  2. The SNSs on the SNS subnet regularly query the registry to learn if there are new blessed deployments. If this is the case, they pull the respective wasm modules from the SNS wasm module canister and initialize an upgrade to this new version.

User experience:

We propose to integrate the necessary calls that a user is expected to make to initialize an SNS into dfx. As many developers are already familiar with the tool, we think this is a good solution for the first version.

While we envision a frontend that makes this functionality available to an even wider range of users, we propose to solve this in a separate design proposal.

Control

New SNS wasm module canister

We propose that the SNS wasm module canister is controlled by the NNS root canister, similarly to the canisters on the NNS.

SNS canisters

Within each SNS, we propose that the root canister controls the governance and ledger canister and that the governance canister controls the root canister. This means that whenever an update is triggered, the respective controlling canisters are responsible for upgrading the controlled canisters.

Dapp

The main motivation for SNSs is of course that they can control dapps in a decentralized manner. We deliberately did not include the dapp in the above design to allow for different use cases. At any point after the SNS exists, the dapp’s control can be changed to the SNS.

In particular, this allows for the following use cases:

  • Developers who control an existing dapp can initialize an SNS and when it exists, they can add the SNS as the dapp’s controller and remove themselves from the set of controllers.
  • Developers may choose to add a SNS as the dapp’s controller but, in the beginning, also remain controllers themselves until they gain sufficient confidence that the SNS works, at which point they can remove themselves as controllers.
  • Developers can set up an SNS without an existing dapp. They can then, for example, use the SNS to get initial funding, vote on what the dapp should look like etc, and then at a later point in time create the dapp and assign the control to the SNS.

The new SNS subnet

As stated above, we propose that the SNS canisters are deployed on a new subnet. We next present more details regarding the design of this subnet.

Subnet type

Currently, there are system subnets (e.g., the NNS) and application subnets. We propose to introduce a third subnet type for the SNSs.

The reason for this is that while we propose similar configurations for the SNS subnet as for the system subnets, the canisters on the SNS subnet should pay cycles (which the NNS canister do not).

Replication

As SNSs are security critical applications and as there are dependencies between the SNS subnet and the NNS (the NNS controls the SNS wasm module canister), we propose that the new subnet should have 34 nodes.

Cycle costs

While we are still working on a concrete proposal, the high level idea is that it should be more expensive to have canisters running on the SNS subnet than on an application subnet.

The main reason for this is that the subnet has a larger number of nodes than the application subnets.

Scalability

We propose to start with one SNS subnet that can host around 10-15 SNSs according to initial estimations. If there is more demand, a new SNS subnet can be created the same way as other new subnets can be added to the IC, by proposals over the NNS. On this new subnet, the NNS can then deploy a new SNS wasm canister, and the same protocols as described above can be done. Following the same process, more and more SNS subnets can be created.

Security

We consider this to be a security critical feature, as the upgrades of dapps and the value of associated governance tokens are at risk if there are vulnerabilities. We thus already initiated a design review by DFINITY’s security team and plan to also have thorough security code reviews.

Alternatives considered

Some different approaches that we could have taken and why we decided against them.

  • Why not hold off on releasing until we have all SNS features, including initial token distribution etc., implemented?
    As argued above, we decided against this as it seemed to be a wish from the community to be able to use and experiment with the individual components as soon as possible.
  • Why not omit the root canister and just have two canisters?
    The reason for this is that the governance canister cannot upgrade itself. Upgrading a canister involves stopping the canister, installing the new code, and starting it again. This cannot be triggered by a canister itself. Moreover, we don’t believe it is a good idea to make the ledger canister more complex by adding this functionality to the ledger canister. Therefore, similarly to the NNS, we propose to have a root canister.
  • Why is the root canister not only controlling the governance canister and the governance canister controls all other canisters?
    There seems to be no strong reasons for not choosing this alternative. As both options seemed equally good, we preferred the above proposed control hierarchy as this is closest to what we have in the NNS and thus closer to what we have already tested and used extensively.
  • Why not place the SNS wasm module canister on the NNS?
    The reason for this is that currently the crossnet message limit is smaller than the size of the canister wasms that we need to communicate from the SNS wasm module canister to the SNS canisters when they are upgraded. While we are planning a feature to compress canisters, we are not sure when this feature will be finished and therefore propose to go with this solution for now.
  • Why not have the SNS wasm module canister control all SNS canisters and notify them or start upgrades when new canister upgrades are available (i.e., implement a “push” rather than a “pull” mechanism for upgrades)?
    For any canister that controls another canister that can either be on a malicious subnet or have bugs, there is the risk that the controlling canister cannot be stopped and thus not be upgraded. This is the case both for a canister that directly controls a buggy canister and for a canister that controls such a canister via a longer chain of control (i.e., A controls B, B controls C, and C is buggy). As we absolutely want to avoid that we cannot upgrade the NNS canisters anymore, we propose to avoid any control chain from the NNS to the SNS canisters as the latter necessarily need to call out to dapp canisters on less secure application subnets. Again, we are working on a more general solution for this problem, but suggest a design that is not dependent on this solution for efficiency reasons.

Risks and mitigations

This feature involves many different layers of the IC stack. It requires changes to existing canisters, the implementation of new canisters, the realisation of a new subnet type, and new communications between canisters on different subnets.

To avoid incompatibilities between the different components and to mitigate the risks specific to different components, we included experts from many different teams in the design phase.

Furthermore, we mitigate the risk of unforeseen findings by involving the testing and security experts early in the process.

Community conversation & timeline

We propose the following approach to discuss the design of this feature:

  1. Feb 10th-15th: Design discussion on this forum thread
  2. Feb 15th: Community conversation about the topic
  3. Afterwards: start implementation of the design, potentially adjusted with feedback from Steps 1 & 2

There has already been a motion proposal on the general idea of SNSs that has been adopted on Dec 21, 2021. We consider this design as a concrete, detailed suggestion on how to realize parts of this larger design / idea. Therefore, we propose not to submit a separate motion proposal for this design and rather discuss it in the forum here and in the community conversation. Apart from feedback on the design, we are also happy to get feedback on and discuss this approach.

18 Likes

Hi @lara , thank you so much for this excellent summary! I’m looking forward to seeing what people bring to this discussion.

4 Likes

Just want to confirm, each SNS will be capable of controlling multiple canisters correct? I imagine that the root canister will be capable of becoming the controller for as many canisters as desired. Then the governance canister could receive proposals that upgrade any canister which is controlled by the root canister. Correct?

And about token distribution by the ledger canister, I’m hoping there will be support for different supply and minting schemes. For example, in a dapp I’m envisioning there will not be a fixed supply, and the SNS will need to be able to mint tokens based on specific user actions. There will also need to be burning.

6 Likes

Will there be the option to convert an SNS on an application subnet to an SNS on the SNS subnet and vice versa?

I can imagine a scenario where an SNS starts off running well with the default code and configuration capabilities, and then the community deciding that they want to venture off with some experiments. And then I can imagine those experiments being upstreamed into the blessed SNS code, and thus that SNS might want to convert back to the SNS subnet.

1 Like

@lara are there any plans to generalize the voting options to allow them to be customizable?

The options we have for proposals in the NNS today could be represented as the sum type Adopt | Reject but I can anticipate wanting to make proposals with something different.

For questions that only need one answer like “How should we refer to Bitcoin on the IC?” we could use something like ckBTC | icBTC | Other Text

It also works when asking questions like, “In which order should we work on things?”. Here we could use Feature1 | Feature2 | Feature3 | Feature4 | Other Text

1 Like

Every time I read one of these proposals, I get this strange itch to purchase and stake more ICP… can’t explain it.

11 Likes

I just went over the design—I think it’s sensible. The “alternatives considered” section was especially illuminating.

A couple of questions:

  1. This design proposes two paths to deploy/upgrade a SNS: “system-deployed” and “self-deployed”. Am I correct in concluding that the whole concept of a blessed deployment is only necessary because we want to support self-deployed SNSs, and that if we hypothetically only supported “system-deployed” SNS then we wouldn’t need a blessed registry (or even SNS wasm module canisters) at all? For example, the NNS doesn’t have the concept of blessed deployments, presumably because there’s only one canonical NNS deployment at any time (in contrast to SNS, where there could be multiple SNSs, some system-deployed, some self-deployed, each potentially running a different version).

  2. Why is a SNS governance canister a controller of a SNS root canister? On the NNS, I believe the only controller of the NNS root canister is the NNS lifeline canister. The NNS governance canister is still able to tell the root canister to upgrade canisters without being its controller, I thought.

As we absolutely want to avoid that we cannot upgrade the NNS canisters anymore, we propose to avoid any control chain from the NNS to the SNS canisters as the latter necessarily need to call out to dapp canisters on less secure application subnets.

  1. I don’t see any control chain from the NNS to SNS canisters here in this design. The NNS can bless new SNS deployments by adding new wasm hashes to the registry canister, but a separate client will then upload the actual canister wasm modules to the SNS wasm module canister. Or were you planning for that client to be the NNS itself upon proposal adoption?

  2. When will the SNS ledger canister design be made available? That was actually listed as the first stage here. My guess is that the ledger canister design will be the most controversial, and will probably need the most time to discuss.

Thanks for sharing!

1 Like

Hi @lastmjs, thanks for the questions.

each SNS will be capable of controlling multiple canisters correct?

Correct. Additional canisters can also be “added”, i.e., set to also be controlled by the SNS, but just setting their controller to the SNS root too.

And about token distribution by the ledger canister

The current thinking is that in the MVP, i.e., the very first version of the SNS, there will be no voting rewards and no minting / burning. I agree with you that this should be made flexible (this is why it should be thought through and we suggest to rather do it thoroughly in a follow up than just introduce a default that people might not want now). If you think this is something that is needed urgently, it would be good to understand so that we can take this into account for prioritising next features.

2 Likes

It is not intended that this is possible, at least in the first version.

Two concerns that I see with allows this:

  1. I would say it is hard to define good criteria for what an SNS needs to satisfy to be allowed to “go back on the blessed track”. Any intermediate updates that did not follow the blessed upgrade path might have introduced some inconsistencies or bugs, so it might be problematic to put those in the same category (regard “as secure / as well tested”) as SNSs that always followed the well-tested path.
  2. Currently the vision is that on the SNS subnet there are only SNSs that follow the automatic upgrades, i.e., follow the blessed upgrade path. This ensures that there are no canisters on this subnet that have (known) bugs for too long, as they all upgrade regularly. Also, with this we can ensure that all canisters “follow the same rules”, e.g., don’t use up too much memory etc. Having canisters on this subnet that divert from this can be a security risk. One could say that one could nevertheless allow SNSs to switch between the self-upgrade and automated upgrade version but that they have to be moved to a new subnet for this. This however might be quite some effort.
2 Likes

Hi @paulyoung , thanks for the question!

For the first version, we envision yes / no votes as in the NNS.

Certainly, we can think about other voting schemes in the future, as the SNSs will continuously be evolved like other canisters on the IC!

I think when introducing the possibility for new voting schemes, there are a few things that we have to consider carefully. The following come to mind spontaneously:

  • we have to define precisely what the different voting schemes mean. I.e., in your example “How should we refer to Bitcoin”, would each voter only have one vote? Or can one assign weights to each possible answer?
  • we might have to bound the number of possible answers
  • we would have to think about how following would work for these new voting schemes (or maybe just say that following only kicks in for the yes / no votes?)
  • once we have a frontend, we would have to think about how we can distinguish these types of proposals from the yes / no ones so that we can have user friendly interfaces for reading and voting on such proposals.
3 Likes

Thanks for reviewing the design so carefully.

Let me try to answer your questions:

  1. Good question. Let me answer the questions regarding whether we need the blessed deployments and the SNS was module canister separately:
    a) I think even if we only had system-deployed SNSs, there are some advantages to bless the deployments. I think the main reason for this is that in contrast to the NNS deployment, there are multiple SNSs. So it could for example be that a new version is blessed, that some SNSs auto-upgrade, but that the upgrade fails for some other SNSs (for whatever reason). Having the blessed deployments, the SNSs where something went wrong can then e.g., “try again” or we can bless alternative paths to help them get back on the “blessed path”. I agree though that there might be alternatives without this, but I like that it also has the extra advantage of making the blessed path available for those who want to self-deploy.
    b) you also ask “… we hypothetically only supported “system-deployed” SNS then we wouldn’t need a blessed registry (or even SNS wasm module canisters) at all”. I would say for the SNS wasm module canister it is the opposite. If we only supported the self-deployment, I think we would not need it, as anyone on such an SNS would build the new canister wasm and include it in a proposal to upgrade the SNS (i.e., include it in an ingress message). We only have the canister for the system-upgrades: there, we don’t want a separate ingress message for each SNS that is upgraded, we want things to be as automatic as possible. Therefore, we put the canister wasms once in this new canister and the SNSs can then just “take” the version from there.

  2. This is correct. Especially, “The NNS governance canister is still able to tell the root canister to upgrade canisters without being its controller” is also correct. The reason for governance to be root’s controller is not for upgrades of other canisters but in case the root canister has to be upgraded itself. Then, we need a canister that can stop root, install the new canister code, and restart root. You are right that on the NNS we have the lifeline canister for this (adding a little more independence, e.g., the lifeline is also written in motoko). We felt that this extra indirection is not needed on the SNS and that the governance canister could just take on this job of upgrading root. Especially, once could say that if something goes terribly wrong with the NNS this is still worse that if something goes wrong with the SNS as in the latter case we might still use the NNS to recover the SNS subnet.

  3. “I don’t see any control chain from the NNS to SNS canisters here in this design.” Right, I agree that this should be the case. The “we absolutely want to avoid…” is part of the reason why we did not choose the alternative of having the SNS wasm module canister control the SNSs, as with this alternative this requirement would not be met. So to be clear: yes, in the current design there should not be any control chain from the NNS to the SNS canisters. Do you have a suggestion how I can make this clearer in the explanation of the last alternative?

  4. The vision here is to generalise the NNS ledger canister so that it can be used with other kinds of tokens and then use this for the first version of the SNS. This is already being implemented atm. I am not sure where the changes will be presented, but can ask internally.

2 Likes

Eventually this might be nice but I don’t think it’s a high priority, thanks for the explanation

1 Like

So how will the initial supply be created? And where will it go? And it will have to be fixed and all created right at the beginning?

I would think that whoever deploys an SNS can choose the initial accounts on the governance canister and on the ledger.
Thus, they could choose how many tokens are initially owned by which account on the ledger.
This will both define the initial supply and where these tokens are.
I could imagine that an SNS could e.g., have some tokens in the account that is owned by the SNS governance canister or the dapp canister, which can then be distributed as rewards or used for other means, decided by SNS proposals.

But I can imagine some use cases for which one might want minting / burning from the start. So in these cases, I guess the communities can either choose to add this functionality themselves (and got the self-deployment path) or to wait a bit until new SNS features are also available.

2 Likes

Minting and burning are crucial to the plans I have for the SNS. Locking into a fixed supply right away is problematic for me. I could possibly work with a fixed supply and allow the SNS to give our tokens from that fixed supply, but not elegant.

I don’t know what other people are planning.

3 Likes

I’d also be interested in some clarification around fixed token supplies. I suppose people who aren’t expecting minting and burning activity may be satisfied with this (I’d be interested in hearing about anyones plans that don’t require these mechanisms btw), but I’d prefer to at least have the option - early on - for a variable token supply.

3 Likes

Thanks, this is useful feedback.
Are you able to elaborate a bit on what you would need from minting / burning (just in case you want to share)?

I.e., would you just require some fixed operation (such as rewards in the NNS) that can mint, or are you looking for something like a method “mint X tokens now” that can be called by the governance canister, or even something that just automatically mints a certain number of tokens per time period to some account ?

2 Likes

Thanks for this feedback!

I think at the moment there is not much more clarification that I can provide, rather than stating that this is probably not feasible for the initial version of SNS governance canister that is also discussed here.

But as already stated in my other answers, it is valuable to get the feedback that there is some need for this, so that we can take this into account when prioritising next steps.
Also, in case you have particular use cases in mind for minting / burning, I would be happy to learn those!

1 Like

What I have in mind is the governance canister being able to mint/burn anytime at will. This capability will be used to issue tokens when users have performed certain actions, and those tokens will be minted and added to the supply in real time. Other user actions will cause tokens to be burned, removing them from the supply in real time.

I also think it would be valuable to have a “mint X token now” governance method, so that proposals can be made to pay out ad hoc.

The projects I have in mind are probably all going to have a variable supply, minting and burning programmatically based on user actions and proposals.

4 Likes

Thanks for clarifying for 1 and 2. I think we’re basically on the same page now.

The “we absolutely want to avoid…” is part of the reason why we did not choose the alternative of having the SNS wasm module canister control the SNSs, as with this alternative this requirement would not be met.

I think the confusion lies when you say that “with this alternative this requirement would not be met”.

Let’s say the SNS wasm module canister controls the SNS canisters. How does the NNS control the SNS wasm module canister? Is it when a new deployment is blessed? For example, when a blessed deployment proposal is adopted, the NNS will not only update the hashes in the registry canister but also upload the actual wasm modules to the SNS wasm module canister (on each SNS subnet)?

  1. The vision here is to generalise the NNS ledger canister so that it can be used with other kinds of tokens and then use this for the first version of the SNS. This is already being implemented atm. I am not sure where the changes will be presented, but can ask internally.

Oh interesting, I had assumed you would share the ledger design proposal on the forum, like you have done with the SNS governance canister and the deployment/upgrades in this post. In my mind, the ledger design proposal might be the most controversial, not the least.

1 Like