Skip to content

Commit 1edf4a1

Browse files
authored
feat(sns): Automatically advance SNS target version upon opt-in (dfinity#3119)
This PR implements a simple extension of the AdvanceSnsTargetVersion mechanism, allowing SNSs to opt-in for getting target versions advanced to the latest available SNS version blessed by the NNS community.
1 parent 9220172 commit 1edf4a1

File tree

13 files changed

+182
-10
lines changed

13 files changed

+182
-10
lines changed

rs/nervous_system/integration_tests/tests/advance_sns_target_version.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ async fn test_get_upgrade_journal() {
180180

181181
expected_upgrade_journal_entries.push(Event::TargetVersionSet(TargetVersionSet::new(
182182
None,
183-
Some(new_sns_version_2.clone()),
183+
new_sns_version_2.clone(),
184+
false,
184185
)));
185186

186187
sns::governance::assert_upgrade_journal(

rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,9 @@ pub struct NervousSystemParameters {
10761076
/// that the PB default (bool fields are false) and our application default
10771077
/// (enabled) agree.
10781078
pub maturity_modulation_disabled: Option<bool>,
1079+
/// Whether to automatically advance the SNS target version after a new upgrade is published
1080+
/// by the NNS. If not specified, defaults to false for backward compatibility.
1081+
pub automatically_advance_target_version: Option<bool>,
10791082
}
10801083
#[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, Copy, PartialEq)]
10811084
pub struct VotingRewardsParameters {
@@ -2236,6 +2239,7 @@ pub mod upgrade_journal_entry {
22362239
pub struct TargetVersionSet {
22372240
pub old_target_version: Option<super::governance::Version>,
22382241
pub new_target_version: Option<super::governance::Version>,
2242+
pub is_advanced_automatically: Option<bool>,
22392243
}
22402244
#[derive(
22412245
candid::CandidType, candid::Deserialize, Debug, serde::Serialize, Clone, PartialEq,

rs/sns/governance/canister/governance.did

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ type NervousSystemParameters = record {
481481
voting_rewards_parameters : opt VotingRewardsParameters;
482482
maturity_modulation_disabled : opt bool;
483483
max_number_of_principals_per_neuron : opt nat64;
484+
automatically_advance_target_version : opt bool;
484485
};
485486

486487
type Neuron = record {
@@ -784,6 +785,7 @@ type UpgradeStepsReset = record {
784785
type TargetVersionSet = record {
785786
new_target_version : opt Version;
786787
old_target_version : opt Version;
788+
is_advanced_automatically : opt bool;
787789
};
788790

789791
type TargetVersionReset = record {

rs/sns/governance/canister/governance_test.did

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ type NervousSystemParameters = record {
495495
voting_rewards_parameters : opt VotingRewardsParameters;
496496
maturity_modulation_disabled : opt bool;
497497
max_number_of_principals_per_neuron : opt nat64;
498+
automatically_advance_target_version : opt bool;
498499
};
499500

500501
type Neuron = record {
@@ -798,6 +799,7 @@ type UpgradeStepsReset = record {
798799
type TargetVersionSet = record {
799800
new_target_version : opt Version;
800801
old_target_version : opt Version;
802+
is_advanced_automatically : opt bool;
801803
};
802804

803805
type TargetVersionReset = record {

rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,10 @@ message NervousSystemParameters {
10991099
// that the PB default (bool fields are false) and our application default
11001100
// (enabled) agree.
11011101
optional bool maturity_modulation_disabled = 22;
1102+
1103+
// Whether to automatically advance the SNS target version after a new upgrade is published
1104+
// by the NNS. If not specified, defaults to false for backward compatibility.
1105+
optional bool automatically_advance_target_version = 23;
11021106
}
11031107

11041108
message VotingRewardsParameters {
@@ -2244,6 +2248,7 @@ message UpgradeJournalEntry {
22442248
message TargetVersionSet {
22452249
optional Governance.Version old_target_version = 1;
22462250
optional Governance.Version new_target_version = 2;
2251+
optional bool is_advanced_automatically = 3;
22472252
}
22482253

22492254
message TargetVersionReset {

rs/sns/governance/src/cached_upgrade_steps.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,8 @@ impl Governance {
476476
true
477477
}
478478

479-
/// Refreshes the cached_upgrade_steps field
479+
/// Attempts to refresh the cached_upgrade_steps field and (if this SNS wants automatic
480+
/// deployment of upgrades), also the target_version.
480481
pub async fn refresh_cached_upgrade_steps(&mut self, deployed_version: Version) {
481482
let sns_governance_canister_id = self.env.canister_id().get();
482483

@@ -495,6 +496,26 @@ impl Governance {
495496
}
496497
};
497498

499+
if self.should_automatically_advance_target_version()
500+
&& upgrade_steps.has_pending_upgrades()
501+
{
502+
let new_target = upgrade_steps.last().clone();
503+
504+
{
505+
let old_version = self.proto.target_version.clone();
506+
let new_target = new_target.clone();
507+
if old_version.as_ref() != Some(&new_target) {
508+
self.push_to_upgrade_journal(upgrade_journal_entry::TargetVersionSet::new(
509+
old_version,
510+
new_target,
511+
true,
512+
));
513+
}
514+
}
515+
516+
self.proto.target_version.replace(new_target);
517+
}
518+
498519
// This copy of the data would go to the upgrade journal for auditability.
499520
let versions = upgrade_steps.clone().into_iter().collect();
500521

rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,10 @@ pub struct NervousSystemParameters {
14731473
/// (enabled) agree.
14741474
#[prost(bool, optional, tag = "22")]
14751475
pub maturity_modulation_disabled: ::core::option::Option<bool>,
1476+
/// Whether to automatically advance the SNS target version after a new upgrade is published
1477+
/// by the NNS. If not specified, defaults to false for backward compatibility.
1478+
#[prost(bool, optional, tag = "23")]
1479+
pub automatically_advance_target_version: ::core::option::Option<bool>,
14761480
}
14771481
#[derive(
14781482
candid::CandidType,
@@ -3547,6 +3551,8 @@ pub mod upgrade_journal_entry {
35473551
pub old_target_version: ::core::option::Option<super::governance::Version>,
35483552
#[prost(message, optional, tag = "2")]
35493553
pub new_target_version: ::core::option::Option<super::governance::Version>,
3554+
#[prost(bool, optional, tag = "3")]
3555+
pub is_advanced_automatically: ::core::option::Option<bool>,
35503556
}
35513557
#[derive(
35523558
candid::CandidType,

rs/sns/governance/src/governance.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3106,11 +3106,14 @@ impl Governance {
31063106
let (_, target_version) = self
31073107
.proto
31083108
.validate_new_target_version(Some(new_target))
3109-
.map_err(|err| GovernanceError::new_with_message(ErrorType::InvalidProposal, err))?;
3109+
.map_err(|err: String| {
3110+
GovernanceError::new_with_message(ErrorType::InvalidProposal, err)
3111+
})?;
31103112

31113113
self.push_to_upgrade_journal(upgrade_journal_entry::TargetVersionSet::new(
31123114
self.proto.target_version.clone(),
3113-
Some(target_version.clone()),
3115+
target_version.clone(),
3116+
false,
31143117
));
31153118

31163119
self.proto.target_version = Some(target_version);
@@ -3123,6 +3126,16 @@ impl Governance {
31233126
self.proto.parameters.as_ref()
31243127
}
31253128

3129+
pub fn should_automatically_advance_target_version(&self) -> bool {
3130+
self.nervous_system_parameters()
3131+
.map(|nervous_system_parameters| {
3132+
nervous_system_parameters
3133+
.automatically_advance_target_version
3134+
.unwrap_or_default()
3135+
})
3136+
.unwrap_or_default()
3137+
}
3138+
31263139
/// Returns the NervousSystemParameters or panics
31273140
fn nervous_system_parameters_or_panic(&self) -> &NervousSystemParameters {
31283141
self.nervous_system_parameters()

rs/sns/governance/src/governance/advance_target_sns_version_tests.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,84 @@ fn get_or_reset_upgrade_steps_leads_to_should_refresh_cached_upgrade_steps() {
926926
assert!(gov.should_refresh_cached_upgrade_steps());
927927
}
928928

929+
#[tokio::test]
930+
async fn test_refresh_cached_upgrade_steps_advances_target_version_automatically_is_required() {
931+
let version_a = Version {
932+
root_wasm_hash: vec![1, 2, 3],
933+
governance_wasm_hash: vec![2, 3, 4],
934+
ledger_wasm_hash: vec![3, 4, 5],
935+
swap_wasm_hash: vec![4, 5, 6],
936+
archive_wasm_hash: vec![5, 6, 7],
937+
index_wasm_hash: vec![6, 7, 8],
938+
};
939+
let mut version_b = version_a.clone();
940+
version_b.root_wasm_hash = vec![9, 9, 9];
941+
942+
// Smoke test.
943+
assert_ne!(version_a, version_b);
944+
945+
let make_gov = || -> Governance {
946+
let mut env = NativeEnvironment::new(Some(*TEST_GOVERNANCE_CANISTER_ID));
947+
add_environment_mock_list_upgrade_steps_call(
948+
&mut env,
949+
vec![
950+
SnsVersion::from(version_a.clone()),
951+
SnsVersion::from(version_b.clone()),
952+
],
953+
);
954+
Governance::new(
955+
GovernanceProto {
956+
deployed_version: Some(version_a.clone()),
957+
cached_upgrade_steps: None,
958+
..basic_governance_proto()
959+
}
960+
.try_into()
961+
.unwrap(),
962+
Box::new(env),
963+
Box::new(DoNothingLedger {}),
964+
Box::new(DoNothingLedger {}),
965+
Box::new(FakeCmc::new()),
966+
)
967+
};
968+
969+
for (automatically_advance_target_version, expected_target_version) in [
970+
(None, None),
971+
(Some(false), None),
972+
(Some(true), Some(version_b.clone())),
973+
] {
974+
let mut gov = make_gov();
975+
976+
if let Some(parameters) = gov.proto.parameters.as_mut() {
977+
parameters.automatically_advance_target_version = automatically_advance_target_version;
978+
};
979+
980+
// Precondition
981+
assert_eq!(gov.proto.cached_upgrade_steps, None);
982+
assert_eq!(gov.proto.target_version, None);
983+
984+
// Run code under test and assert intermediate conditions.
985+
let deployed_version = gov
986+
.try_temporarily_lock_refresh_cached_upgrade_steps()
987+
.unwrap();
988+
gov.refresh_cached_upgrade_steps(deployed_version).await;
989+
990+
// Intermediate postcondition.
991+
assert_eq!(
992+
gov.proto
993+
.cached_upgrade_steps
994+
.clone()
995+
.unwrap()
996+
.upgrade_steps
997+
.unwrap()
998+
.versions,
999+
vec![version_a.clone(), version_b.clone(),]
1000+
);
1001+
1002+
// Main postcondition.
1003+
assert_eq!(gov.proto.target_version, expected_target_version);
1004+
}
1005+
}
1006+
9291007
fn add_environment_mock_calls_for_initiate_upgrade(
9301008
env: &mut NativeEnvironment,
9311009
expected_wasm_hash_requested: Vec<u8>,

rs/sns/governance/src/pb/conversions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,7 @@ impl From<pb::NervousSystemParameters> for pb_api::NervousSystemParameters {
11231123
max_dissolve_delay_bonus_percentage: item.max_dissolve_delay_bonus_percentage,
11241124
max_age_bonus_percentage: item.max_age_bonus_percentage,
11251125
maturity_modulation_disabled: item.maturity_modulation_disabled,
1126+
automatically_advance_target_version: item.automatically_advance_target_version,
11261127
}
11271128
}
11281129
}
@@ -1150,6 +1151,7 @@ impl From<pb_api::NervousSystemParameters> for pb::NervousSystemParameters {
11501151
max_dissolve_delay_bonus_percentage: item.max_dissolve_delay_bonus_percentage,
11511152
max_age_bonus_percentage: item.max_age_bonus_percentage,
11521153
maturity_modulation_disabled: item.maturity_modulation_disabled,
1154+
automatically_advance_target_version: item.automatically_advance_target_version,
11531155
}
11541156
}
11551157
}
@@ -3222,6 +3224,7 @@ impl From<pb::upgrade_journal_entry::TargetVersionSet>
32223224
Self {
32233225
old_target_version: item.old_target_version.map(|x| x.into()),
32243226
new_target_version: item.new_target_version.map(|x| x.into()),
3227+
is_advanced_automatically: item.is_advanced_automatically,
32253228
}
32263229
}
32273230
}
@@ -3232,6 +3235,7 @@ impl From<pb_api::upgrade_journal_entry::TargetVersionSet>
32323235
Self {
32333236
old_target_version: item.old_target_version.map(|x| x.into()),
32343237
new_target_version: item.new_target_version.map(|x| x.into()),
3238+
is_advanced_automatically: item.is_advanced_automatically,
32353239
}
32363240
}
32373241
}

0 commit comments

Comments
 (0)