How to update asset canister after SNS proposal?

I’m testing a frontend deployment using the sns-testing repository. I’ve replaced the test asset canister with a simple webapp build output to test the deployment.

Here are the steps I’ve taken:

  1. ./setup_locally.sh
  2. Update assets entry in dfx.json:
 "assets": {
      "frontend": {
        "entrypoint": "./frontend/build/index.html"
      },
      "source": [
        "./frontend/build"
      ],
      "type": "assets"
    },
  1. Run ./deploy_assets.sh to deploy assets canister
  2. Run ./deploy_sns.sh sns-test.yml
  3. Run ./prepare_assets.sh
  4. Register asset canister: ./register_dapp.sh bnz7o-iuaaa-aaaaa-qaaaa-cai
  5. Update permissions ./register_permission_assets.sh
  6. Open sns sale using ./open_sns_swap.sh
  7. Vote using NNS frontend dapp locally.
  8. And at last finalize the sale by running: ./finalize_sns_swap.sh

After all these steps the neurons get distributed and the sns swap becomes successfull. But I’m not then able to update the canister. Running the deploy assets script again deploys the canister. How do I update the frontend canister via a SNS proposal?

You can find detailed instructions and ready-to-use scripts here. Happy to answer questions if you run into problems :slightly_smiling_face:

The example used for asset canister in the repo uses a wasm and not individual assets which cause a little confusion.


The only part related to updating asset canister is point 6. I’ve tried using the ./commit_assets.sh script, but did not find a way to create a SNS proposal out of the update.

For eg, I update the index.html file,
In that case I would run ./commit_assets.sh index.html ./frontend/build/index.html to commit the updated asset. What is the next step here.

Also, what if I have multiple files that have changed and I want to commit the changed files in the build folder. How would I do that?

Steps 4 and 5 are required, and I found some more WIP documentation on the next steps. Copy/pasting it here for reference:

New SNS GenericNervousSystemFunctions

  1. Submit a new AddGenericNervouSystemFunction SNS Proposal to support the commit_proposed_batch API. The target canister id should be the asset canister (that is upgraded in Upgrade Steps) and the target function is commit_proposed_batch. The validate function should be validate_commit_proposed_batch.
  2. Submit an ExecuteNervousSystemFunction SNS Proposal with the output from dfx deploy <frontend canister name> --network ic --by-proposal. (see Upgrade Steps)

Upgrade Steps

  1. Upgrade the asset canister (by proposal, as with any other canister) to the asset canister wasm bundled with dfx 0.14.1, available here: https://github.com/dfinity/sdk/blob/release-0.14.1/src/distributed/assetstorage.wasm.gz
  2. After upgrading the asset canister by proposal, have someone with Prepare permission run dfx deploy <frontend canister name> --network ic --by-proposal. The output will contain something like this:
Proposed commit of batch 2 with evidence e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855. Either commit it by proposal, or delete it.
  1. Save the batch number and the evidence value for use with the asset canister API.
  2. To ensure that others would be able to verify the evidence in the proposal, have someone else clone the dapp repo and run dfx deploy <frontend canister name> --network ic --compute-evidence. The computed evidence should match the evidence from step (2).
  3. Submit a new proposal to commit the batch, using the ‘New Canister APIs’ above.

I’m having trouble with the formatting of the commit_proposed_batch command, I gave myself prepare permissions to trouble shoot. Rather than calling the proposal, I’m just trying to get the command formatted correctly:

First I encode the evidence:
didc encode '("255e5e9d4e2e4b29d336c7a975a03158a48986efa3d25f58dc17840d888e06ef")' --format blob

Next I call the command with the resulting blob:

dfx canister call <assets_canister> commit_proposed_batch '(record {batch_id=2:nat; evidence=blob "DIDL\00\01q@255e5e9d4e2e4b29d336c7a975a03158a48986efa3d25f58dc17840d888e06ef"})'

Then the call is rejected:
The replica returned a replica error: Replica Error: reject code CanisterError, reject message Canister avqkn-guaaa-aaaaa-qaaea-cai trapped explicitly: batch computed evidence 255e5e9d4e2e4b29d336c7a975a03158a48986efa3d25f58dc17840d888e06ef does not match presented evidence 4449444c0001714032353565356539643465326534623239643333366337613937356130333135386134383938366566613364323566353864633137383430643838386530366566, error code None

compute_evidence produces bytes. It looks like you then converted these bytes to a hex string. Then you take the hex string and pack it into a candid message. Last, you send the candid message blob in a candid message to the canister, as evidenced by the canister saying presented evidence 4449444c0001<...>, which you can recognise because 4449444c0001 is the beginning of a candid-encoded message (that’s just something ‘one knows’ :slightly_smiling_face:)

What you are supposed to do is to use the blob produced by compute_evidence directly as the evidence blob in commit_proposed_batch without converting it to a string so that the hex-encoded evidence (255e5e9<...>) is also what commit_proposed_batch would produce if it were to hex-encode the evidence

1 Like

Great, that helped me through…

Maybe its an obvious point or there is another way to format the arg, but to get the blob from the evidence, it was just a matter of adding \'s :
evidence = 255e5e9d4e2e4b29d336c7a975a03158a48986efa3d25f58dc17840d888e06ef
blob = blob "\25\5e\5e\9d\4e\2e\4b\29\d3\36\c7\a9\75\a0\31\58\a4\89\86\ef\a3\d2\5f\58\dc\17\84\0d\88\8e\06\ef"

1 Like

Hi @Severin, I think I’m getting lost as I could see a wasm to gzip in the frontend .dfx folder, so I tried this route.

I commited my frontend as a batch:

and then ran:

dfx canister call OpenFPL_frontend commit_proposed_batch ‘(record {batch_id=203:nat; evidence =blob
“\5f\2d\8f\ac\45\91\e0\1e\2d\8e\0d\a7\15\a6\32\ba\50\16\d8\bd\aa\89\7d\31\c0\76\6a\30\95\d3\fb\13”})’

But get the commit permission error:

Did you hand that canister over to an SNS? Then probably only the SNS has Commit permissions and you need to decide about the proposal in a vote. Otherwise you can give yourself the rights either via grant_permission or upgrade args (see did file for exact naming)

Yes I handed the canister over to the SNS, it was in the sns_init file.

Yeah proposal in a vote is cool, how do i raise the proposal linking this commit? I can’t do it the same as the backend because I don’t have a single frontend wasm to gzip.

You need to register a generic function call (see docs here) and then run the function with the computed evidence (see your screenshot above).

Hi @Severin,

I’m trying to trigger the generic proposal in the same way i trigger the others but i keep getting a parser error.

So I need to encode the payload I send to the function:


#!/bin/bash

# Set current directory to the scripts root
SCRIPT=$(readlink -f "$0")
SCRIPT_DIR=$(dirname "$SCRIPT")
cd $SCRIPT_DIR

TITLE="Update Frontend Canister."
SUMMARY="Update frontend canister with evidence batch id 203."
URL="https://openfpl.xyz"

ARGS="( record { 
    batch_id = 203:nat;
    evidence =blob "\5f\2d\8f\ac\45\91\e0\1e\2d\8e\0d\a7\15\a6\32\ba\50\16\d8\bd\aa\89\7d\31\c0\76\6a\30\95\d3\fb\13"
} )"
FUNCTION_ID=24000

# Submit the proposal

../../utils/make_custom_function_proposal_frontend.sh $FUNCTION_ID "$TITLE" "$SUMMARY" "$URL" "$ARGS" "validate_commit_proposed_batch"

Which then gets used with the custom function proposal, but I used to encode that using arguments from the backend canister but this generic function is on the frontend canister. This might be why I’m getting a parse error.

#!/bin/bash

# cd into folder containing this script
SCRIPT=$(readlink -f "$0")
SCRIPT_DIR=$(dirname "$SCRIPT")
cd $SCRIPT_DIR

# Extract the args
FUNCTION_ID=$1
TITLE=$2
SUMMARY=$3
URL=$4
ARGS=$5
METHOD=$6

# Candid encode the payload as binary
PAYLOAD=$(didc encode "$ARGS" --format blob -d ../../.dfx/ic/canisters/OpenFPL_frontend/backend.did -m $METHOD)

# Build the proposal candid
PROPOSAL="(record { title=\"$TITLE\"; url=\"$URL\"; summary=\"$SUMMARY\"; action=opt variant 
    {ExecuteGenericNervousSystemFunction = record {function_id=($FUNCTION_ID:nat64); payload=$PAYLOAD}}})"

# Make the proposal
./submit_proposal.sh "$PROPOSAL"

Nothing looks like a smoking gun to me, but here’s a few ideas:

You have double quotes in the text and then you pass that around. Sounds pretty dangerous to me with string escaping and so on. Can you manually encode this and compare with a print statement in the other scrip to see if it’s passed properly?

Why are you targetting validate_...? Shouldn’t you try to call the real function?

If you use the backend .did to encode the frontend one I would expect it to complain that there is no such function defined

Hi Severin,

I’ve tidied up some code and the issue appears to be the method I’m passing in, since it’s not on the backend canister I assume:

So in this file I need to pass it the definition of the frontend with the commit_proposed_batch method:

#!/bin/bash

# cd into folder containing this script
SCRIPT=$(readlink -f "$0")
SCRIPT_DIR=$(dirname "$SCRIPT")
cd $SCRIPT_DIR

# Extract the args
FUNCTION_ID=$1
TITLE=$2
SUMMARY=$3
URL=$4
ARGS=$5
METHOD=$6

# Candid encode the payload as binary
PAYLOAD=$(didc encode "$ARGS" --format blob -d ../../.dfx/ic/canisters/OpenFPL_backend/OpenFPL_backend.did -m $METHOD)

echo $PAYLOAD

# Build the proposal candid
PROPOSAL="(record { title=\"$TITLE\"; url=\"$URL\"; summary=\"$SUMMARY\"; action=opt variant 
    {ExecuteGenericNervousSystemFunction = record {function_id=($FUNCTION_ID:nat64); payload=$PAYLOAD}}})"

# Make the proposal
./submit_proposal.sh "$PROPOSAL"

I think…

1 Like

Hi @Severin,

So this is the encode line:


PAYLOAD=$(didc encode "$ARGS" --format blob -d ../../.dfx/ic/canisters/OpenFPL_frontend/constructor.did -m $METHOD)

The frontend file has the title constructor.did

And I have a new error, which I’ll work on:

Just didn’t want you wasting time looking into the encoding as it’s all setup.

Hi @Severin,

I can’t recreate the batch process since batch_id 203 has already been created by I’m sure I’m passing in the output from that process, I haven’t changed the frontend since beginning this process of trying to update via proposal.

Answered over here if someone runs into the same issue: Batch computed evidence does not match presented evidence

Kinic DAO member is doing a PR for Quill that helped resolve this.

1 Like