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

Support reinstalling canisters (SNS) #228

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Overhauled output format. All commands besides `quill sns` should have human-readable output instead of candid IDL. Candid IDL format can be forced with `--raw`.

- Added support for setting the install mode for UpgradeSnsControlledCanister proposals.

## [0.4.4] - 2024-03-21

- Fixed `quill sns make-proposal` setting some fields to null.
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ license = "Apache-2.0"
[dependencies]
ic-base-types = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
ic-ckbtc-minter = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
ic-management-canister-types = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
ic-nervous-system-common = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
ic-nns-common = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
ic-nns-constants = { git = "https://github.com/dfinity/ic", rev = "479fc39a7ee082a62ec070efeed224784a83eb1b" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ quill sns make-upgrade-canister-proposal <PROPOSER_NEURON_ID> --target-canister-
| `--title <TITLE>` | Title of the proposal. |
| `--url <URL>` | URL of the proposal. |
| `--wasm-path <WASM_PATH>` | Path to the WASM file to be installed into the target canister. |
| `--mode <MODE>` | The install mode ("install", "reinstall", or "upgrade"). |

## Remarks

Expand Down
39 changes: 33 additions & 6 deletions src/commands/sns/make_upgrade_canister_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use candid::Principal;
use candid::{Encode, IDLArgs};
use candid_parser::parse_idl_args;
use clap::Parser;
use ic_management_canister_types::CanisterInstallMode;
use ic_sns_governance::pb::v1::{
manage_neuron, proposal, ManageNeuron, Proposal, UpgradeSnsControlledCanister,
};
Expand All @@ -27,8 +28,8 @@ pub struct MakeUpgradeCanisterProposalOpts {
proposer_neuron_id: ParsedSnsNeuron,

/// Title of the proposal.
#[arg(long, default_value_t = String::from("Upgrade Canister"))]
title: String,
#[arg(long)]
title: Option<String>,

/// URL of the proposal.
#[arg(long, default_value_t = String::new())]
Expand Down Expand Up @@ -62,6 +63,10 @@ pub struct MakeUpgradeCanisterProposalOpts {
/// Path to the binary file containing argument to post-upgrade method of the new canister WASM.
#[arg(long, conflicts_with = "canister_upgrade_arg")]
canister_upgrade_arg_path: Option<String>,

/// The install mode.
#[arg(long, value_parser = ["install", "reinstall", "upgrade"])]
mode: String,
}

pub fn exec(
Expand All @@ -79,7 +84,23 @@ pub fn exec(
wasm_path,
canister_upgrade_arg,
canister_upgrade_arg_path,
mode,
} = opts;
let mode = match mode.as_str() {
"install" => CanisterInstallMode::Install,
"reinstall" => CanisterInstallMode::Reinstall,
"upgrade" => CanisterInstallMode::Upgrade,
_ => return Err(Error::msg("Invalid mode.")),
};

let title = title.unwrap_or_else(|| {
match mode {
CanisterInstallMode::Install => "Install Canister",
CanisterInstallMode::Reinstall => "Reinstall Canister",
CanisterInstallMode::Upgrade => "Upgrade Canister",
}
.to_string()
});

let wasm = std::fs::read(wasm_path).context("Unable to read --wasm-path.")?;
let canister_upgrade_arg = match (canister_upgrade_arg, canister_upgrade_arg_path) {
Expand All @@ -100,7 +121,7 @@ pub fn exec(
String::from_utf8(std::fs::read(path).context("Unable to read --summary-path.")?)
.context("Summary must be valid UTF-8.")?
}
(None, None) => summarize(target_canister_id, &wasm),
(None, None) => summarize(target_canister_id, &wasm, mode),
};

let proposal = Proposal {
Expand All @@ -112,7 +133,7 @@ pub fn exec(
canister_id: Some(target_canister_id.into()),
new_canister_wasm: wasm,
canister_upgrade_arg,
mode: None,
mode: Some(mode as i32),
},
)),
};
Expand All @@ -137,14 +158,20 @@ pub fn exec(
Ok(vec![msg])
}

fn summarize(target_canister_id: Principal, wasm: &Vec<u8>) -> String {
fn summarize(target_canister_id: Principal, wasm: &Vec<u8>, mode: CanisterInstallMode) -> String {
// Fingerprint wasm.
let mut hasher = Sha256::new();
hasher.update(wasm);
let wasm_fingerprint = hex::encode(hasher.finalize());

let action = match mode {
CanisterInstallMode::Install => "Install",
CanisterInstallMode::Reinstall => "Reinstall",
CanisterInstallMode::Upgrade => "Upgrade",
};

format!(
"Upgrade canister:
"{action} canister:

ID: {}

Expand Down
6 changes: 3 additions & 3 deletions tests/output/default/sns/make_proposal/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ Sending message with
command = opt variant {
MakeProposal = record {
url = "";
title = "Upgrade Canister";
title = "Install Canister";
action = opt variant {
UpgradeSnsControlledCanister = record {
new_canister_wasm = blob "\00\61\73\6d\01\00\00\00";
mode = null;
mode = opt (1 : int32);
canister_id = opt principal "pycv5-3jbbb-ccccc-ddddd-cai";
canister_upgrade_arg = null;
}
};
summary = "Upgrade canister:\n\n ID: pycv5-3jbbb-ccccc-ddddd-cai\n\n WASM:\n length: 8\n fingerprint: 93a44bbb96c751218e4c00d479e4c14358122a389acca16205b1e4d0dc5f9476";
summary = "Install canister:\n\n ID: pycv5-3jbbb-ccccc-ddddd-cai\n\n WASM:\n length: 8\n fingerprint: 93a44bbb96c751218e4c00d479e4c14358122a389acca16205b1e4d0dc5f9476";
}
};
},
Expand Down
6 changes: 3 additions & 3 deletions tests/output/default/sns/make_proposal/upgrade_arg.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ Sending message with
command = opt variant {
MakeProposal = record {
url = "";
title = "Upgrade Canister";
title = "Reinstall Canister";
action = opt variant {
UpgradeSnsControlledCanister = record {
new_canister_wasm = blob "\00\61\73\6d\01\00\00\00";
mode = null;
mode = opt (2 : int32);
canister_id = opt principal "pycv5-3jbbb-ccccc-ddddd-cai";
canister_upgrade_arg = opt blob "\44\49\44\4c\01\6c\02\b9\fa\ee\18\79\b5\f6\a1\43\79\01\00\02\00\00\00\03\00\00\00";
}
};
summary = "Upgrade canister:\n\n ID: pycv5-3jbbb-ccccc-ddddd-cai\n\n WASM:\n length: 8\n fingerprint: 93a44bbb96c751218e4c00d479e4c14358122a389acca16205b1e4d0dc5f9476";
summary = "Reinstall canister:\n\n ID: pycv5-3jbbb-ccccc-ddddd-cai\n\n WASM:\n length: 8\n fingerprint: 93a44bbb96c751218e4c00d479e4c14358122a389acca16205b1e4d0dc5f9476";
}
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Sending message with
action = opt variant {
UpgradeSnsControlledCanister = record {
new_canister_wasm = blob "\00\61\73\6d\01\00\00\00";
mode = null;
mode = opt (3 : int32);
canister_id = opt principal "pycv5-3jbbb-ccccc-ddddd-cai";
canister_upgrade_arg = null;
}
Expand Down
6 changes: 3 additions & 3 deletions tests/output/sns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,16 @@ fn make_proposal() {
.diff("sns/make_proposal/from_file.txt");

let canister_wasm = asset("sns_canister.wasm");
quill_sns_send(&format!("sns make-upgrade-canister-proposal {NEURON_ID} --wasm-path '{canister_wasm}' --target-canister-id pycv5-3jbbb-ccccc-ddddd-cai"))
quill_sns_send(&format!("sns make-upgrade-canister-proposal {NEURON_ID} --wasm-path '{canister_wasm}' --target-canister-id pycv5-3jbbb-ccccc-ddddd-cai --mode install"))
.diff("sns/make_proposal/upgrade.txt");
quill_sns_send(&format!("sns make-upgrade-canister-proposal {NEURON_ID} --wasm-path '{canister_wasm}'
--canister-upgrade-arg '(record {{major=2:nat32; minor=3:nat32;}})' --target-canister-id pycv5-3jbbb-ccccc-ddddd-cai"))
--canister-upgrade-arg '(record {{major=2:nat32; minor=3:nat32;}})' --target-canister-id pycv5-3jbbb-ccccc-ddddd-cai --mode reinstall"))
.diff("sns/make_proposal/upgrade_arg.txt");

let upgrade_summary = asset("upgrade_summary.txt");
quill_sns_send(&format!(
"sns make-upgrade-canister-proposal {NEURON_ID} --wasm-path '{canister_wasm}'
--target-canister-id pycv5-3jbbb-ccccc-ddddd-cai --summary-path '{upgrade_summary}'"
--target-canister-id pycv5-3jbbb-ccccc-ddddd-cai --summary-path '{upgrade_summary}' --mode upgrade"
))
.diff("sns/make_proposal/upgrade_summary_path.txt");
}
Expand Down
Loading