diff --git a/rs/nns/governance/api/src/types.rs b/rs/nns/governance/api/src/types.rs index b15f9b960aef..68ce89a42bc8 100644 --- a/rs/nns/governance/api/src/types.rs +++ b/rs/nns/governance/api/src/types.rs @@ -4200,6 +4200,12 @@ pub enum NnsFunction { /// UpdateConfigOfSubnet can be used instead. But otherwise, this is the /// state of the art (as of Oct 2025) way of doing subnet recovery. SetSubnetOperationalLevel = 55, + /// Does what the name says: takes a canister snapshot. + /// + /// The canister being snapshotted (the "target" canister) must be + /// controlled by the NNS Root canister. This restriction could be relaxed + /// later. See nns/.../root.did for the payload type. + TakeCanisterSnapshot = 56, } impl NnsFunction { /// String value of the enum field names used in the ProtoBuf definition. @@ -4283,6 +4289,7 @@ impl NnsFunction { NnsFunction::PauseCanisterMigrations => "NNS_FUNCTION_PAUSE_CANISTER_MIGRATIONS", NnsFunction::UnpauseCanisterMigrations => "NNS_FUNCTION_UNPAUSE_CANISTER_MIGRATIONS", NnsFunction::SetSubnetOperationalLevel => "NNS_FUNCTION_SET_SUBNET_OPERATIONAL_LEVEL", + NnsFunction::TakeCanisterSnapshot => "NNS_FUNCTION_TAKE_CANISTER_SNAPSHOT", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -4363,6 +4370,7 @@ impl NnsFunction { "NNS_FUNCTION_PAUSE_CANISTER_MIGRATIONS" => Some(Self::PauseCanisterMigrations), "NNS_FUNCTION_UNPAUSE_CANISTER_MIGRATIONS" => Some(Self::UnpauseCanisterMigrations), "NNS_FUNCTION_SET_SUBNET_OPERATIONAL_LEVEL" => Some(Self::SetSubnetOperationalLevel), + "NNS_FUNCTION_TAKE_CANISTER_SNAPSHOT" => Some(Self::TakeCanisterSnapshot), _ => None, } } diff --git a/rs/nns/governance/proto/ic_nns_governance/pb/v1/governance.proto b/rs/nns/governance/proto/ic_nns_governance/pb/v1/governance.proto index 5ef8a6938c36..aa48018e3b61 100644 --- a/rs/nns/governance/proto/ic_nns_governance/pb/v1/governance.proto +++ b/rs/nns/governance/proto/ic_nns_governance/pb/v1/governance.proto @@ -495,6 +495,9 @@ enum NnsFunction { // Take subnet offline or bring back online. Used as part of subnet recovery. NNS_FUNCTION_SET_SUBNET_OPERATIONAL_LEVEL = 55; + + // Take a canister snapshot. + NNS_FUNCTION_TAKE_CANISTER_SNAPSHOT = 56; } // Payload of a proposal that calls a function on another NNS diff --git a/rs/nns/governance/src/canister_state.rs b/rs/nns/governance/src/canister_state.rs index 1a7e3877cf6b..71c7727d3ed9 100644 --- a/rs/nns/governance/src/canister_state.rs +++ b/rs/nns/governance/src/canister_state.rs @@ -394,7 +394,8 @@ fn get_effective_payload( | ValidNnsFunction::DeployHostosToSomeNodes | ValidNnsFunction::PauseCanisterMigrations | ValidNnsFunction::UnpauseCanisterMigrations - | ValidNnsFunction::SetSubnetOperationalLevel => Ok(payload.clone()), + | ValidNnsFunction::SetSubnetOperationalLevel + | ValidNnsFunction::TakeCanisterSnapshot => Ok(payload.clone()), } } diff --git a/rs/nns/governance/src/gen/ic_nns_governance.pb.v1.rs b/rs/nns/governance/src/gen/ic_nns_governance.pb.v1.rs index b7795d5807a1..600a8e8dbd8a 100644 --- a/rs/nns/governance/src/gen/ic_nns_governance.pb.v1.rs +++ b/rs/nns/governance/src/gen/ic_nns_governance.pb.v1.rs @@ -4820,6 +4820,8 @@ pub enum NnsFunction { UnpauseCanisterMigrations = 54, /// Take subnet offline or bring back online. Used as part of subnet recovery. SetSubnetOperationalLevel = 55, + /// Take a canister snapshot. + TakeCanisterSnapshot = 56, } impl NnsFunction { /// String value of the enum field names used in the ProtoBuf definition. @@ -4893,6 +4895,7 @@ impl NnsFunction { Self::PauseCanisterMigrations => "NNS_FUNCTION_PAUSE_CANISTER_MIGRATIONS", Self::UnpauseCanisterMigrations => "NNS_FUNCTION_UNPAUSE_CANISTER_MIGRATIONS", Self::SetSubnetOperationalLevel => "NNS_FUNCTION_SET_SUBNET_OPERATIONAL_LEVEL", + Self::TakeCanisterSnapshot => "NNS_FUNCTION_TAKE_CANISTER_SNAPSHOT", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -4973,6 +4976,7 @@ impl NnsFunction { "NNS_FUNCTION_PAUSE_CANISTER_MIGRATIONS" => Some(Self::PauseCanisterMigrations), "NNS_FUNCTION_UNPAUSE_CANISTER_MIGRATIONS" => Some(Self::UnpauseCanisterMigrations), "NNS_FUNCTION_SET_SUBNET_OPERATIONAL_LEVEL" => Some(Self::SetSubnetOperationalLevel), + "NNS_FUNCTION_TAKE_CANISTER_SNAPSHOT" => Some(Self::TakeCanisterSnapshot), _ => None, } } diff --git a/rs/nns/governance/src/governance.rs b/rs/nns/governance/src/governance.rs index 97f1f1d2db20..9f1fc968a336 100644 --- a/rs/nns/governance/src/governance.rs +++ b/rs/nns/governance/src/governance.rs @@ -1,6 +1,7 @@ #![allow(deprecated)] use crate::{ - are_nf_fund_proposals_disabled, are_performance_based_rewards_enabled, decoder_config, + are_canister_snapshot_proposals_enabled, are_nf_fund_proposals_disabled, + are_performance_based_rewards_enabled, decoder_config, governance::{ merge_neurons::{ build_merge_neurons_response, calculate_merge_neurons_effect, @@ -4807,6 +4808,13 @@ impl Governance { Self::validate_add_or_remove_data_centers_payload(&update.payload) .map_err(invalid_proposal_error)?; } + ValidNnsFunction::TakeCanisterSnapshot => { + if !are_canister_snapshot_proposals_enabled() { + return Err(invalid_proposal_error( + "TakeCanisterSnapshot proposals are not yet enabled.".to_string(), + )); + } + } _ => {} }; diff --git a/rs/nns/governance/src/pb/conversions/mod.rs b/rs/nns/governance/src/pb/conversions/mod.rs index 61c21285f491..86b2d4a31461 100644 --- a/rs/nns/governance/src/pb/conversions/mod.rs +++ b/rs/nns/governance/src/pb/conversions/mod.rs @@ -3987,6 +3987,7 @@ impl From for pb_api::NnsFunction { pb::NnsFunction::SetSubnetOperationalLevel => { pb_api::NnsFunction::SetSubnetOperationalLevel } + pb::NnsFunction::TakeCanisterSnapshot => pb_api::NnsFunction::TakeCanisterSnapshot, } } } @@ -4096,6 +4097,7 @@ impl From for pb::NnsFunction { pb_api::NnsFunction::SetSubnetOperationalLevel => { pb::NnsFunction::SetSubnetOperationalLevel } + pb_api::NnsFunction::TakeCanisterSnapshot => pb::NnsFunction::TakeCanisterSnapshot, } } } diff --git a/rs/nns/governance/src/proposals/execute_nns_function.rs b/rs/nns/governance/src/proposals/execute_nns_function.rs index 79f74f654e1f..0d8a47cac333 100644 --- a/rs/nns/governance/src/proposals/execute_nns_function.rs +++ b/rs/nns/governance/src/proposals/execute_nns_function.rs @@ -153,6 +153,7 @@ pub enum ValidNnsFunction { PauseCanisterMigrations, UnpauseCanisterMigrations, SetSubnetOperationalLevel, + TakeCanisterSnapshot, } impl ValidNnsFunction { @@ -281,6 +282,7 @@ impl ValidNnsFunction { ValidNnsFunction::SetSubnetOperationalLevel => { (REGISTRY_CANISTER_ID, "set_subnet_operational_level") } + ValidNnsFunction::TakeCanisterSnapshot => (ROOT_CANISTER_ID, "take_canister_snapshot"), } } @@ -341,6 +343,8 @@ impl ValidNnsFunction { ValidNnsFunction::AddSnsWasm | ValidNnsFunction::InsertSnsWasmUpgradePathEntries => { Topic::ServiceNervousSystemManagement } + + ValidNnsFunction::TakeCanisterSnapshot => Topic::ProtocolCanisterManagement, } } @@ -397,6 +401,7 @@ impl ValidNnsFunction { ValidNnsFunction::PauseCanisterMigrations => "Pause Canister Migrations", ValidNnsFunction::UnpauseCanisterMigrations => "Unpause Canister Migrations", ValidNnsFunction::SetSubnetOperationalLevel => "Set Subnet Operational Level", + ValidNnsFunction::TakeCanisterSnapshot => "Take Canister Snapshot", } } @@ -623,6 +628,11 @@ impl ValidNnsFunction { used to take a subnet offline or bring it back online as part of \ subnet recovery." } + ValidNnsFunction::TakeCanisterSnapshot => { + "A proposal to take a snapshot of a canister controlled the NNS. \ + For an introduction to canister snapshots in general, see \ + https://docs.internetcomputer.org/building-apps/canister-management/snapshots ." + } } } } @@ -711,6 +721,7 @@ impl TryFrom for ValidNnsFunction { NnsFunction::SetSubnetOperationalLevel => { Ok(ValidNnsFunction::SetSubnetOperationalLevel) } + NnsFunction::TakeCanisterSnapshot => Ok(ValidNnsFunction::TakeCanisterSnapshot), // Obsolete functions - based on check_obsolete NnsFunction::BlessReplicaVersion | NnsFunction::RetireReplicaVersion => { diff --git a/rs/nns/governance/unreleased_changelog.md b/rs/nns/governance/unreleased_changelog.md index 94126a0ff421..bee492f2761d 100644 --- a/rs/nns/governance/unreleased_changelog.md +++ b/rs/nns/governance/unreleased_changelog.md @@ -9,6 +9,10 @@ on the process that this file is part of, see ## Added +* New TakeCanisterSnapshot proposal type. Disabled for now, but will be enabled + in the not too distant future. For now, the declarations are in place (in + governance.did), which helps clients to get ready for this new proposal type. + ## Changed ## Deprecated