How to deploy and distribute a censorship-resistant upgradeable dapp
From the inception of the first versions of Aragon we took building a truly decentralized app very seriously. We decided that just using Ethereum as the settlement layer was not enough, because if a significant part of the infrastructure depended on centralized servers, we would quickly become a central point of failure that could be taken down.
However, relying on regular users to review, download and keep up to date versions of all the required software can become a barrier for adoption beyond developers or very tech-savvy users. In order to fully run Aragon, both IPFS and Ethereum nodes are required, both of which require setting up a complex environment and there are currently no good options for running them on mobile devices.
In this post we explore the process of how the Aragon client and the different apps the Aragon team has built so far (Voting, Token Manager, etc.) get deployed and how we make them available to users regardless of their skill level.
Upgradeability is an important focus for us, and one of the key features of aragonOS. We are dealing with experimental and bleeding edge technology, and it would be such a step back forcing users to commit forever to whatever version of the software was available when they created their organization.
We decided to build aragonPM as the main way to distribute different versions of the packages that comprise Aragon. A package or repository (repo) in the aragonPM keeps track of evolving versions of its contents (the webapp component typically) and smart contract code (if applicable).
Each aragonPM registry is a smart contract that owns an Ethereum Name Service(ENS) domain and therefore can create subdomains for its repos. This gives users the ability to find repos with human-readable names. We envision that many aragonPM registries will be created for different purposes and types of packages. In the case of Aragon, we use the aragonpm.eth registry to host our core components and all the 'first party' apps that we develop. For now only people within the organization can create new repos. We also have the open.aragonpm.eth registry for community developed packages, where anyone can create repos.
At the repo level, each repo can have its own rules that govern how new versions can be published using the aragonOS access control list. This allows for setting up different types of processes depending the importance of the repo or the nature of the upgrade (major, minor or patch).
A repo is created in a registry and can have many versions published over time
As explained above and in the figure, a repo keeps versioned history of content and smart contract code tuples. The content is an on-chain reference to a blob of data that lives off-chain (we support IPFS or HTTP addressing currently). By using IPFS whoever is fetching the content has the assurance of the integrity of the data and that it hasn't changed since it was published. Aragon always uses IPFS for publishing, but having HTTP is useful for testing purposes or for less critical code.
The smart contract code only applies to packages that have an on-chain contract component associated with a particular version. It can be the implementation code for upgradeable Proxies or a smart contract that can be directly used. By having these code addresses stored on-chain, smart contracts can use aragonPM directly to get the latest version of the code for a repo. At Aragon we benefit from having these contract references on-chain for our dao-kits to know what the latest version of an app is (to set up the proxies), or for locating the smart contract for a dao-template that can create and set up a DAO (which is interacted with directly).
aragonPM gives users complete transparency over all deployments and traceability of what process publishing a new version entailed. At the moment, Aragon One's dev team can directly publish new versions, but in the future, publishing new versions to repos could require a more complex governance process. Because aragonPM repos are Aragon apps that are part of the aagonPM Registry DAO, repos can use any of the aragonOS-compatible governance apps to govern the process for creating new updates.
It is important to point out that aragonPM just acts as a Schelling point to what the last version of a repo is, but all upgrades are opt-in and DAOs through their governance mechanisms need to decide to upgrade, or keep using an old version. Automatically upgrading all of Aragon's DAOs is extremely dangerous regardless of what the governance mechanism over upgrades is. That's why by default all upgrades must be started within the DAO, however someone could build an auto-update contract that makes the DAO and its apps up to date to the latest version in aragonPM.
We have recently started to document all our deployments and the governance over different repos in our aragonPM registry. This gives total transparency over who can deploy new code and also a full audit trail of the changes that were pushed, which can be reproduced locally in order to verify their integrity. The next step on this front is to have these reports be automatically generated and with better visualization of the information. You can check out the deployment history in the deployments repository below:
Even though anyone running Ethereum and IPFS nodes can directly connect to aragonPM to fetch repos and use the apps, it presents a significant barrier to entry for less sophisticated users or newcomers that are just trying Aragon out.
We decided to create apm-serve to balance decentralization and usability, knowing that a motivated user could always have a fully trustless set up without requiring much infrastructure work or resources. apm-serve acts as a bridge between aragonPM and someone casually browsing the web. We were inspired by the IPFS gateway when building apm-serve, which brings access to IPFS hosted content to anyone surfing the web. apm-serve is to aragonPM what the IPFS gateways are to IPFS.
This tool, hosted on a server located in Switzerland, is able to serve content from aragonPM just by performing a simple HTTP request to the server. We host our instance of apm-serve on aragonpm.com, signaling the bridge to the on-chain aragonpm.eth domain name.
When someone goes to http://aragon.aragonpm.com, apm-serve will find the aragonPM repo for aragon.aragonpm.eth and then get its latest version. Once the version is found, apm-serve will fetch from IPFS the content associated with that version and serve it back to the user. The bridge is built so that it can serve any aragonPM repos that get published automatically, without needing any further configuration.
Aragon being served with apm-serve
Thanks to apm-serve, any static website can easily be published in the decentralized web, with the ability to have ECDSA signatures and arbitrary governance to any deployment, and still be served using regular HTTP requests.
In order to interact with aragonPM registries we have built apm.js, a standalone JS library to inspect aragonPM repos, get their different versions and fetch the referenced content. In fact, apm-serve is just a very thin server layer on top of apm.js. The library also allows interaction with the aragonPM contracts in order to create repos or new versions in repos.
The aragonCLI also uses apm.js to provide a great developer experience to publishing new versions to APM repos. The CLI aragonPM commands, accessible doing aragon apm, are the easiest way to manage aragonPM repos.
Using the aragonCLI to publish a version to an aragonPM repo and inspecting it
As explained before, aragonPM can already be used to verifiably deploy new versions of static websites completely unrelated to Ethereum. Because APM is built on top of Ethereum and IPFS, the authorship and integrity of every change are maintained, while at the same time being censorship-resistant and easily mirrorable.
Another very interesting usecase of aragonPM is DAppNode, who are using aragonPM as the backbone of their Docker registry for packages. Thanks to using aragonPM, packages in DAppNode with different levels of criticality can have custom governance processes for publishing updates.
aragonPM powered DAppNode package registry
For the next versions of aragonPM we are also looking into compatibility with the Ethereum Package Manager spec for smart contract packaging and distribution. aragonPM could be used to provide an extra layer of authorization and traceability to package upgrades.
We'd also love to see aragonPM being used as a language agnostic package manager for open source libraries and frameworks. Heavily used centralized infrastructure for package management such as NPM is a security hole the Ethereum developer community relies on heavily right now. A decentralized NPM with a more sophisticated security model could be built on top of aragonPM, which could have helped prevent some of the past issues with NPM.