Skip to content
Open
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
4 changes: 2 additions & 2 deletions rs/nns/integration_tests/src/registry_get_changes_since.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn test_allow_opaque_caller() {
assert_eq!(error, None);
// The important thing is that deltas is not empty. The exact number of
// elements is not so important.
assert_eq!(deltas.len(), 14);
assert_eq!(deltas.len(), 13);
assert_eq!(version, 1);
}

Expand Down Expand Up @@ -70,6 +70,6 @@ fn test_allow_self_authenticating_caller() {
assert_eq!(error, None);
// The important thing is that deltas is not empty. The exact number of
// elements is not so important.
assert_eq!(deltas.len(), 14);
assert_eq!(deltas.len(), 13);
assert_eq!(version, 1);
}
4 changes: 2 additions & 2 deletions rs/nns/integration_tests/src/upgrades_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,14 @@ fn test_submit_and_accept_update_elected_replica_versions_proposal() {
),
(
retire_version_payload(vec![version_to_elect_and_unelect1, default_version]),
Some("currently deployed to a subnet"),
Some("Using a version that isn't elected"),
),
(
update_versions_payload(
Some(version_to_elect.into()),
vec![version_to_elect_and_unelect1, unassigned_nodes_version],
),
Some("currently deployed to unassigned nodes"),
Some("Using a version that isn't elected"),
),
(
ReviseElectedGuestosVersionsPayload {
Expand Down
19 changes: 2 additions & 17 deletions rs/nns/test_utils/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use ic_protobuf::registry::{
dc::v1::DataCenterRecord,
node::v1::{ConnectionEndpoint, NodeRecord},
node_operator::v1::NodeOperatorRecord,
replica_version::v1::{BlessedReplicaVersions, ReplicaVersionRecord},
replica_version::v1::ReplicaVersionRecord,
routing_table::v1::RoutingTable as RoutingTablePB,
subnet::v1::{
CatchUpPackageContents, ChainKeyConfig, InitialNiDkgTranscriptRecord, SubnetListRecord,
Expand All @@ -36,8 +36,7 @@ use ic_protobuf::registry::{
};
use ic_registry_canister_api::{AddNodePayload, Chunk, GetChunkRequest};
use ic_registry_keys::{
make_blessed_replica_versions_key, make_canister_ranges_key,
make_catch_up_package_contents_key, make_crypto_node_key,
make_canister_ranges_key, make_catch_up_package_contents_key, make_crypto_node_key,
make_crypto_threshold_signing_pubkey_key, make_crypto_tls_cert_key,
make_data_center_record_key, make_node_operator_record_key, make_node_record_key,
make_replica_version_key, make_subnet_list_record_key, make_subnet_record_key,
Expand Down Expand Up @@ -354,9 +353,6 @@ pub fn invariant_compliant_mutation_with_subnet_id(
release_package_urls: vec![release_package_url],
guest_launch_measurements: None,
};
let blessed_replica_version = BlessedReplicaVersions {
blessed_version_ids: vec![replica_version_id.clone()],
};

let subnet_list = SubnetListRecord {
subnets: vec![subnet_pid.get().to_vec()],
Expand Down Expand Up @@ -386,10 +382,6 @@ pub fn invariant_compliant_mutation_with_subnet_id(
make_replica_version_key(replica_version_id).as_bytes(),
replica_version.encode_to_vec(),
),
insert(
make_blessed_replica_versions_key().as_bytes(),
blessed_replica_version.encode_to_vec(),
),
insert(
ic_registry_keys::NODE_REWARDS_TABLE_KEY.as_bytes(),
rewards_table.encode_to_vec(),
Expand Down Expand Up @@ -631,9 +623,6 @@ pub fn initial_mutations_for_a_multinode_nns_subnet() -> Vec<RegistryMutation> {
release_package_urls: vec![release_package_url],
guest_launch_measurements,
};
let blessed_replica_version = BlessedReplicaVersions {
blessed_version_ids: vec![replica_version_id.clone()],
};
let subnet_list = SubnetListRecord {
subnets: vec![nns_subnet_id.get().to_vec()],
};
Expand Down Expand Up @@ -670,10 +659,6 @@ pub fn initial_mutations_for_a_multinode_nns_subnet() -> Vec<RegistryMutation> {
make_replica_version_key(replica_version_id).as_bytes(),
replica_version.encode_to_vec(),
),
insert(
make_blessed_replica_versions_key().as_bytes(),
blessed_replica_version.encode_to_vec(),
),
];

for nor in &node_operator {
Expand Down
2 changes: 1 addition & 1 deletion rs/prep/src/bin/prep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ struct CliArgs {
pub max_block_payload_size: Option<u64>,

/// if release-package-download-url is not specified and this option is
/// specified, the corresponding update image field in the blessed replica
/// specified, the corresponding update image field in the elected replica
/// version record is left empty.
#[clap(long)]
pub allow_empty_update_image: bool,
Expand Down
31 changes: 7 additions & 24 deletions rs/prep/src/internet_computer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ use ic_interfaces_registry::{RegistryDataProvider, RegistryRecord, ZERO_REGISTRY

use ic_protobuf::registry::replica_version::v1::GuestLaunchMeasurements;
use ic_protobuf::registry::{
api_boundary_node::v1::ApiBoundaryNodeRecord,
dc::v1::DataCenterRecord,
api_boundary_node::v1::ApiBoundaryNodeRecord, dc::v1::DataCenterRecord,
node_operator::v1::NodeOperatorRecord,
provisional_whitelist::v1::ProvisionalWhitelist as PbProvisionalWhitelist,
replica_version::v1::{BlessedReplicaVersions, ReplicaVersionRecord},
routing_table::v1::RoutingTable as PbRoutingTable,
subnet::v1::SubnetListRecord,
unassigned_nodes_config::v1::UnassignedNodesConfigRecord,
replica_version::v1::ReplicaVersionRecord, routing_table::v1::RoutingTable as PbRoutingTable,
subnet::v1::SubnetListRecord, unassigned_nodes_config::v1::UnassignedNodesConfigRecord,
};
use ic_protobuf::registry::{
dc::v1::Gps,
Expand All @@ -44,10 +41,9 @@ use ic_protobuf::types::v1::{PrincipalId as PrincipalIdProto, SubnetId as Subnet
use ic_registry_client::client::RegistryDataProviderError;
use ic_registry_keys::{
FirewallRulesScope, ROOT_SUBNET_ID_KEY, make_api_boundary_node_record_key,
make_blessed_replica_versions_key, make_canister_ranges_key, make_data_center_record_key,
make_firewall_rules_record_key, make_node_operator_record_key,
make_provisional_whitelist_record_key, make_replica_version_key, make_subnet_list_record_key,
make_unassigned_nodes_config_record_key,
make_canister_ranges_key, make_data_center_record_key, make_firewall_rules_record_key,
make_node_operator_record_key, make_provisional_whitelist_record_key, make_replica_version_key,
make_subnet_list_record_key, make_unassigned_nodes_config_record_key,
};
use ic_registry_local_store::{Changelog, KeyMutation, LocalStoreImpl, LocalStoreWriter};
use ic_registry_proto_data_provider::ProtoRegistryDataProvider;
Expand Down Expand Up @@ -257,7 +253,7 @@ pub struct IcConfig {
target_dir: PathBuf,
pub topology_config: TopologyConfig,
/// When a node starts up, the orchestrator fetches the replica binary found
/// at the URL in the blessed version record that carries the version
/// at the URL in the elected version record that carries the version
/// id referred to in the subnet record that the node belongs to.
///
/// The following are parameters used for all subnets in the initial
Expand Down Expand Up @@ -650,17 +646,12 @@ impl IcConfig {
opt_url.map(|u| vec![u.to_string()]).unwrap_or_default()
}

let initial_replica_version = self.initial_replica_version_id.to_string();
let replica_version_record = ReplicaVersionRecord {
release_package_sha256_hex: self.initial_release_package_sha256_hex.unwrap_or_default(),
release_package_urls: opturl_to_string_vec(self.initial_release_package_url),
guest_launch_measurements: self.guest_launch_measurements,
};

let blessed_replica_versions_record = BlessedReplicaVersions {
blessed_version_ids: vec![initial_replica_version],
};

write_registry_entry(
&data_provider,
self.target_dir.as_path(),
Expand All @@ -669,14 +660,6 @@ impl IcConfig {
replica_version_record,
);

write_registry_entry(
&data_provider,
self.target_dir.as_path(),
&make_blessed_replica_versions_key(),
version,
blessed_replica_versions_record,
);

let provisional_whitelist = match self.provisional_whitelist {
Some(list) => list,
// The principal id below is the one corresponding to the hardcoded key in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,18 @@ use crate::{common::LOG_PREFIX, registry::Registry};
use candid::{CandidType, Deserialize};
#[cfg(target_arch = "wasm32")]
use dfn_core::println;
use ic_base_types::{PrincipalId, SubnetId};
use ic_protobuf::registry::replica_version::v1::GuestLaunchMeasurements;
use ic_protobuf::registry::{
replica_version::v1::{BlessedReplicaVersions, ReplicaVersionRecord},
subnet::v1::{SubnetListRecord, SubnetRecord},
unassigned_nodes_config::v1::UnassignedNodesConfigRecord,
};
use ic_registry_keys::{
make_blessed_replica_versions_key, make_replica_version_key, make_subnet_list_record_key,
make_subnet_record_key, make_unassigned_nodes_config_record_key,
};
use ic_protobuf::registry::replica_version::v1::ReplicaVersionRecord;
use ic_registry_keys::make_replica_version_key;
use ic_registry_transport::pb::v1::{RegistryMutation, registry_mutation};
use prost::Message;
use serde::Serialize;

impl Registry {
/// Update the elected replica versions by:
/// a) Adding a new replica version to the registry and blessing it, i.e.,
/// adding the version's ID to the list of blessed replica versions.
/// a) Adding a new replica version to the registry
///
/// b) Removing specified replica versions from the registry and retiring them, i.e.,
/// removing the versions' IDs from the list of blessed replica versions.
/// b) Removing specified replica versions from the registry
///
/// This method is called by the governance canister, after a proposal
/// for updating the elected replica versions has been accepted.
Expand All @@ -52,17 +42,12 @@ impl Registry {
})
.collect();

let mut versions = self.remove_blessed_versions_or_panic(&versions_to_remove);

if let Some(version) = payload.replica_version_to_elect.as_ref() {
assert!(
!versions_to_remove.contains(version),
"{LOG_PREFIX}ReviseElectedGuestosVersionsPayload cannot elect and unelect the same version.",
);

versions.push(version.clone());
println!("{LOG_PREFIX}Blessed versions after append: {versions:?}");

mutations.push(
// Register the new version (that is, insert the new ReplicaVersionRecord)
RegistryMutation {
Expand All @@ -82,109 +67,9 @@ impl Registry {
);
}

mutations.push(
// Update the list of blessed versions
RegistryMutation {
mutation_type: registry_mutation::Type::Upsert as i32,
key: make_blessed_replica_versions_key().as_bytes().to_vec(),
value: BlessedReplicaVersions {
blessed_version_ids: versions,
}
.encode_to_vec(),
},
);

// Check invariants before applying mutations
self.maybe_apply_mutation_internal(mutations);
}

/// Try to remove the given versions from registry. Panic if any of them are in
/// use by a subnet or unassigned nodes. Return the list of blessed version IDs
/// that remain after removal.
pub fn remove_blessed_versions_or_panic(
&self,
versions_to_remove: &BTreeSet<String>,
) -> Vec<String> {
let version = self.latest_version();
let before_removal = self.get_blessed_replica_version_ids();

let after_removal: Vec<String> = before_removal
.iter()
.filter(|&v| !versions_to_remove.contains(v))
.cloned()
.collect();

if before_removal.len() == after_removal.len() {
return after_removal;
}

// Get all subnet records
let subnets_key = make_subnet_list_record_key();
let subnets = self
.get(subnets_key.as_bytes(), version)
.map(|reg_value| {
SubnetListRecord::decode(reg_value.value.as_slice())
.unwrap()
.subnets
})
.unwrap_or_default();

// Try to find a replica version that is both, part of the payload and used by a subnet
let in_use = subnets
.iter()
.map(|id| {
let subnet_id = SubnetId::new(PrincipalId::try_from(id).unwrap());
let subnet_key = make_subnet_record_key(subnet_id);
let reg_value = self.get(subnet_key.as_bytes(), version).unwrap();
SubnetRecord::decode(reg_value.value.as_slice())
.unwrap()
.replica_version_id
})
.filter(|id| versions_to_remove.contains(id))
.collect::<BTreeSet<String>>();

if !in_use.is_empty() {
panic!(
"{LOG_PREFIX}Cannot retire versions {in_use:?}, because they are currently deployed to a subnet!"
);
}

// Do the same for unassigned node record
let unassigned_key = make_unassigned_nodes_config_record_key();
let in_use = self
.get(unassigned_key.as_bytes(), version)
.map(|reg_value| {
UnassignedNodesConfigRecord::decode(reg_value.value.as_slice())
.unwrap()
.replica_version
})
.filter(|id| versions_to_remove.contains(id));

if let Some(version) = in_use {
panic!(
"{LOG_PREFIX}Cannot retire version {version}, because it is currently deployed to unassigned nodes!"
);
}

println!(
"{LOG_PREFIX}Blessed versions before: {before_removal:?} and after: {after_removal:?}"
);

after_removal
}

pub fn get_blessed_replica_version_ids(&self) -> Vec<String> {
self.get(
make_blessed_replica_versions_key().as_bytes(),
self.latest_version(),
)
.map(|reg_value| {
BlessedReplicaVersions::decode(reg_value.value.as_slice())
.expect("Failed to decode BlessedReplicaVersions")
.blessed_version_ids
})
.expect("BlessedReplicaVersions key not found in registry")
}
}

/// The payload of a proposal to update elected replica versions.
Expand Down
5 changes: 0 additions & 5 deletions rs/registry/keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,6 @@ pub fn make_hostos_version_key<S: AsRef<str>>(hostos_version_id: S) -> String {
)
}

/// Returns the only key whose payload is the list of blessed replica versions.
pub fn make_blessed_replica_versions_key() -> String {
"blessed_replica_versions".to_string()
}

pub fn make_routing_table_record_key() -> String {
"routing_table".to_string()
}
Expand Down
26 changes: 3 additions & 23 deletions rs/test_utilities/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use ic_limits::INITIAL_NOTARY_DELAY;
use ic_management_canister_types_private::VetKdKeyId;
use ic_protobuf::registry::crypto::v1::AlgorithmId;
use ic_protobuf::registry::crypto::v1::PublicKey as PublicKeyProto;
use ic_protobuf::registry::replica_version::v1::{BlessedReplicaVersions, ReplicaVersionRecord};
use ic_protobuf::registry::replica_version::v1::ReplicaVersionRecord;
use ic_protobuf::registry::subnet::v1::ChainKeyInitialization;
use ic_protobuf::registry::subnet::v1::chain_key_initialization::Initialization;
use ic_protobuf::registry::subnet::v1::{
Expand All @@ -14,9 +14,8 @@ use ic_protobuf::registry::subnet::v1::{
use ic_protobuf::types::v1::{PrincipalId as PrincipalIdPb, master_public_key_id::KeyId};
use ic_registry_client_fake::FakeRegistryClient;
use ic_registry_keys::{
make_blessed_replica_versions_key, make_catch_up_package_contents_key,
make_crypto_threshold_signing_pubkey_key, make_replica_version_key,
make_subnet_list_record_key, make_subnet_record_key,
make_catch_up_package_contents_key, make_crypto_threshold_signing_pubkey_key,
make_replica_version_key, make_subnet_list_record_key, make_subnet_record_key,
};
use ic_registry_local_store::{LocalStoreImpl, compact_delta_to_changelog};
use ic_registry_proto_data_provider::ProtoRegistryDataProvider;
Expand Down Expand Up @@ -85,25 +84,6 @@ pub fn setup_registry_non_final(
(registry_data_provider, registry)
}

/// Add blessed replica versions to the registry.
pub fn add_blessed_replica_versions(
registry_data_provider: &Arc<ProtoRegistryDataProvider>,
version: u64,
blessed_version_ids: &[&str],
) {
let registry_version = RegistryVersion::from(version);
let blessed_versions = BlessedReplicaVersions {
blessed_version_ids: blessed_version_ids.iter().map(|x| x.to_string()).collect(),
};
registry_data_provider
.add(
&make_blessed_replica_versions_key(),
registry_version,
Some(blessed_versions),
)
.expect("Failed to add blessed replica versions.");
}

/// Add a replica version record to the registry.
pub fn add_replica_version_record(
registry_data_provider: &Arc<ProtoRegistryDataProvider>,
Expand Down
Loading