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
18 changes: 18 additions & 0 deletions rs/nns/governance/src/proposals/execute_nns_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ use ic_nns_constants::{
};
use std::sync::Arc;

/// A partial Candid interface for the management canister (ic_00) that contains the necessary
/// methods for all the ExecuteNnsFunction proposals. Currently, only the uninstall_code method is
/// supported.
const PARTIAL_IC_00_CANDID: &str = r#"type uninstall_code_args = record {
canister_id : principal;
sender_canister_version : opt nat64;
};
service ic : {
uninstall_code : (uninstall_code_args) -> ();
}"#;

Comment on lines +20 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not copy this and instead, source the whole thing from an authoritative location?

#[derive(Debug, Clone, PartialEq)]
pub struct ValidExecuteNnsFunction {
pub nns_function: ValidNnsFunction,
Expand Down Expand Up @@ -72,6 +83,13 @@ impl ValidExecuteNnsFunction {

async fn get_candid_source(&self, env: Arc<dyn Environment>) -> Result<String, String> {
let (canister_id, _method_name) = self.nns_function.canister_and_function();

// The management canister (ic_00) doesn't expose candid:service metadata, so we return a
// hard-coded DID file for it.
Comment on lines +87 to +88
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sad.

if canister_id == CanisterId::ic_00() {
return Ok(PARTIAL_IC_00_CANDID.to_string());
}

let request = CanisterMetadataRequest::new(canister_id, "candid:service".to_string());
let encoded_request = Encode!(&request).expect("Failed to encode payload");
let response = env
Expand Down
46 changes: 45 additions & 1 deletion rs/nns/governance/src/proposals/execute_nns_function_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
},
test_utils::{ExpectedCallCanisterMethodCallArguments, MockEnvironment},
};
use candid::Encode;
use candid::{Encode, Nat};
use ic_base_types::CanisterId;
use ic_management_canister_types_private::{CanisterMetadataRequest, CanisterMetadataResponse};
use ic_nns_constants::CYCLES_MINTING_CANISTER_ID;
Expand Down Expand Up @@ -186,3 +186,47 @@ service : {
})
);
}

#[tokio::test]
async fn test_to_self_describing_uninstall_code() {
// Create the uninstall_code_args payload
#[derive(candid::CandidType)]
struct UninstallCodeArgs {
canister_id: CanisterId,
sender_canister_version: Option<u64>,
}

let target_canister = CanisterId::from_u64(123);
let arg = UninstallCodeArgs {
canister_id: target_canister,
sender_canister_version: Some(42),
};
let payload = Encode!(&arg).unwrap();

let execute_nns_function = ValidExecuteNnsFunction {
nns_function: ValidNnsFunction::UninstallCode,
payload,
};

// No canister_metadata call expected a hard-coded DID file is used instead.
let env = Arc::new(MockEnvironment::new(vec![], 0));

let proposal_action = ValidProposalAction::ExecuteNnsFunction(execute_nns_function);
let result = proposal_action.to_self_describing(env).await.unwrap();

assert_eq!(result.type_name, "Uninstall Code");
assert!(
result
.type_description
.contains("Uninstall code of a canister")
);
assert_eq!(
SelfDescribingValue::from(result.value.unwrap()),
SelfDescribingValue::Map(hashmap! {
"canister_id".to_string() => SelfDescribingValue::Text("2uzo4-eaaaa-aaaaa-aab5q-cai".to_string()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"canister_id".to_string() => SelfDescribingValue::Text("2uzo4-eaaaa-aaaaa-aab5q-cai".to_string()),
"canister_id".to_string() => SelfDescribingValue::Text(target_canister.to_str().to_string()),

"sender_canister_version".to_string() => SelfDescribingValue::Array(vec![
SelfDescribingValue::Nat(Nat::from(42u64)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SelfDescribingValue::Nat(Nat::from(42u64)),
SelfDescribingValue::Nat(Nat::from(42_u64)),

]),
})
);
}
Loading