From 9dfce3a041f8f29649694b4294c9516bcc4b4dd6 Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 26 Mar 2024 15:35:47 +0100 Subject: [PATCH 1/8] chore: ApiBoundaryNode implements clone --- ic-agent/src/agent/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 900bc924..1ce73d4a 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1469,7 +1469,7 @@ pub(crate) struct Subnet { } /// API boundary node, which routes /api calls to IC replica nodes. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ApiBoundaryNode { /// Domain name pub domain: String, From d747b2196d800303357034362b3bffbb9ecbe7a9 Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 26 Mar 2024 16:06:54 +0100 Subject: [PATCH 2/8] chore: hide effective_canister_id inside fetch_api_boundary_nodes() --- ic-agent/src/agent/mod.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 1ce73d4a..9ba1f979 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1129,15 +1129,11 @@ impl Agent { } /// Retrieve all existing API boundary nodes from the state tree. - pub async fn fetch_api_boundary_nodes( - &self, - effective_canister_id: Principal, - ) -> Result, AgentError> { + pub async fn fetch_api_boundary_nodes(&self) -> Result, AgentError> { + // Here we use root canister_id, but any other 'permanent' canister in the root subnet can be used too. + let root_canister_id = Principal::from_text("r7inp-6aaaa-aaaaa-aaabq-cai").unwrap(); let certificate = self - .read_state_raw( - vec![vec!["api_boundary_nodes".into()]], - effective_canister_id, - ) + .read_state_raw(vec![vec!["api_boundary_nodes".into()]], root_canister_id) .await?; let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; Ok(api_boundary_nodes) From 92971fa11e5db10b0114dbeaf2f29efb3dac2276 Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 26 Mar 2024 16:39:11 +0100 Subject: [PATCH 3/8] chore: keep two versions of the functions --- ic-agent/src/agent/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 9ba1f979..057c7a34 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1128,7 +1128,7 @@ impl Agent { } } - /// Retrieve all existing API boundary nodes from the state tree. + /// Retrieve all existing API boundary nodes from the state tree using a hard-coded `effective_canister_id`. pub async fn fetch_api_boundary_nodes(&self) -> Result, AgentError> { // Here we use root canister_id, but any other 'permanent' canister in the root subnet can be used too. let root_canister_id = Principal::from_text("r7inp-6aaaa-aaaaa-aaabq-cai").unwrap(); @@ -1139,6 +1139,21 @@ impl Agent { Ok(api_boundary_nodes) } + /// Retrieve all existing API boundary nodes from the state tree using a custom `effective_canister_id`. + pub async fn fetch_api_boundary_nodes_by_canister_id( + &self, + effective_canister_id: Principal, + ) -> Result, AgentError> { + let certificate = self + .read_state_raw( + vec![vec!["api_boundary_nodes".into()]], + effective_canister_id, + ) + .await?; + let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; + Ok(api_boundary_nodes) + } + async fn fetch_subnet_by_canister( &self, canister: &Principal, From 86678f934856beb657ae3f69b33c38af3671981d Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Mon, 1 Apr 2024 21:33:18 +0200 Subject: [PATCH 4/8] chore: use /subnet//read_state for BNs --- ic-agent/src/agent/mod.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 057c7a34..a28fc633 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1128,28 +1128,29 @@ impl Agent { } } - /// Retrieve all existing API boundary nodes from the state tree using a hard-coded `effective_canister_id`. - pub async fn fetch_api_boundary_nodes(&self) -> Result, AgentError> { - // Here we use root canister_id, but any other 'permanent' canister in the root subnet can be used too. - let root_canister_id = Principal::from_text("r7inp-6aaaa-aaaaa-aaabq-cai").unwrap(); - let certificate = self - .read_state_raw(vec![vec!["api_boundary_nodes".into()]], root_canister_id) - .await?; + /// Retrieve all existing API boundary nodes from the state tree using a hard-coded id of the root subnet in mainnet. + /// Endpoint /api/v2/subnet//read_state is called internally. + pub async fn fetch_api_boundary_nodes_mainnet( + &self, + ) -> Result, AgentError> { + // While the id of the root subnet is utilized here, it's important to note that an ID of any existing subnet could also be employed. + let root_subnet_id = + Principal::from_text("tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe") + .expect("failed to parse principle"); + let paths = vec![vec!["api_boundary_nodes".into()]]; + let certificate = self.read_subnet_state_raw(paths, root_subnet_id).await?; let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; Ok(api_boundary_nodes) } - /// Retrieve all existing API boundary nodes from the state tree using a custom `effective_canister_id`. - pub async fn fetch_api_boundary_nodes_by_canister_id( + /// Retrieve all existing API boundary nodes from the state tree using a custom existing subnet_id. + /// Endpoint /api/v2/subnet//read_state is called internally. + pub async fn fetch_api_boundary_nodes( &self, - effective_canister_id: Principal, + subnet_id: Principal, ) -> Result, AgentError> { - let certificate = self - .read_state_raw( - vec![vec!["api_boundary_nodes".into()]], - effective_canister_id, - ) - .await?; + let paths = vec![vec!["api_boundary_nodes".into()]]; + let certificate = self.read_subnet_state_raw(paths, subnet_id).await?; let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; Ok(api_boundary_nodes) } From 01ccd77a47191ea69a8f86eb0060ce31d01c8449 Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 2 Apr 2024 09:57:10 +0200 Subject: [PATCH 5/8] docs: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fce7c936..b462e37b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `QueryBuilder::call_with_verification()` and `QueryBuilder::call_without_verification()` which always/never verify query signatures regardless the Agent level configuration from `AgentBuilder::with_verify_query_signatures`. +* Function `Agent::fetch_api_boundary_nodes()` is modified and split into two: `fetch_api_boundary_nodes_mainnet()` and `fetch_api_boundary_nodes(subnet_id)` (now uses `subnet_id` instead of `effective_canister_id`). ## [0.34.0] - 2024-03-18 From 2daf127aa98c5f19384c6e321a08e894ce6dc401 Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 2 Apr 2024 10:10:46 +0200 Subject: [PATCH 6/8] docs: minor improvement --- ic-agent/src/agent/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index a28fc633..eee215af 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1133,7 +1133,7 @@ impl Agent { pub async fn fetch_api_boundary_nodes_mainnet( &self, ) -> Result, AgentError> { - // While the id of the root subnet is utilized here, it's important to note that an ID of any existing subnet could also be employed. + // While the id of the root subnet is utilized here, it's important to note that an id of any existing subnet could also be employed. let root_subnet_id = Principal::from_text("tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe") .expect("failed to parse principle"); @@ -1143,7 +1143,7 @@ impl Agent { Ok(api_boundary_nodes) } - /// Retrieve all existing API boundary nodes from the state tree using a custom existing subnet_id. + /// Retrieve all existing API boundary nodes from the state tree using a custom id of an existing subnet. /// Endpoint /api/v2/subnet//read_state is called internally. pub async fn fetch_api_boundary_nodes( &self, From fe9b7c4841f7c909883c4d5c64c3a995413f988c Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 2 Apr 2024 18:06:13 +0200 Subject: [PATCH 7/8] chore: use ApiBoundaryNodesResolver --- CHANGELOG.md | 2 +- ic-agent/src/agent/mod.rs | 37 ++++++++++++++++++------------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 561c7b35..b05af50f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Changed `WalletCanister::from_canister/create`'s version check to not rely on the reject code. * Added `QueryBuilder::call_with_verification()` and `QueryBuilder::call_without_verification()` which always/never verify query signatures regardless the Agent level configuration from `AgentBuilder::with_verify_query_signatures`. -* Function `Agent::fetch_api_boundary_nodes()` is modified and split into two: `fetch_api_boundary_nodes_mainnet()` and `fetch_api_boundary_nodes(subnet_id)` (now uses `subnet_id` instead of `effective_canister_id`). +* Function `Agent::fetch_api_boundary_nodes(effective_canister_id)` is modified into `fetch_api_boundary_nodes(resolver: ApiBoundaryNodesResolver)`. ## [0.34.0] - 2024-03-18 diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index eee215af..1801e64d 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1128,30 +1128,20 @@ impl Agent { } } - /// Retrieve all existing API boundary nodes from the state tree using a hard-coded id of the root subnet in mainnet. - /// Endpoint /api/v2/subnet//read_state is called internally. - pub async fn fetch_api_boundary_nodes_mainnet( - &self, - ) -> Result, AgentError> { - // While the id of the root subnet is utilized here, it's important to note that an id of any existing subnet could also be employed. - let root_subnet_id = - Principal::from_text("tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe") - .expect("failed to parse principle"); - let paths = vec![vec!["api_boundary_nodes".into()]]; - let certificate = self.read_subnet_state_raw(paths, root_subnet_id).await?; - let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; - Ok(api_boundary_nodes) - } - - /// Retrieve all existing API boundary nodes from the state tree using a custom id of an existing subnet. - /// Endpoint /api/v2/subnet//read_state is called internally. + /// Retrieve all existing API boundary nodes from the state tree. pub async fn fetch_api_boundary_nodes( &self, - subnet_id: Principal, + resolver: ApiBoundaryNodesResolver, ) -> Result, AgentError> { let paths = vec![vec!["api_boundary_nodes".into()]]; - let certificate = self.read_subnet_state_raw(paths, subnet_id).await?; + let certificate = match resolver { + ApiBoundaryNodesResolver::ViaCanisterId(id) => self.read_state_raw(paths, id).await?, + ApiBoundaryNodesResolver::ViaSubnetId(id) => { + self.read_subnet_state_raw(paths, id).await? + } + }; let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; + Ok(api_boundary_nodes) } @@ -1480,6 +1470,15 @@ pub(crate) struct Subnet { canister_ranges: RangeInclusiveSet, } +/// Specifies a method for fetching API boundary nodes. +#[derive(Debug, Clone)] +pub enum ApiBoundaryNodesResolver { + /// Via endpoint: /api/v2/canister//read_state + ViaCanisterId(Principal), + /// Via endpoint: /api/v2/subnet//read_state + ViaSubnetId(Principal), +} + /// API boundary node, which routes /api calls to IC replica nodes. #[derive(Debug, Clone)] pub struct ApiBoundaryNode { From 81d16239b1acbb42ddfd4128d3d40f3564ea293a Mon Sep 17 00:00:00 2001 From: Nikolay Komarevskiy Date: Tue, 2 Apr 2024 22:40:31 +0200 Subject: [PATCH 8/8] chore: split into two functions --- CHANGELOG.md | 2 +- ic-agent/src/agent/mod.rs | 32 ++++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b05af50f..5ed1fb55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Changed `WalletCanister::from_canister/create`'s version check to not rely on the reject code. * Added `QueryBuilder::call_with_verification()` and `QueryBuilder::call_without_verification()` which always/never verify query signatures regardless the Agent level configuration from `AgentBuilder::with_verify_query_signatures`. -* Function `Agent::fetch_api_boundary_nodes(effective_canister_id)` is modified into `fetch_api_boundary_nodes(resolver: ApiBoundaryNodesResolver)`. +* Function `Agent::fetch_api_boundary_nodes()` is split into two functions: `fetch_api_boundary_nodes_by_canister_id()` and `fetch_api_boundary_nodes_by_subnet_id()`. ## [0.34.0] - 2024-03-18 diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 1801e64d..31292a7b 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -1128,20 +1128,25 @@ impl Agent { } } - /// Retrieve all existing API boundary nodes from the state tree. - pub async fn fetch_api_boundary_nodes( + /// Retrieve all existing API boundary nodes from the state tree via endpoint /api/v2/canister//read_state + pub async fn fetch_api_boundary_nodes_by_canister_id( &self, - resolver: ApiBoundaryNodesResolver, + canister_id: Principal, ) -> Result, AgentError> { let paths = vec![vec!["api_boundary_nodes".into()]]; - let certificate = match resolver { - ApiBoundaryNodesResolver::ViaCanisterId(id) => self.read_state_raw(paths, id).await?, - ApiBoundaryNodesResolver::ViaSubnetId(id) => { - self.read_subnet_state_raw(paths, id).await? - } - }; + let certificate = self.read_state_raw(paths, canister_id).await?; let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; + Ok(api_boundary_nodes) + } + /// Retrieve all existing API boundary nodes from the state tree via endpoint /api/v2/subnet//read_state + pub async fn fetch_api_boundary_nodes_by_subnet_id( + &self, + subnet_id: Principal, + ) -> Result, AgentError> { + let paths = vec![vec!["api_boundary_nodes".into()]]; + let certificate = self.read_subnet_state_raw(paths, subnet_id).await?; + let api_boundary_nodes = lookup_api_boundary_nodes(certificate)?; Ok(api_boundary_nodes) } @@ -1470,15 +1475,6 @@ pub(crate) struct Subnet { canister_ranges: RangeInclusiveSet, } -/// Specifies a method for fetching API boundary nodes. -#[derive(Debug, Clone)] -pub enum ApiBoundaryNodesResolver { - /// Via endpoint: /api/v2/canister//read_state - ViaCanisterId(Principal), - /// Via endpoint: /api/v2/subnet//read_state - ViaSubnetId(Principal), -} - /// API boundary node, which routes /api calls to IC replica nodes. #[derive(Debug, Clone)] pub struct ApiBoundaryNode {