Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
aterga committed Dec 23, 2024
1 parent acce706 commit 534ea16
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 49 deletions.
4 changes: 3 additions & 1 deletion rs/nervous_system/integration_tests/src/pocket_ic_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ pub async fn install_canister_on_subnet(
controllers: Some(controllers),
..Default::default()
});
let canister_id = pocket_ic.create_canister_on_subnet(None, settings, subnet_id).await;
let canister_id = pocket_ic
.create_canister_on_subnet(None, settings, subnet_id)
.await;
pocket_ic
.add_cycles(canister_id, STARTING_CYCLES_PER_CANISTER)
.await;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@

use ic_nervous_system_common::ONE_MONTH_SECONDS;
use ic_nervous_system_integration_tests::{create_service_nervous_system_builder::CreateServiceNervousSystemBuilder, pocket_ic_helpers::{add_wasms_to_sns_wasm, install_nns_canisters}};
use canister_test::Wasm;
use ic_base_types::SubnetId;
use ic_base_types::{CanisterId, PrincipalId};
use ic_nervous_system_common::ONE_MONTH_SECONDS;
use ic_nervous_system_integration_tests::pocket_ic_helpers::install_canister_on_subnet;
use ic_nervous_system_integration_tests::{
create_service_nervous_system_builder::CreateServiceNervousSystemBuilder,
pocket_ic_helpers::{add_wasms_to_sns_wasm, install_nns_canisters},
};
use ic_nns_test_utils::common::modify_wasm_bytes;
use pocket_ic::{management_canister::{CanisterInstallMode, CanisterInstallModeUpgradeInner}, PocketIcBuilder};
use pocket_ic::management_canister::CanisterSettings;
use ic_test_utilities::universal_canister::UNIVERSAL_CANISTER_WASM;
use ic_nervous_system_integration_tests::pocket_ic_helpers::install_canister_on_subnet;
use canister_test::Wasm;
use ic_base_types::SubnetId;
use pocket_ic::management_canister::CanisterSettings;
use pocket_ic::{
management_canister::{CanisterInstallMode, CanisterInstallModeUpgradeInner},
PocketIcBuilder,
};

#[tokio::test]
async fn test() {
Expand All @@ -35,7 +40,8 @@ async fn test() {
vec![],
Some(original_wasm.clone()),
vec![developer],
).await;
)
.await;

// Install the (mainnet) NNS canisters.
{
Expand Down Expand Up @@ -74,38 +80,40 @@ async fn test() {
// .await;

// TODO: Use SNS proposal to perform the upgrade using chunked Wasm.
let store_canister_id = install_canister_on_subnet(
&pocket_ic,
app_subnet,
vec![],
None,
vec![developer],
).await;
let store_canister_id =
install_canister_on_subnet(&pocket_ic, app_subnet, vec![], None, vec![developer]).await;

// TODO: Make the new WASM bigger than 2 MiB so that it does not fit into an ingress message.
let new_wasm = modify_wasm_bytes(&original_wasm.bytes(), 123);
let new_wasm_hash = new_wasm.sha256_hash();

let chunk_hashes_list = {
pocket_ic.upload_chunk(store_canister_id.into(), Some(developer.into()), new_wasm).await;
let chunk_hashes_list = pocket_ic.stored_chunks(store_canister_id.into(), Some(developer.into())).await.unwrap();
pocket_ic
.upload_chunk(store_canister_id.into(), Some(developer.into()), new_wasm)
.await;
let chunk_hashes_list = pocket_ic
.stored_chunks(store_canister_id.into(), Some(developer.into()))
.await
.unwrap();
assert_eq!(chunk_hashes_list[0], new_wasm_hash);
chunk_hashes_list
};

// Finally, trigger the chunked upgrade
pocket_ic.install_chunked_canister(
target_canister_id.into(),
Some(developer.into()),
CanisterInstallMode::Upgrade(Some(CanisterInstallModeUpgradeInner {
wasm_memory_persistence: None,
skip_pre_upgrade: Some(false),
})),
store_canister_id.into(),
chunk_hashes_list,
new_wasm_hash.to_vec(),
vec![],
).await;
pocket_ic
.install_chunked_canister(
target_canister_id.into(),
Some(developer.into()),
CanisterInstallMode::Upgrade(Some(CanisterInstallModeUpgradeInner {
wasm_memory_persistence: None,
skip_pre_upgrade: Some(false),
})),
store_canister_id.into(),
chunk_hashes_list,
new_wasm_hash.to_vec(),
vec![],
)
.await;

panic!("hello");
}
17 changes: 17 additions & 0 deletions rs/nervous_system/root/src/change_canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ use ic_nervous_system_clients::{
use ic_nervous_system_runtime::Runtime;
use serde::Serialize;

pub struct ChunkedCanisterWasm {
// Check sum of the overall WASM to be reassembled from chunks.
wasm_module_hash: Vec<u8>,

// Indicates which canister stores the WASM chunks.
store_canister_id: CanisterId,

// Specifies a list of hash values for the chunks that comprise this WASM. Must contain at least
// one chink.
chunk_hashes_list: Vec<Vec<u8>>,
}

/// Argument to the similarly-named methods on the NNS and SNS root canisters.
#[derive(Clone, Eq, PartialEq, CandidType, Deserialize, Serialize)]
pub struct ChangeCanisterRequest {
Expand Down Expand Up @@ -52,6 +64,10 @@ pub struct ChangeCanisterRequest {
pub compute_allocation: Option<candid::Nat>,
#[serde(serialize_with = "serialize_optional_nat")]
pub memory_allocation: Option<candid::Nat>,

/// If the entire WASM does not into the 2 MiB ingress limit, then `new_canister_wasm` should be
/// an empty, and this field should be set instead.
pub chunked_canister_wasm: Option<ChunkedCanisterWasm>,
}

impl ChangeCanisterRequest {
Expand All @@ -71,6 +87,7 @@ impl ChangeCanisterRequest {
.field("arg_sha256", &format!("{:x?}", arg_sha))
.field("compute_allocation", &self.compute_allocation)
.field("memory_allocation", &self.memory_allocation)
.field("chunked_canister_wasm", &self.chunked_canister_wasm)
.finish()
}
}
Expand Down
28 changes: 28 additions & 0 deletions rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,30 @@ pub struct Motion {
#[prost(string, tag = "1")]
pub motion_text: ::prost::alloc::string::String,
}

/// Represents a WASM chunked into potentially multiple smaller chunks, each of which can safely
/// be sent around the ICP.
#[derive(
candid::CandidType,
candid::Deserialize,
comparable::Comparable,
Clone,
PartialEq,
::prost::Message,
)]
pub struct ChunkedCanisterWasm {
/// Obligatory check sum of the overall WASM to be reassembled from chunks.
#[prost(bytes = "vec", optional, tag = "1")]
pub wasm_module_hash: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
/// Obligatory; indicates which canister stores the WASM chunks.
#[prost(message, optional, tag = "2")]
pub store_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>,
/// Specifies a list of hash values for the chunks that comprise this WASM. Must contain at least
/// one chink.
#[prost(bytes = "vec", repeated, tag = "3")]
pub chunk_hashes_list: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
}

/// A proposal function that upgrades a canister that is controlled by the
/// SNS governance canister.
#[derive(
Expand Down Expand Up @@ -395,6 +419,10 @@ pub struct UpgradeSnsControlledCanister {
tag = "4"
)]
pub mode: ::core::option::Option<i32>,
/// If the entire WASM does not into the 2 MiB ingress limit, then `new_canister_wasm` should be
/// an empty, and this field should be set instead.
#[prost(message, optional, tag = "5")]
pub chunked_canister_wasm: ::core::option::Option<ChunkedCanisterWasm>,
}
/// A proposal to transfer SNS treasury funds to (optionally a Subaccount of) the
/// target principal.
Expand Down
15 changes: 15 additions & 0 deletions rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ message Motion {
string motion_text = 1;
}

// Represents a WASM chunked into potentially multiple smaller chunks, each of which can safely
// be sent around the ICP.
message ChunkedCanisterWasm {
// Obligatory check sum of the overall WASM to be reassembled from chunks.
optional bytes wasm_module_hash = 1;
// Obligatory; indicates which canister stores the WASM chunks.
optional ic_base_types.pb.v1.PrincipalId store_canister_id = 2;
// Specifies a list of hash values for the chunks that comprise this WASM. Must contain at least
// one chink.
repeated bytes chunk_hashes_list = 3;
}

// A proposal function that upgrades a canister that is controlled by the
// SNS governance canister.
message UpgradeSnsControlledCanister {
Expand All @@ -323,6 +335,9 @@ message UpgradeSnsControlledCanister {
optional bytes canister_upgrade_arg = 3;
// Canister install_code mode.
optional types.v1.CanisterInstallMode mode = 4;
// If the entire WASM does not into the 2 MiB ingress limit, then `new_canister_wasm` should be
// an empty, and this field should be set instead.
optional ChunkedCanisterWasm chunked_canister_wasm = 5;
}

// A proposal to transfer SNS treasury funds to (optionally a Subaccount of) the
Expand Down
26 changes: 26 additions & 0 deletions rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,28 @@ pub struct Motion {
#[prost(string, tag = "1")]
pub motion_text: ::prost::alloc::string::String,
}
/// Represents a WASM chunked into potentially multiple smaller chunks, each of which can safely
/// be sent around the ICP.
#[derive(
candid::CandidType,
candid::Deserialize,
comparable::Comparable,
Clone,
PartialEq,
::prost::Message,
)]
pub struct ChunkedCanisterWasm {
/// Obligatory check sum of the overall WASM to be reassembled from chunks.
#[prost(bytes = "vec", optional, tag = "1")]
pub wasm_module_hash: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
/// Obligatory; indicates which canister stores the WASM chunks.
#[prost(message, optional, tag = "2")]
pub store_canister_id: ::core::option::Option<::ic_base_types::PrincipalId>,
/// Specifies a list of hash values for the chunks that comprise this WASM. Must contain at least
/// one chink.
#[prost(bytes = "vec", repeated, tag = "3")]
pub chunk_hashes_list: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
}
/// A proposal function that upgrades a canister that is controlled by the
/// SNS governance canister.
#[derive(
Expand Down Expand Up @@ -395,6 +417,10 @@ pub struct UpgradeSnsControlledCanister {
tag = "4"
)]
pub mode: ::core::option::Option<i32>,
/// If the entire WASM does not into the 2 MiB ingress limit, then `new_canister_wasm` should be
/// an empty, and this field should be set instead.
#[prost(message, optional, tag = "5")]
pub chunked_canister_wasm: ::core::option::Option<ChunkedCanisterWasm>,
}
/// A proposal to transfer SNS treasury funds to (optionally a Subaccount of) the
/// target principal.
Expand Down
8 changes: 7 additions & 1 deletion rs/sns/governance/src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2507,9 +2507,15 @@ impl Governance {

let mode = upgrade.mode_or_upgrade() as i32;

let new_canister_wasm = if let Some(chunked_canister_wasm) = upgrade.chunked_canister_wasm {
todo!()
} else {
upgrade.new_canister_wasm
};

self.upgrade_non_root_canister(
target_canister_id,
upgrade.new_canister_wasm,
new_canister_wasm,
upgrade
.canister_upgrade_arg
.unwrap_or_else(|| Encode!().unwrap()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2914,6 +2914,7 @@ fn test_sns_controlled_canister_upgrade_only_upgrades_dapp_canisters() {
new_canister_wasm: vec![0, 0x61, 0x73, 0x6D, 2, 0, 0, 0],
canister_upgrade_arg: None,
mode: Some(CanisterInstallModeProto::Upgrade.into()),
chunked_canister_wasm: None,
});

// Upgrade Proposal
Expand Down
23 changes: 23 additions & 0 deletions rs/sns/governance/src/pb/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,39 @@ impl From<pb::UpgradeSnsControlledCanister> for pb_api::UpgradeSnsControlledCani
new_canister_wasm: item.new_canister_wasm,
canister_upgrade_arg: item.canister_upgrade_arg,
mode: item.mode,
chunked_canister_wasm: item.chunked_canister_wasm.map(pb_api::ChunkedCanisterWasm::from),
}
}
}

impl From<pb_api::ChunkedCanisterWasm> for pb::ChunkedCanisterWasm {
fn from(item: pb_api::ChunkedCanisterWasm) -> Self {
Self {
wasm_module_hash: item.wasm_module_hash,
store_canister_id: item.store_canister_id,
chunk_hashes_list: item.chunk_hashes_list,
}
}
}

impl From<pb::ChunkedCanisterWasm> for pb_api::ChunkedCanisterWasm {
fn from(item: pb::ChunkedCanisterWasm) -> Self {
Self {
wasm_module_hash: item.wasm_module_hash,
store_canister_id: item.store_canister_id,
chunk_hashes_list: item.chunk_hashes_list,
}
}
}

impl From<pb_api::UpgradeSnsControlledCanister> for pb::UpgradeSnsControlledCanister {
fn from(item: pb_api::UpgradeSnsControlledCanister) -> Self {
Self {
canister_id: item.canister_id,
new_canister_wasm: item.new_canister_wasm,
canister_upgrade_arg: item.canister_upgrade_arg,
mode: item.mode,
chunked_canister_wasm: item.chunked_canister_wasm.map(pb::ChunkedCanisterWasm::from),
}
}
}
Expand Down
Loading

0 comments on commit 534ea16

Please sign in to comment.