Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: asset canister permissions can be set via upgrade args #2237

Merged
merged 7 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ They can do so by running the following command:
dfx sns prepare-canisters add-nns-root $CANISTER_ID
```

They also remove themselves from the list of principals that may change frontend canister content on their own.
sesi200 marked this conversation as resolved.
Show resolved Hide resolved

```bash
dfx canister call $CANISTER_ID revoke_permission '(record {of_principal = principal "<developer principal"; permission = variant { Commit;};})'
```

If any other canisters in the dapp contain custom access control, these permission lists should also be prepared for decentralization.
sesi200 marked this conversation as resolved.
Show resolved Hide resolved

### 2. Dapp developers choose the initial parameters of the SNS for a dapp.

Typically, dapp developers choose initial parameters that will be used in subsequent proposals.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ This is necessary in order for the rest of the steps to work automatically.
As any eligible NNS neuron can submit the proposal in Stage 3, this is an important step
where the dapp developers explicity express their intent to hand over their dapp to a DAO.

In this step, the dapp developers also deregister themselves from asset canisters as principals that may change website content without going through a vote.
If any other canisters in the dapp contain custom access control, these permission lists should also be prepared for decentralization.
sesi200 marked this conversation as resolved.
Show resolved Hide resolved

If successful, at the end of stage, the following has changed:

#### Table 1: Canisters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The [asset canister](https://github.com/dfinity/sdk/tree/master/src/canisters/fr

In the context of the SNS, a dapp's associated asset canister serves the frontend assets related to the dapp and may also include a frontend to the SNS DAO, e.g., through which users can vote on governance proposals.

The contents of the asset canister must be configured prior to the launch of the SNS, and any changes afterwards must be made by a principal with the `Prepare` permission. Principals with this `Prepare` permission can make a batch of changes to the asset canister and then 'lock' those changes. To have those changes applied, a proposal must be submitted. Anyone can submit the proposal for the 'locked' changes. Once changes are proposed, they can be voted on by the SNS DAO. If approved, the SNS governance canister is the only one that can commit the approved changes. This configuration assures that changes to the asset canister are only made by approved proposals. These changes are referred to as 'updates' to the asset canister in the remainder of this document.
The contents of the asset canister can be configured prior to the launch of the SNS. If configured correctly, any changes afterwards must be made by a principal with the `Prepare` permission. Principals with this `Prepare` permission can make a batch of changes to the asset canister and then 'lock' those changes. To have those changes applied, a proposal must be submitted. Anyone can submit the proposal for the 'locked' changes. Once changes are proposed, they can be voted on by the SNS DAO. If approved, the SNS governance canister is the only one that can commit the approved changes. This configuration assures that changes to the asset canister are only made by approved proposals. These changes are referred to as 'updates' to the asset canister in the remainder of this document.

This section is relevant if your project contains an asset canister and describes how you can test handing over control of an asset canister to an SNS.

Expand All @@ -19,15 +19,14 @@ The term **update** refers to changing or updating the assets stored within an a

## Deploying an asset canister

An asset canister must first be deployed before control of it can be handed over to an SNS. When a dapp's control is handed over to an SNS, this is also true for the associated asset canister.

The general overview of deploying an asset canister during an SNS launch is as follows:
- First, the asset canister must be created with or upgraded to a Wasm file from [dfx 0.14.1+](https://github.com/dfinity/sdk/blob/release-0.14.1/src/distributed/assetstorage.wasm.gz).
- Then, the dapp should hand control of the asset canister over to the SNS by setting the following permissions:
- The SNS governance canister is given `Commit` permissions. This is done by the previous developer using the `grant_permissions` command (see the granting permissions section below), otherwise the SNS must grant this permission once it is a controller.
- A whitelist of principals with `Prepare` permissions is created to give certain individuals the permission to upload changes to the asset canister. Changes must be approved through a proposal before they are applied to the asset canister.
- The user or developer creating the SNS should remove their own personal permissions.
- Lastly, the SNS's function should be registered to commit the configuration.
- First, the asset canister must be created with or upgraded to a Wasm file from [dfx 0.15.2+](https://github.com/dfinity/sdk/blob/release-0.15.2/src/distributed/assetstorage.wasm.gz).
- Then, developers should use `revoke_permission` to remove their own permissions (especially `Commit`) that allow them to update the assets arbitrarily.
- Then, after launching the SNS, the SNS's function should be [registered](#sns-genericnervoussystemfunctions) to commit proposed changes.
- Last, using upgrade arguments, updated permissions can be set. This is only possible after the SNS canisters have been successfully deployed and [initialized](../launching/launch-summary-1proposal.md#7-automatically-sns-w-initializes-sns-canisters-according-to-settings-from-step-1) because before the launch the principal id of SNS governance is not known yet
- The SNS governance canister is given `Commit` permissions. With `Commit`, SNS governance may apply a batch of proposed asset updates to the assets served by the asset canister.
- To give certain individuals the permission to upload changes to the asset canister that can then be put to vote, these principals can be granted `Prepare` permissions. Changes created using `Prepare` permissions must be approved through a proposal before they are applied to the asset canister.
- To facilitate permission management via custom SNS proposals, it can make sense to grant SNS governance the `ManagePermissions` permission. With this permission, it is not necessary to upgrade the asset canister every time permissions are supposed to change.

To deploy an asset canister, any canister in the `dfx.json` file can be set as `"type": "assets"`, and dfx will automatically generate the required files, such as an assets.wasm.gz file and a candid/assets.did file once the canister has been built.

Expand All @@ -46,11 +45,9 @@ An example of configuring an asset canister within the `dfx.json` file can be fo
To deploy your asset canister locally for testing purposes, the following command can be used:

```
dfx deploy assets --network "local" --no-wallet
dfx deploy assets --network "local"
```

The asset canister should be deployed and have permissions configured before the dapp is handed over to an SNS.

### Deploying on the mainnet

:::info
Expand All @@ -60,22 +57,18 @@ To deploy to the mainnet, you will need a wallet that contains cycles. For more
To deploy your asset canister to the mainnet, the following command can be used:

```
dfx deploy assets --network "ic" --wallet <principal>
dfx deploy assets --network "ic"
```

The asset canister should be deployed and have permissions configured before the dapp is handed over to an SNS.

## Configuring an asset canister's permissions

When configuring an asset canister, a set of permissions that contains a whitelist of principals must be created. This whitelist details who is allowed to submit changes that update assets in the asset canister. This whitelist must be configured prior to the SNS launch. Principals that are allowed to submit changes are given the `Prepare` permission.
When configuring an asset canister, a set of permissions that contains a whitelist of principals must be created. This whitelist details who is allowed to submit changes that update assets in the asset canister. Principals that are allowed to submit changes are given the `Prepare` permission.

Once a principal with `Prepare` permissions submits changes to the asset canister, these changes are set in a 'locked' state. Then, anyone can submit a proposal that proposes the 'locked' changes be applied; there is no permission necessary to submit this proposal.

During the SNS launch, control of the asset canister must be handed over to the SNS. Apart from assigning canister control to SNS root as with all dapp canisters, the SNS' governance canister should be added to the whitelist as a principal with `Commit` rights. Only principals with `Commit` rights may apply proposed changes.
Only principals with `Commit` rights may apply proposed changes.

Once the asset canister has been handed over to the SNS, only the governance canister should have `Commit` rights, and principals in the whitelist should have `Prepare` rights. The developer who configured and deployed the SNS should have their permissions removed during the SNS launch.

It is recommended that the SNS calls `take_ownership` via a proposal, which must be added as a custom proposal type. This will clear all permissions, and give only the SNS governance canister `Commit` permissions. If the SNS does not call `take_ownership`, a user cannot verify that all changes to the assets have been approved by an SNS proposal.
Once the asset canister has been handed over to the SNS, only the governance canister should have `Commit` rights, and principals in the whitelist should have `Prepare` rights. The developer who configured and deployed the SNS should have their permissions removed prior to the SNS launch.

### Granting permissions

Expand Down Expand Up @@ -115,6 +108,41 @@ dfx canister call --network ic oa7fk-maaaa-aaaam-abgka-cai list_permitted '(reco

Once the asset canister has been deployed and permissions have been configured, the SNS decentralization swap can be started. You can learn more about launching an SNS [here](../launching/launch-summary-1proposal.md)

### Overwriting permissions

No matter the state of permissions, using upgrade arguments the permissions lists can be set to new values. The upgrade argument is of type `(AssetCanisterArgs)`, where the contained types are:
sesi200 marked this conversation as resolved.
Show resolved Hide resolved

```
type AssetCanisterArgs = variant {
Init: InitArgs;
Upgrade: UpgradeArgs;
};
type InitArgs = record {};
type UpgradeArgs = record {
set_permissions: opt SetPermissions;
};
/// Sets the list of principals granted each permission.
type SetPermissions = record {
prepare: vec principal;
commit: vec principal;
manage_permissions: vec principal;
};
```

Therefore, to set the permissions such that SNS governance has `ManagePermissions` and `Commit` permissions and `principal1` has `Prepare` permissions, the upgrade argument would look like this:

```
(variant {
Upgrade = record {
set_permissions = opt record {
prepare = vec { principal "<principal1>"; };
commit = vec { principal "<SNS governance>"; };
manage_permissions = vec { principal "<SNS governance>"; };
}
}
})
```

## SNS GenericNervousSystemFunctions

Generic proposals are a way for each SNS to define custom proposals. To commit changes to the asset canister, such generic proposals are used.
Expand Down Expand Up @@ -158,14 +186,13 @@ The computed evidence should match the evidence from step 2.
Use these asset canister APIs in the proposal:

```
type CommitProposedBatchArguments = record {
type CommitProposedBatchArguments = record {
batch_id: BatchId;
evidence: blob;
};
type ValidationResult = variant { Ok : text; Err : text };


validate_commit_proposed_batch: (CommitProposedBatchArguments) -> (ValidationResult);
validate_commit_proposed_batch: (CommitProposedBatchArguments) -> (ValidationResult);
commit_proposed_batch: (CommitProposedBatchArguments) -> ();

```
Expand Down
Loading