Skip to content

Commit

Permalink
fix: registry canister (#854)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
NikolaMilosa and github-actions[bot] authored Sep 3, 2024
1 parent e3b94ef commit 65e1de7
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 15 deletions.
18 changes: 17 additions & 1 deletion Cargo.Bazel.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"checksum": "76ee0866d5618a992b9197d6e283f29d8ae8c99652ea79b1025390bcd0d1ab07",
"checksum": "98c4b087938d37a4ae4cd08aa4c609f2abde672bb6e51a11137bd24fa1b6b40d",
"crates": {
"actix-codec 0.5.2": {
"name": "actix-codec",
Expand Down Expand Up @@ -16909,6 +16909,10 @@
"id": "ic-base-types 0.9.0",
"target": "ic_base_types"
},
{
"id": "ic-interfaces-registry 0.9.0",
"target": "ic_interfaces_registry"
},
{
"id": "ic-management-canister-types 0.9.0",
"target": "ic_management_canister_types"
Expand All @@ -16929,6 +16933,14 @@
"id": "ic-protobuf 0.9.0",
"target": "ic_protobuf"
},
{
"id": "ic-registry-keys 0.9.0",
"target": "ic_registry_keys"
},
{
"id": "ic-registry-nns-data-provider 0.9.0",
"target": "ic_registry_nns_data_provider"
},
{
"id": "ic-registry-transport 0.9.0",
"target": "ic_registry_transport"
Expand All @@ -16941,6 +16953,10 @@
"id": "ic-transport-types 0.37.1",
"target": "ic_transport_types"
},
{
"id": "ic-types 0.9.0",
"target": "ic_types"
},
{
"id": "ic-utils 0.37.0",
"target": "ic_utils"
Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions rs/ic-canisters/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ url = { workspace = true }
ic-sns-wasm = { workspace = true }
trustworthy-node-metrics-types = { workspace = true }
ic-transport-types = { workspace = true }
ic-registry-keys.workspace = true
ic-types.workspace = true
ic-interfaces-registry.workspace = true
ic-registry-nns-data-provider.workspace = true
70 changes: 63 additions & 7 deletions rs/ic-canisters/src/registry.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
use ic_agent::Agent;
use ic_base_types::PrincipalId;
use ic_interfaces_registry::RegistryTransportRecord;
use ic_nns_constants::REGISTRY_CANISTER_ID;
use ic_protobuf::registry::subnet::v1::SubnetListRecord;
use ic_registry_transport::pb::v1::{RegistryGetValueRequest, RegistryGetValueResponse};
use ic_protobuf::{
registry::{crypto::v1::PublicKey, subnet::v1::SubnetListRecord},
types::v1::SubnetId,
};
use ic_registry_keys::make_crypto_threshold_signing_pubkey_key;
use ic_registry_nns_data_provider::certification::decode_certified_deltas;
use ic_registry_transport::pb::v1::{
RegistryGetChangesSinceRequest, RegistryGetLatestVersionResponse, RegistryGetValueRequest, RegistryGetValueResponse,
};
use ic_types::crypto::threshold_sig::ThresholdSigPublicKey;
use prost::Message;

use crate::IcAgentCanisterClient;
Expand All @@ -23,23 +32,70 @@ impl RegistryCanisterWrapper {
}

pub async fn get_subnets(&self) -> anyhow::Result<Vec<PrincipalId>> {
let decoded_resp = self.get_value("subnet_list".to_string()).await?;

let mapped = SubnetListRecord::decode(decoded_resp.as_slice())?;

Ok(mapped.subnets.into_iter().map(|id: Vec<u8>| PrincipalId::try_from(id).unwrap()).collect())
}

pub async fn nns_subnet_id(&self) -> anyhow::Result<SubnetId> {
let decoded_resp = self.get_value("nns_subnet_id".to_string()).await?;

SubnetId::decode(decoded_resp.as_slice()).map_err(anyhow::Error::from)
}

pub async fn nns_public_key(&self) -> anyhow::Result<ThresholdSigPublicKey> {
let subnet_id = self.nns_subnet_id().await?;
let subnet_id = ic_types::SubnetId::new(ic_types::PrincipalId::try_from(
subnet_id.principal_id.ok_or(anyhow::anyhow!("Failed to find nns subnet id"))?.raw,
)?);

let decoded_resp = self.get_value(make_crypto_threshold_signing_pubkey_key(subnet_id)).await?;

ThresholdSigPublicKey::try_from(PublicKey::decode(decoded_resp.as_slice())?).map_err(anyhow::Error::from)
}

pub async fn get_latest_version(&self) -> anyhow::Result<u64> {
let response = self.agent.query(&REGISTRY_CANISTER_ID.into(), "get_latest_version").call().await?;

RegistryGetLatestVersionResponse::decode(response.as_slice())
.map_err(anyhow::Error::from)
.map(|r| r.version)
}

pub async fn get_certified_changes_since(&self, version: u64) -> anyhow::Result<Vec<RegistryTransportRecord>> {
let request = RegistryGetChangesSinceRequest { version };
let mut buf = vec![];
request.encode(&mut buf)?;

let response = self
.agent
.query(&REGISTRY_CANISTER_ID.into(), "get_certified_changes_since")
.with_arg(buf)
.call()
.await?;

decode_certified_deltas(version, &REGISTRY_CANISTER_ID, &self.nns_public_key().await?, response.as_slice())
.map_err(|e| anyhow::anyhow!("Error decoding certificed deltas: {:?}", e))
.map(|(res, _, _)| res)
}

async fn get_value(&self, request: String) -> anyhow::Result<Vec<u8>> {
let request = RegistryGetValueRequest {
key: "subnet_list".as_bytes().to_vec(),
key: request.as_bytes().to_vec(),
..Default::default()
};

let mut buf = vec![];
request.encode(&mut buf)?;

let response = self.agent.query(&REGISTRY_CANISTER_ID.into(), "get_value").with_arg(buf).call().await?;

let decoded_resp = RegistryGetValueResponse::decode(&response[..])?;
if let Some(error) = decoded_resp.error {
return Err(anyhow::anyhow!(error.reason));
}

let mapped = SubnetListRecord::decode(&decoded_resp.value[..])?;

Ok(mapped.subnets.into_iter().map(|id: Vec<u8>| PrincipalId::try_from(id).unwrap()).collect())
Ok(decoded_resp.value)
}
}
15 changes: 8 additions & 7 deletions rs/ic-management-backend/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use futures::future::BoxFuture;
use futures::TryFutureExt;
use ic_base_types::NodeId;
use ic_base_types::{RegistryVersion, SubnetId};
use ic_canisters::registry::RegistryCanisterWrapper;
use ic_canisters::IcAgentCanisterClient;
use ic_interfaces_registry::{RegistryClient, RegistryValue, ZERO_REGISTRY_VERSION};
use ic_management_types::{
Artifact, ArtifactReleases, Datacenter, DatacenterOwner, Guest, Network, NetworkError, Node, NodeProviderDetails, NodeProvidersResponse,
Expand Down Expand Up @@ -937,6 +939,8 @@ pub fn local_registry_path(network: &Network) -> PathBuf {
local_cache_path().join(Path::new(network.name.as_str())).join("local_registry")
}

#[allow(dead_code)]
// Probably will not be used anymore
pub async fn nns_public_key(registry_canister: &RegistryCanister) -> anyhow::Result<ThresholdSigPublicKey> {
let (nns_subnet_id_vec, _) = registry_canister
.get_value(ROOT_SUBNET_ID_KEY.as_bytes().to_vec(), None)
Expand All @@ -963,7 +967,8 @@ pub async fn sync_local_store(target_network: &Network) -> anyhow::Result<()> {
let local_registry_path = local_registry_path(target_network);
let local_store = Arc::new(LocalStoreImpl::new(local_registry_path.clone()));
let nns_urls = target_network.get_nns_urls().clone();
let registry_canister = RegistryCanister::new(nns_urls);
let agent = IcAgentCanisterClient::from_anonymous(nns_urls.first().unwrap().clone()).unwrap();
let registry_canister: RegistryCanisterWrapper = agent.into();
let mut local_latest_version = if !Path::new(&local_registry_path).exists() {
ZERO_REGISTRY_VERSION
} else {
Expand All @@ -972,7 +977,6 @@ pub async fn sync_local_store(target_network: &Network) -> anyhow::Result<()> {
registry_cache.get_latest_version()
};
let mut updates = vec![];
let nns_public_key = nns_public_key(&registry_canister).await?;

loop {
match registry_canister.get_latest_version().await {
Expand All @@ -998,13 +1002,10 @@ pub async fn sync_local_store(target_network: &Network) -> anyhow::Result<()> {
}
},
Err(e) => {
error!("Failed to get latest registry version: {}", e);
error!("Failed to get latest registry version: {:?}", e);
}
}
if let Ok((mut initial_records, _, _)) = registry_canister
.get_certified_changes_since(local_latest_version.get(), &nns_public_key)
.await
{
if let Ok(mut initial_records) = registry_canister.get_certified_changes_since(local_latest_version.get()).await {
initial_records.sort_by_key(|tr| tr.version);
let changelog = initial_records.iter().fold(Changelog::default(), |mut cl, r| {
let rel_version = (r.version - local_latest_version).get();
Expand Down

0 comments on commit 65e1de7

Please sign in to comment.