Regarding NNS controlling application canisters

Hi ICP folks,

I am writing this on behalf of DFINITY as our current stance:

TLDR:

DFINITY proposes there be a wider and deeper community conversation regarding having the NNS control user canisters. Particularly, what good practices should be, what community norms may be good, and what (if any) code updates there may be necessary. While that happens, the default DFINITY position will be to vote REJECT (instead of ABSTAIN) on most updates for NNS-controlled canisters. DFINITY will only vote yes for those code updates it has verified.

Background:

Any developer can choose to have their canister set the NNS as its own controller. Recently, there was a thread where a long time ICP developer Austin was assigning their canister to be controlled by the NNS. This is a consequence of two facts about the IC:

  1. Canisters can change controllers.

  2. NNS (Network Nervous System) can control canisters.

In fact, the NNS controls many canisters. Most canisters the NNS controls are protocol-level canisters such as the ledger canister or governance canister. DFINITY, as its community role in ICP as a major contributor, and other parties audit any code updates to these canisters and vote appropriately.

This situation made us aware that we needed to clarify our own thinking to ourselves and externally.

The Catch:

But what happens when there are more and more non-protocol level canisters? If Alice and Bob each designate the NNS to control their canister, and there are proposals to update those canisters code… should DFINITY audit that code too?

DFINITY has decided that (as a default position) it cannot be responsible for auditing all code updates to user-level canisters.

Ok, so the next question is: “could DFINITY abstain?”

Here is where we hit the real catch: There are two security issues emerging from this:

  1. Protocol-level security concern with DFINITY default voting ABSTAIN

A malicious canister could set NNS as controller, submit proposals, let them be unresolved until they time out, and through a series of actions block some of the emergency capability of the NNS to do emergency updates (if needed). It’s a complex path, yes, but a possible one for an attacker. @lara explains this risk here: Using NnsCanisterUpgrade Proposal types - #13 by lara

  1. Canister-level security concern with DFINITY default voting ACCEPT

DFINITY could default accept all changes… but that may lead to DFINITY inadvertently voting for malicious proposals to canisters.

Our Current Thinking:

Given the current landscape…

  1. We at DFINITY will default vote REJECT on proposals for canisters controlled by the NNS unless it has audited them… and DFINITY will rarely audit non-protocol level canisters.
  2. We at DFINITY recommend that users refrain from designating NNS as controllers at this time, but of course recognize any users can choose to do this.

As Austin noted in this thread, “DFINITY did recommend that we NOT start submitting canisters to NNS control.”

Next Steps:

Over the past three years, the utilization of this feature has been minimal. However, as it gains traction, we are starting to observe emerging patterns.

This prompts a discussion about how we should adapt our governance to facilitate NNS controlling canisters in a manner that aligns with our vision.

Possible avenues include:

  • Not changing the code at all, but instead establishing community guidelines or norms for voting on these matters.

  • Exploring alternative options that better serve our community and protocol.

We encourage community input on this topic, as your perspectives are crucial in shaping our path forward. We want to hear from you.

6 Likes

Why would a developer need to have the NNS control their canisters? Is it because developers want to minimize trust in their projects as much as possible while retaining the possibility for upgrades? It seems like there is a need for decentralizing control of canisters by developers who don’t want to launch a DAO. I think there is a business opportunity here to create an SNS DAO whose job is to manage control of canisters for developers throughout the ecosystem.

1 Like

would Juno be a good fit for this?
Seems like it’s not really a NNS thing for most people. Always thought it might be a short term solution.

I think the @Sneed team is developing some DAO tooling, additionally Orbit is providing some multisig canister control functionalities. This is also something that is floating around.

1 Like

The issue in this particular case is that the NNS Subscription utility asks for an infinity icrc2 approval to spend the users funds. As a developer, I do not want access to upgrade the canister and steal user funds which I can do if I remain the controller. For an SNS, first you have to jump through all the hoops, raise funds, etc, and then the ability for someone to steal user funds is only bounded by the market cap of your SNS.

Since this is a general purpose public utility with no real profit motive other than the small public goods donation, it is unlikely to draw much investment.

The next two levels of trust are

Highest: black hole, but you can never upgrade

NNS: has secured $2B+ for 3+ years, has a facility for upgrades

Thus, it would be really nice to hitch a ride with the security level provided by the NNS.

1 Like

It has taken a week for me to clear the decks enough to get back to this issue, so I’m sorry for the delay.

I understand DFINITY’s position, but I would like to clarify a couple of things. This post is split into:

1. Counterpoint
2. Conundrum
3. Actions needed

1. Counterpoint

The NNS Subscription Utility canister that we would like to upgrade is NOT a user-level canister any more than the CycleLedge, ckBTC, ckETH, EVM RPC, or Exchange Rate Canisters. It is a general-purpose, protocol-level open Internet utility service designed and architected to be integral to the Internet Computer’s functionality as a valid financial platform. Further, it can be argued that it provides protocol-level functionality that should have been in the ICP ledger on Genesis Day. It is NOT INTEGRAL to the protocol functioning though, and other canisters like this that DFINITY has built are now called “Application Canisters” and are governed by the “Application Canister Management” Topic:

For this topic, I’m going to call them Protocol Support Canisters as things like the Exchange Rate Canister, the ckX canister, Cycles ledger, etc are not absolutely necessary, but they provide key support to the protocol that makes it more useful and it just fundamentally makes sense to have just one of these. There is no profit margin to be made on these kinds of utilities and they just generally work better when there is one of them that everyone agrees to use.

So the NNS Subscription Utility Canister is, I would argue, a Protocol Support canister that enables long-term subscriptions for Open Internet Services based on ICRC 1/2/3 standards. It provides a trusted smart contract that can only be changed by the governing controller(in this case the NNS is what we want because it provides the best security). You need this because if you ICRC-2 approve infinity tokens that you intend to pay on a per-month basis until such time as you want to cancel the service to a closed source canister, a third-party canister controlled by “some dude”, or even an SNS controlled canister with a low market cap, the controllers can upgrade the canister and take all your funds. This functionality could be in each ledger canister, and with ICRC-79 there is now a way to include a native subscription in your ledger canister (watch the skies!), but it is really nice to have one Lego brick everyone can use and Ledger authors can keep that code out unless they really need it(and don’t need to pay audit and maintenance costs).

2. Conundrum

It is true that DFINITY has not audited the code and I can understand DFINITY not wanting to audit code it did not write and that not scaling even if they did, but until we have a solution where DFINITY will do something other than default reject, NO Protocol-Support(ie 0, Can’t Happen) code can be built or deployed by anyone but DFINTY unless you want bootstrap your own security model that is as good or better than the NNS while also trying to build a system. This does not scale.

What I will say is that it is the community’s responsibility to organize itself enough to decentralize the Application Canister Management topic and not DFINITY’s.

If we look at the last accepted Application Canister Upgrade request we see this pattern:

Going from 2% to 99.4% with one vote(Dfinity) is a steep hill to climb. Digging in it turns into a mountain when you look at the details:

image

  • DFINITY: +14.915212%
  • ICA: +4.83945838%
  • Synapse.vote (original): +0.00000487%
  • ICPMANUAL: +0.00000066%
  • Jerry Banfield: +0.00163676%
  • GEEKFACTORY: +0.01192052%
  • Smaug’s Neuron for Retail Investors: +0.00126456%
  • OpenChat: +0.04553785%
  • Paul Young: +0.0000047%
  • ICLight.io: +0.00000407%
  • Isaac Valadez: +0.00013205%
  • John Wiegley: +0.00001991%
  • Synapse.vote (NEW): +0.00000055%
  • ICPL.app: +0.00001035%
  • WaterNeuron: +0.135698%
  • Nicolas.ic: +0.00000047%
  • Anvil: +0.00000059%
  • CryptoIsGood: +0.00034709%
  • Sonic AMM: +0.00000438%
  • CodeGov: +0.00000027%
  • Arthur’s Neuron (used to be cycle_dao): +0.00000607%
  • RawTech Venture: +0.00000582%
  • 8yeargangDAO: +0.00004331%
  • Gold DAO: +0.03362146%
  • The Accumulators’ Neuron: +0.00061717%
  • ICDevs.org: +0.00050434%
  • ICP Hub Bulgaria: +0.00000212%
  • $STACK: +0.00000044%
  • ysyms: +0.00139313%
  • nICP by WaterNeuron.fi: +0.16313314%
  • Bob Bodily: +0.00000153%
  • Wenzel Bartlett: +0.00000093%
  • Daniel Radu: +0.00000711%
  • David Fisher: +0.00000049%
  • Kyle Langham: +0.00000049%
  • tiago89: +0.00000054%
  • Adnan - MonkeyCruise: +0.00000087%
  • Andrew Weed: +0.00000328%
  • The ICP Maximalist: +0.00000049%
  • Roman I: +0.00000054%
  • Steve Erickson: +0.00000049%
  • Gekctek: +0.00000026%
  • Lightninglad: +0.00000049%
  • Other: +55.65255533%
  • Untrackable: +20.78891549%

Observation 1: Don’t nICP and waterneruon vote on their own? Why am I clicking 135 times every 4 days if my vote just actually follows DFINITY(cc @EnzoPlayer0ne @WaterNeuron). Perhaps this feature isn’t turned on yet? or maybe it is just this topic? A bit irrelevant, but with about 30% of the vote here it would be great if we got those two independents on these votes.

Observation 2: The really damning piece here is 75% Other and Untrackable. Those folks probably follow DFINITY directly and we’re going to have to excruciatingly extract them one voter at a time. Who knows how many of these people have lost their keys? Perhaps the neuron reset code will help here but we are months away from that VP starting to decay.

So these two together leave me less than enthused about the possibility of trying to undertake decentralizing the NNS on the Application Canister topic all on my own in an attempt to overcome DFINITY’s “not made here” auto-reject. BUT there are other options.

3. Actions needed

  1. DFINITY needs to define what kind of review and audit they would want to move toward an abstain or even affirmative vote. This seems like a no-brainer. DFINITY cannot build a thriving ecosystem of competent developers if they will only allow code that they write and review on the protocol support level. Any developer that not knee-deep in existential-dread-inducing sunk costs with the capability to develop these levels of systems will run screaming the other way into other permissionless ecosystems.

This is unsustainable and has been for a while.

I know of two Motoko auditing entities and I’m one of them. I can’t audit my own code and I can’t afford to pay the other guy’s fees for the 4-5 utility canisters that I have in my pipeline. So what do we do here? Ultimately DFINITY has to decide what they will accept, or at least at what hurdle they will decide to abstain. Please, please, please @lara, @dominicwilliams, @Jan, @diegop start this conversation. If we know the hurdle we can raise money and organize around it. As long as it stays undefined we are stuck.

1b. The community needs to fund whatever X is from 1. that will allow us to get code audited and into production from third parties. Is this a DAO? Is this an SNS? Is it some other thing? There is likely not much profit in it but it is vital and upgradeable contracts vastly complicate the complexity and potential cost overrun. (see Discussion: Finny & Let's Figure Out Where We Went Wrong) No external audit firm is rolling in and helping bootstrap a Motoko audit capability at a price point that startups can afford. Rust capability is out there but excruciatingly expensive. It is all us ya’ll.

  1. We need to architect and get DFINITY to approve an alternative. My current thinking is to write a very small, very compact canister that does only one thing and does it really well: 1. Read NNS Proposals and see if they’ve passed. 2. Install code if the right configuration is there and the proposal has passed. This would remove the act of upgrading from the NNS Governance canister and eliminate the problem of enabling an attacker to “let them be unresolved until they time out, and through a series of actions block some of the emergency capability of the NNS to do emergency updates”.

If this upgrade canister is REALLY REALLY tight we could black hole it…but again, with some of the fluctuations that the NNS has gone through, I think it is better to let it be controlled by the NNS so we can upgrade in a pinch.

I don’t have to write this. DFINITY could write and deploy the alt-install canister.

image

How would this work? Either:

Option 1. We use Install Code type so we can put the actual wasm bits in the proposal, but point to a consistent blackhole so that the install insta-fails and can’t hang up the NNS(Although maybe this need to be in the rust equivalent of a try catch? Pardon my rust ignorance ic/rs/nns/governance/src/governance.rs at fa2329782561f1b4a5d27052147023e75727e1fa · dfinity/ic · GitHub). The proposer would need to put some kind of tag in the proposal that the alt-install canister can pull and parse. Maybe we wrap the args in a specific variant flag and unwrap it on the alt-install canister.

Option 2: We have more complexity in the alt-install canister and wasms need to be uploaded there and registered. Users could get some kind of generated tag they could put in motion proposals and just submit motion proposals so that the NNS isn’t even trying to call install on the system canister.

Both of these options let us co-opt the security of the NNS without putting it at risk.

I haven’t spoken to the potential long-term issue of “does this lead to governance spam and fatigue,” but let’s set that aside for a moment and just see if it is possible technically and politically or not.

What we need to know from DFINITY is 1. Do either of these options work? and 2. Do they work enough for DFINITY to generally abstain from those proposals?

Thanks for enduring my somewhat sarcasm-tinged response. I’ve been shipping another canister, the ICRC-75-based list management canister which is yet another potential utility canister that could drastically simplify developer’s complexity for a number of use cases. There are bunch of these we can build…and if we can secure them and make them trustworthy we can solve the upgradeability issue and put a tailwind behind developers.

h/t to https://www.memefighter.app/ for the levity.

1 Like

There is a few things i disagree here with, but it is a fairly well-argued case. Let me ping folks inside the foundation.