Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ic-geo-route-provider

Geographic-aware route provider for the Internet Computer. Ensures IC requests only go through API boundary nodes located in specific regions.

Why

The Internet Computer's ic-agent routes requests to API boundary nodes without geographic awareness. For data sovereignty (EU/Swiss compliance, GDPR, FINMA), you may need to guarantee that all IC traffic stays within a specific jurisdiction. This crate solves that by filtering boundary nodes based on their registered data center location in the NNS registry.

How it works

NNS Registry (periodic sync)
  |
  v
GeoRouteProvider
  1. Fetch API boundary node IDs
  2. Resolve geo chain: NodeRecord -> NodeOperatorRecord -> DataCenterRecord
  3. Filter by region prefix (e.g. "Europe,CH")
  4. Health-check surviving nodes (GET /health)
  5. Expose via RouteProvider trait
  |
  v
ic-agent / ic-http-gateway
  - route()          -> random healthy node in region
  - n_ordered_routes -> top n healthy nodes in region

The NNS registry is the source of truth. Every API boundary node has a NodeRecord linking to a NodeOperatorRecord linking to a DataCenterRecord with a region string (e.g. "Europe,CH,Zurich") and GPS coordinates. No GeoIP heuristics are needed.

A background task re-syncs from the registry and health-checks nodes on configurable intervals.

Important: This controls which API boundary node handles your request, not which subnet replicas execute it. If the target canister lives on a subnet whose replica nodes are outside your filtered region, the boundary node will still forward the request to those replicas. To achieve full data sovereignty, the canister itself must be deployed on a subnet with nodes in the desired region.

Usage

Add to Cargo.toml:

[dependencies]
ic-geo-route-provider = { path = "." }  # or git/crates.io once published
ic-agent = "0.46"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
url = "2"

With ic-agent

use ic_agent::Agent;
use ic_geo_route_provider::GeoRouteProviderBuilder;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = GeoRouteProviderBuilder::new()
        .with_seed_urls(vec!["https://icp-api.io".parse()?])
        .with_region_filter(vec!["Europe,CH".into()]) // Swiss-only
        .build()
        .await?;

    let agent = Agent::builder()
        .with_arc_route_provider(std::sync::Arc::new(provider))
        .build()?;

    // All requests now go through Swiss boundary nodes
    // agent.query(...).await?;
    Ok(())
}

With ic-http-gateway

use ic_agent::Agent;
use ic_http_gateway::HttpGatewayClient;
use ic_geo_route_provider::GeoRouteProviderBuilder;

let provider = GeoRouteProviderBuilder::new()
    .with_seed_urls(vec!["https://icp-api.io".parse()?])
    .with_region_filter(vec!["Europe,CH".into()]) // Swiss-only
    .build()
    .await?;

let agent = Agent::builder()
    .with_arc_route_provider(std::sync::Arc::new(provider))
    .build()?;

let gateway_client = HttpGatewayClient::builder()
    .with_agent(agent)
    .build()?;

// All gateway requests now route through Swiss boundary nodes

Region filter examples

Filter Matches
["Europe,CH"] Swiss nodes only (Geneva, Zurich)
["Europe"] All European nodes (CH, DE, RO, BE, ...)
["Europe,CH", "Europe,DE"] Swiss + German nodes
["North America,US"] US nodes only

Region strings use comma-separated hierarchies matching the NNS registry DataCenterRecord.region field. Filtering is case-insensitive prefix matching.

Builder options

GeoRouteProviderBuilder::new()
    .with_seed_urls(urls)           // Required: bootstrap URLs for registry queries
    .with_region_filter(filters)    // Required: region prefix list
    .with_sync_interval(dur)        // Registry re-sync interval (default: 60s)
    .with_health_check_interval(dur) // Health check interval (default: 10s)
    .build()
    .await?;

Current mainnet nodes (as of April 2026)

Region Nodes
Europe,CH (Swiss) 3 (Geneva, Zurich x2)
Europe (all) 6 (CH, DE, RO, BE)
North America 8 (US, CA)
Asia 5 (IN, KR, SG)
Africa 1 (ZA)

Testing

# Unit tests
cargo test

# Integration tests (hits IC mainnet)
cargo test --test mainnet -- --nocapture --ignored

License

MPL-2.0

About

Route IC traffic through geo-filtered API boundary nodes for data sovereignty compliance.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages