diff --git a/Cargo.lock b/Cargo.lock index 2d8516e738e..277b0bc34d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17765,6 +17765,7 @@ dependencies = [ "ic-cdk 0.16.0", "ic-certification 3.0.2", "ic-error-types", + "ic-management-canister-types", "ic-transport-types", "k256 0.13.4", "lazy_static", @@ -17886,6 +17887,7 @@ version = "0.9.0" dependencies = [ "candid", "ic-cdk 0.16.0", + "ic-management-canister-types", "serde", "serde_bytes", ] diff --git a/packages/pocket-ic/BUILD.bazel b/packages/pocket-ic/BUILD.bazel index 3cbe06bfe13..f3c9a2d6be9 100644 --- a/packages/pocket-ic/BUILD.bazel +++ b/packages/pocket-ic/BUILD.bazel @@ -33,6 +33,7 @@ MACRO_DEPENDENCIES = [ TEST_DEPENDENCIES = [ # Keep sorted. "//rs/types/error_types", + "//rs/types/management_canister_types", #TODO: try upgrading this to the latest bitcion crate "@crate_index//:bitcoin_0_28", "@crate_index//:candid_parser", diff --git a/packages/pocket-ic/Cargo.toml b/packages/pocket-ic/Cargo.toml index 2f607c8ed66..c369eabef50 100644 --- a/packages/pocket-ic/Cargo.toml +++ b/packages/pocket-ic/Cargo.toml @@ -56,3 +56,4 @@ ic-error-types = { path = "../../rs/types/error_types" } k256 = { workspace = true } lazy_static = { workspace = true } wat = { workspace = true } +ic-management-canister-types = { path = "../../rs/types/management_canister_types" } diff --git a/packages/pocket-ic/test_canister/BUILD.bazel b/packages/pocket-ic/test_canister/BUILD.bazel index 65f2948ca59..c40f6402a6a 100644 --- a/packages/pocket-ic/test_canister/BUILD.bazel +++ b/packages/pocket-ic/test_canister/BUILD.bazel @@ -6,6 +6,7 @@ rust_canister( service_file = ":canister.did", deps = [ # Keep sorted. + "//rs/types/management_canister_types", "@crate_index//:candid", "@crate_index//:ic-cdk", "@crate_index//:serde", diff --git a/packages/pocket-ic/test_canister/Cargo.toml b/packages/pocket-ic/test_canister/Cargo.toml index 2a2550e3f27..797d08c9680 100644 --- a/packages/pocket-ic/test_canister/Cargo.toml +++ b/packages/pocket-ic/test_canister/Cargo.toml @@ -15,3 +15,4 @@ candid = { workspace = true } ic-cdk = { workspace = true } serde = { workspace = true } serde_bytes = { workspace = true } +ic-management-canister-types = { path = "../../../rs/types/management_canister_types" } diff --git a/packages/pocket-ic/test_canister/canister.did b/packages/pocket-ic/test_canister/canister.did index f0e2766bcc7..4cf647d6a24 100644 --- a/packages/pocket-ic/test_canister/canister.did +++ b/packages/pocket-ic/test_canister/canister.did @@ -98,6 +98,22 @@ type TransformArgs = record { context : blob; }; +type NodeMetricsHistoryArgs = record { + subnet_id: principal; + start_at_timestamp_nanos: nat64; +}; + +type NodeMetrics = record { + node_id: principal; + num_blocks_proposed_total: nat64; + num_block_failures_total: nat64; +}; + +type NodeMetricsHistoryResponse = record { + timestamp_nanos: nat64; + node_metrics: vec NodeMetrics; +}; + service : { http_request: (request: HttpGatewayRequest) -> (HttpGatewayResponse) query; schnorr_public_key : (opt principal, vec blob, SchnorrKeyId) -> (SchnorrPublicKeyResult); @@ -107,6 +123,7 @@ service : { canister_http : () -> (HttpResponseResult); canister_http_with_transform : () -> (HttpResponse); transform : (TransformArgs) -> (HttpResponse) query; + node_metrics_history_proxy: (NodeMetricsHistoryArgs) -> (vec NodeMetricsHistoryResponse) query; whoami : () -> (text); whois : (principal) -> (text); blob_len : (blob) -> (nat64); diff --git a/packages/pocket-ic/test_canister/src/canister.rs b/packages/pocket-ic/test_canister/src/canister.rs index 239803ea47b..3aa47006ac3 100644 --- a/packages/pocket-ic/test_canister/src/canister.rs +++ b/packages/pocket-ic/test_canister/src/canister.rs @@ -1,5 +1,5 @@ use candid::{define_function, CandidType, Principal}; -use ic_cdk::api::call::{accept_message, arg_data_raw, reject, RejectionCode}; +use ic_cdk::api::call::{accept_message, arg_data_raw, reject, CallResult, RejectionCode}; use ic_cdk::api::instruction_counter; use ic_cdk::api::management_canister::ecdsa::{ ecdsa_public_key as ic_cdk_ecdsa_public_key, sign_with_ecdsa as ic_cdk_sign_with_ecdsa, @@ -10,9 +10,9 @@ use ic_cdk::api::management_canister::http_request::{ TransformArgs, TransformContext, TransformFunc, }; use ic_cdk::{inspect_message, query, trap, update}; +use ic_management_canister_types::{NodeMetricsHistoryArgs, NodeMetricsHistoryResponse}; use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; - // HTTP gateway interface pub type HeaderField = (String, String); @@ -267,6 +267,21 @@ async fn canister_http_with_transform() -> HttpResponse { // inter-canister calls +#[query] +async fn node_metrics_history_proxy( + args: NodeMetricsHistoryArgs, +) -> Vec { + ic_cdk::api::call::call_with_payment128::<_, (Vec,)>( + candid::Principal::management_canister(), + "node_metrics_history", + (args,), + 0_u128, + ) + .await + .unwrap() + .0 +} + #[update] async fn whoami() -> String { ic_cdk::id().to_string() diff --git a/packages/pocket-ic/tests/tests.rs b/packages/pocket-ic/tests/tests.rs index 21ac2e65250..8735df8669e 100644 --- a/packages/pocket-ic/tests/tests.rs +++ b/packages/pocket-ic/tests/tests.rs @@ -1,11 +1,14 @@ use candid::{decode_one, encode_one, CandidType, Decode, Deserialize, Encode, Principal}; use ic_certification::Label; +use ic_management_canister_types::NodeMetricsHistoryResponse; use ic_transport_types::Envelope; use ic_transport_types::EnvelopeContent::ReadState; +use pocket_ic::common::rest::{BlockMakerConfigs, RawSubnetBlockmakerMetrics, TickConfigs}; use pocket_ic::management_canister::{ CanisterIdRecord, CanisterInstallMode, CanisterSettings, EcdsaPublicKeyResult, - HttpRequestResult, ProvisionalCreateCanisterWithCyclesArgs, SchnorrAlgorithm, - SchnorrPublicKeyArgsKeyId, SchnorrPublicKeyResult, SignWithBip341Aux, SignWithSchnorrAux, + HttpRequestResult, NodeMetricsHistoryArgs, ProvisionalCreateCanisterWithCyclesArgs, + SchnorrAlgorithm, SchnorrPublicKeyArgsKeyId, SchnorrPublicKeyResult, SignWithBip341Aux, + SignWithSchnorrAux, }; use pocket_ic::{ common::rest::{ @@ -2214,3 +2217,70 @@ fn test_reject_response_type() { assert!(!err.certified); } } + +#[test] +fn test_custom_blockmaker() { + // Setup PocketIC with initial subnets and records + let pocket_ic = PocketIcBuilder::new().with_application_subnet().build(); + + let topology = pocket_ic.topology(); + let application_subnet = topology.get_app_subnets()[0]; + + // We create a canister on the app subnet. + let canister = pocket_ic.create_canister_on_subnet(None, None, application_subnet); + // We top up the canister with cycles and install the test canister WASM to them. + pocket_ic.add_cycles(canister, INIT_CYCLES); + pocket_ic.install_canister(canister, test_canister_wasm(), vec![], None); + + let blockmaker_node = topology + .subnet_configs + .get(&application_subnet) + .unwrap() + .node_ids[0] + .clone(); + + let subnets_blockmakers = vec![RawSubnetBlockmakerMetrics { + subnet: application_subnet.into(), + blockmaker: blockmaker_node, + failed_blockmakers: vec![], + }]; + + let tick_configs = TickConfigs { + blockmakers: Some(BlockMakerConfigs { + blockmakers_per_subnet: subnets_blockmakers, + }), + }; + + pocket_ic.tick_with_configs(tick_configs.clone()); + pocket_ic.tick_with_configs(tick_configs.clone()); + pocket_ic.tick_with_configs(tick_configs.clone()); + pocket_ic.tick_with_configs(tick_configs.clone()); + pocket_ic.tick_with_configs(tick_configs.clone()); + + pocket_ic + //go to next day it should have recorder the metrics + .advance_time(std::time::Duration::from_secs(60 * 60 * 25)); + + pocket_ic.tick(); + pocket_ic.tick(); + pocket_ic.tick(); + pocket_ic.tick(); + pocket_ic.tick(); + + let response = pocket_ic + .query_call( + canister, + Principal::anonymous(), + "node_metrics_history_proxy", + Encode!(&NodeMetricsHistoryArgs { + subnet_id: application_subnet, + start_at_timestamp_nanos: 0, + }) + .unwrap(), + ) + .unwrap(); + + let res = Decode!(&response, Vec).unwrap(); + println!("{:?}", res); + assert!(false); +} diff --git a/rs/pocket_ic_server/tests/test.rs b/rs/pocket_ic_server/tests/test.rs index 6a870d5cdf6..26a44304b0d 100644 --- a/rs/pocket_ic_server/tests/test.rs +++ b/rs/pocket_ic_server/tests/test.rs @@ -1058,69 +1058,6 @@ fn test_query_stats_live() { }) } -#[test] -fn test_custom_blockmaker() { - // Setup PocketIC with initial subnets and records - let pocket_ic = PocketIcBuilder::new() - .with_nns_subnet() - .with_application_subnet() - .build(); - - let topology = pocket_ic.topology(); - let application_subnet = topology.get_app_subnets()[0]; - let blockmaker_node = topology - .subnet_configs - .get(&application_subnet) - .unwrap() - .node_ids[0] - .clone(); - - let subnets_blockmakers = vec![RawSubnetBlockmakerMetrics { - subnet: application_subnet.into(), - blockmaker: blockmaker_node, - failed_blockmakers: vec![], - }]; - - let tick_configs = TickConfigs { - blockmakers: Some(BlockMakerConfigs { - blockmakers_per_subnet: subnets_blockmakers, - }), - }; - - pocket_ic.tick_with_configs(tick_configs.clone()); - pocket_ic.tick_with_configs(tick_configs.clone()); - pocket_ic.tick_with_configs(tick_configs.clone()); - pocket_ic.tick_with_configs(tick_configs.clone()); - pocket_ic.tick_with_configs(tick_configs.clone()); - - pocket_ic - //go to next day it should have recorder the metrics - .advance_time(std::time::Duration::from_secs(60 * 60 * 25)); - - pocket_ic.tick(); - pocket_ic.tick(); - pocket_ic.tick(); - pocket_ic.tick(); - pocket_ic.tick(); - - let response = pocket_ic - .update_call( - Principal::management_canister(), - Principal::anonymous(), - "node_metrics_history", - Encode!(&NodeMetricsHistoryArgs { - subnet_id: application_subnet.into(), - start_at_timestamp_nanos: 0, - }) - .unwrap(), - ) - .unwrap(); - - let res = Decode!(&response, Vec).unwrap(); - println!("{:?}", res); - assert!(false) -} - /// Tests subnet read state requests. #[test] fn test_subnet_read_state() { diff --git a/rs/types/management_canister_types/BUILD.bazel b/rs/types/management_canister_types/BUILD.bazel index 39e3c90bd16..8b78629d925 100644 --- a/rs/types/management_canister_types/BUILD.bazel +++ b/rs/types/management_canister_types/BUILD.bazel @@ -9,6 +9,7 @@ permanent_whitelist = [ "//rs/cycles_account_manager:__subpackages__", "//rs/messaging:__subpackages__", "//rs/management_canister_types/fuzz:__subpackages__", + "//packages/pocket-ic:__subpackages__", ] # These crates depend on this library directly for historical reasons