From b4f55f0c3a022ddc67640a29488cd8188b1316f7 Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Thu, 28 May 2026 08:08:10 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20"chore:=200.48.0=20=E2=80=94=20rustls?= =?UTF-8?q?=20crypto=20provider=20selection=20via=20cargo=20features=20(#7?= =?UTF-8?q?32)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 01b6b2ce96ceb44871b2a4273166e8d1cd5440ca. --- .github/workflows/test.yml | 83 +++++-------- CHANGELOG.md | 14 --- Cargo.lock | 15 ++- Cargo.toml | 11 +- ic-agent/Cargo.toml | 17 +-- ic-agent/src/agent/http_transport/mod.rs | 8 ++ .../agent/http_transport/reqwest_transport.rs | 116 ++++++++++++++++++ ic-agent/src/agent/mod.rs | 42 +------ .../route_provider/dynamic_routing/mod.rs | 6 +- ic-agent/tests/crypto_provider_default.rs | 36 ------ ic-agent/tests/crypto_provider_idempotent.rs | 41 ------- ic-agent/tests/crypto_provider_neither.rs | 21 ---- ref-tests/Cargo.toml | 2 +- 13 files changed, 174 insertions(+), 238 deletions(-) create mode 100644 ic-agent/src/agent/http_transport/mod.rs create mode 100644 ic-agent/src/agent/http_transport/reqwest_transport.rs delete mode 100644 ic-agent/tests/crypto_provider_default.rs delete mode 100644 ic-agent/tests/crypto_provider_idempotent.rs delete mode 100644 ic-agent/tests/crypto_provider_neither.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69594e383..312be1867 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,67 +52,42 @@ jobs: run: | ./scripts/download_reftest_assets.sh - # --------------------------------------------------------------------- - # Test matrix - # --------------------------------------------------------------------- - # Native (Linux + macOS + Windows): - # - Test: workspace (--all-features) all crates except ref-tests - # - Test: ic-agent (default features) ship config smoke - # - Test: ic-agent (tls-ring only) alternate TLS provider - # - Test: ic-agent (no TLS, panic path) asserts the expected panic - # - # Linux-only (need extra system setup or have CI resource limits): - # - Test: WASM (ic-agent, wasm-bindgen) browser target - # - Test: ref-tests (pocket-ic) integration baseline - # - Test: ref-tests + SoftHSM HSM-backed identity - # --------------------------------------------------------------------- - - - name: Test - workspace (--all-features) - # Covers every crate except ref-tests with --all-features. For ic-agent - # this enables both TLS providers; the additivity rule selects the - # aws-lc-rs code path at runtime. - shell: bash - run: cargo test --workspace --exclude ref-tests --all-features --no-fail-fast - - - name: Test - ic-agent (default features) - # Ship-config smoke: build & test with only the default feature set - # (pem + tls-aws-lc-rs), the configuration downstream users get by - # default. Catches cfg gates that compile under --all-features but - # break with defaults alone. - shell: bash - run: cargo test -p ic-agent --no-fail-fast - - - name: Test - ic-agent (tls-ring only) - # Exercises the tls-ring code path (the minimal-feature config that - # dfinity/ic relies on to avoid rustls provider conflicts). - shell: bash - run: cargo test -p ic-agent --no-default-features --features pem,tls-ring --no-fail-fast - - - name: Test - ic-agent (no TLS, panic path) - # When no TLS feature is enabled, building the default reqwest client - # must panic with "No provider set". The integration test asserts this - # via #[should_panic]; run only that test, since the rest of ic-agent's - # lib tests would also panic for the same (expected) reason. - shell: bash - run: cargo test -p ic-agent --no-default-features --features pem --test crypto_provider_neither --no-fail-fast - - - name: Test - WASM (ic-agent, wasm-bindgen) - if: ${{ matrix.os == 'ubuntu-latest' }} - run: CARGO_TARGET_DIR=target/wasm wasm-pack test --chrome --headless ic-agent --features wasm-bindgen - - - name: Test - ref-tests (pocket-ic) + - name: Run Tests (ref-tests) # ref-tests are skipped on macOS CI: the GitHub Actions macOS runner has # a low per-process thread limit (kern.maxthreadsperproc) that cannot be # raised without root. pocket-ic spawns many OS threads per subnet, and # tokio's blocking thread pool accumulates idle threads across sequential # tests, exhausting the limit before all tests finish. This is a CI # resource constraint — ref-tests work fine on a local macOS machine. - # --test-threads=1 keeps the thread footprint manageable on Linux too. if: ${{ matrix.os == 'ubuntu-latest' }} shell: bash - run: cargo test -p ref-tests --no-fail-fast -- --test-threads=1 + run: | + cd ref-tests + cargo test --no-fail-fast -- --test-threads=1 + env: + RUST_BACKTRACE: 1 + + - name: Run Tests + shell: bash + run: | + # Test all features and no features for each package. + # ref-tests is excluded here and run separately with --test-threads=1 + # to avoid exhausting OS thread limits when pocket-ic spawns many threads. + for p in $(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name != "ref-tests") | .manifest_path'); do + pushd $(dirname $p) + cargo test --all-features --no-fail-fast + cargo test --no-default-features --no-fail-fast + popd + done + env: + RUST_BACKTRACE: 1 + + - name: Run Tests (WASM) + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + CARGO_TARGET_DIR=target/wasm wasm-pack test --chrome --headless ic-agent --features wasm-bindgen - - name: Test - ref-tests + SoftHSM + - name: Run Tests (SoftHSM) if: ${{ matrix.os == 'ubuntu-latest' }} run: | set -ex @@ -120,8 +95,10 @@ jobs: # create key: pkcs11-tool -k --module $HSM_PKCS11_LIBRARY_PATH --login --slot-index $HSM_SLOT_INDEX -d $HSM_KEY_ID --key-type EC:prime256v1 --pin $HSM_PIN - cargo test -p ref-tests --all-features --no-fail-fast -- --nocapture --test-threads=1 + cd ref-tests + cargo test --all-features --no-fail-fast -- --nocapture --test-threads=1 env: + RUST_BACKTRACE: 1 HSM_PKCS11_LIBRARY_PATH: /usr/lib/softhsm/libsofthsm2.so HSM_SO_PIN: 123456 HSM_PIN: 1234 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b6713ad5..309d68435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -## [0.48.0] - 2026-05-21 - -* `ic-agent`: Added cargo features `tls-aws-lc-rs` (default) and `tls-ring` to select the rustls crypto provider used by the default `reqwest::Client`. Features are additive: when both are enabled, aws-lc-rs is installed as the process-wide rustls default. Reqwest's `rustls` feature (which hardcoded aws-lc-rs) has been swapped for `rustls-no-provider`; ic-agent now installs the chosen provider via `CryptoProvider::install_default()` on the default-client path, idempotently (an application-installed provider is not overwritten). When the user supplies a client via `AgentBuilder::with_http_client`, ic-agent installs no provider. - -### Breaking Changes - -* `ic-agent`: - * Default feature set changed from `["pem"]` to `["pem", "tls-aws-lc-rs"]`. Stock-default users are unaffected (aws-lc-rs has been the only crypto provider available since 0.46.0). The `rustls` dependency is declared `cfg(not(target_family = "wasm"))`, so wasm consumers using default features are also unaffected — aws-lc-sys (which does not cross-compile to wasm) is not pulled in on wasm targets. - * Consumers using `default-features = false` on a non-wasm target must now opt into a TLS feature, otherwise `Agent::new` panics with "No provider set" when constructing the default reqwest client. - * Migration: add `tls-aws-lc-rs` (matches previous behavior) or `tls-ring` (matches reqwest 0.12 behavior) to the feature list, or supply your own `reqwest::Client` via `AgentBuilder::with_http_client`. - * Example: `ic-agent = { version = "0.48", default-features = false, features = ["pem", "tls-ring"] }`. - * Removed the deprecated `http_transport` module (`ReqwestTransport`, `AgentBuilder::with_transport`, `AgentBuilder::with_arc_transport`), deprecated since 0.38.0. - * Migration: use the dedicated `AgentBuilder` methods (`with_url`, `with_http_client`, `with_arc_route_provider`, `with_max_response_body_size`, `with_max_tcp_error_retries`). - ## [0.47.3] - 2026-05-15 * `ic-agent`: Added the `EffectiveId` enum (`Canister(Principal)` | `Subnet(Principal)`) and widened `Agent::update_signed`, `query_signed`, `request_status_signed`, `request_status_raw`, `wait`, `wait_signed`, `read_state_raw`, `verify`, and `sign_request_status` to accept `impl Into`. Passing a bare `Principal` is unchanged (treated as `EffectiveId::Canister(_)`); passing `EffectiveId::Subnet(_)` routes to the subnet-scoped HTTP endpoints (`/api/v4/subnet//call`, `/api/v3/subnet//read_state`, `/api/v3/subnet//query`) introduced in IC interface spec 0.60.0. diff --git a/Cargo.lock b/Cargo.lock index dd412e15f..59c300fd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1413,7 +1413,7 @@ dependencies = [ [[package]] name = "ic-agent" -version = "0.48.0" +version = "0.47.3" dependencies = [ "anyhow", "arc-swap", @@ -1436,7 +1436,7 @@ dependencies = [ "http-body-util", "ic-certification", "ic-ed25519", - "ic-transport-types 0.48.0", + "ic-transport-types 0.47.3", "ic-verify-bls-signature", "ic_principal", "js-sys", @@ -1451,7 +1451,6 @@ dependencies = [ "ref-tests", "reqwest 0.13.2", "ring", - "rustls", "sec1", "serde", "serde_bytes", @@ -1504,7 +1503,7 @@ dependencies = [ [[package]] name = "ic-identity-hsm" -version = "0.48.0" +version = "0.47.3" dependencies = [ "hex", "ic-agent", @@ -1556,7 +1555,7 @@ dependencies = [ [[package]] name = "ic-transport-types" -version = "0.48.0" +version = "0.47.3" dependencies = [ "candid", "hex", @@ -1573,7 +1572,7 @@ dependencies = [ [[package]] name = "ic-utils" -version = "0.48.0" +version = "0.47.3" dependencies = [ "async-trait", "candid", @@ -1743,7 +1742,7 @@ dependencies = [ [[package]] name = "icx" -version = "0.48.0" +version = "0.47.3" dependencies = [ "anyhow", "candid", @@ -1762,7 +1761,7 @@ dependencies = [ [[package]] name = "icx-cert" -version = "0.48.0" +version = "0.47.3" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index 6c5854fc0..3c16e20d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ members = [ ] [workspace.package] -version = "0.48.0" +version = "0.47.3" authors = ["DFINITY Stiftung "] edition = "2021" repository = "https://github.com/dfinity/agent-rs" @@ -30,10 +30,10 @@ license = "Apache-2.0" # a comment listing those crates). Otherwise, features are declared in the individual crate Cargo.toml. # # The path dependencies below ensure all workspace members use the same version of internal crates. -ic-agent = { path = "ic-agent", version = "0.48.0", default-features = false } -ic-identity-hsm = { path = "ic-identity-hsm", version = "0.48.0" } -ic-transport-types = { path = "ic-transport-types", version = "0.48.0" } -ic-utils = { path = "ic-utils", version = "0.48.0" } +ic-agent = { path = "ic-agent", version = "0.47.3", default-features = false } +ic-identity-hsm = { path = "ic-identity-hsm", version = "0.47.3" } +ic-transport-types = { path = "ic-transport-types", version = "0.47.3" } +ic-utils = { path = "ic-utils", version = "0.47.3" } ic-utils-bindgen = { path = "ic-utils-bindgen" } ref-tests = { path = "ref-tests" } @@ -88,7 +88,6 @@ rand = "0.10.1" rangemap = "1.7" reqwest = { version = "0.13.2", default-features = false } ring = "0.17" -rustls = { version = "0.23", default-features = false } sec1 = "0.7.2" semver = "1.0.7" serde = "1.0.215" diff --git a/ic-agent/Cargo.toml b/ic-agent/Cargo.toml index 9e8230bb8..38160d87b 100644 --- a/ic-agent/Cargo.toml +++ b/ic-agent/Cargo.toml @@ -19,15 +19,9 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] features = ["wasm-bindgen"] [features] -default = ["pem", "tls-aws-lc-rs"] +default = ["pem"] pem = ["dep:pem", "pkcs8/pem"] ring = ["dep:ring"] -# rustls crypto provider selection. Features are additive: if both are enabled, -# aws-lc-rs is installed as the process-wide rustls default (the ring code is -# compiled in but unused). To use ring, set `default-features = false` and -# enable `tls-ring` explicitly. -tls-aws-lc-rs = ["dep:rustls", "rustls/aws-lc-rs"] -tls-ring = ["dep:rustls", "rustls/ring"] ic_ref_tests = ["default"] # Used to separate integration tests for ic-ref which need a server running. wasm-bindgen = [ "dep:js-sys", @@ -75,7 +69,7 @@ pem = { workspace = true, optional = true } pkcs8 = { workspace = true, features = ["std"] } rand = { workspace = true } rangemap = { workspace = true } -reqwest = { workspace = true, default-features = false, features = ["blocking", "json", "rustls-no-provider", "stream"] } +reqwest = { workspace = true, default-features = false, features = ["blocking", "json", "rustls", "stream"] } ring = { workspace = true, optional = true } sec1 = { workspace = true, features = ["pem"] } serde = { workspace = true, features = ["derive"] } @@ -91,12 +85,6 @@ tracing = { workspace = true, optional = true } url = { workspace = true } [target.'cfg(not(target_family = "wasm"))'.dependencies] -# rustls is only used off-wasm: on wasm the reqwest client is the browser's -# fetch API, and the rustls crypto-provider install is gated -# `cfg(not(target_family = "wasm"))`. Keeping the dep target-conditional means -# wasm consumers can use the default features without pulling in aws-lc-sys -# (which doesn't cross-compile to wasm32-unknown-unknown). -rustls = { workspace = true, default-features = false, features = ["std", "tls12"], optional = true } tokio = { workspace = true, default-features = false, features = ["time", "sync"] } [target.'cfg(target_family = "wasm")'.dependencies] @@ -115,7 +103,6 @@ tracing-subscriber = { workspace = true } [target.'cfg(not(target_family = "wasm"))'.dev-dependencies] mockito = { workspace = true } -rustls = { workspace = true, features = ["aws-lc-rs", "ring"] } tokio = { workspace = true, features = ["full"] } [target.'cfg(target_family = "wasm")'.dev-dependencies] diff --git a/ic-agent/src/agent/http_transport/mod.rs b/ic-agent/src/agent/http_transport/mod.rs new file mode 100644 index 000000000..bf9376675 --- /dev/null +++ b/ic-agent/src/agent/http_transport/mod.rs @@ -0,0 +1,8 @@ +//! This module has been deprecated in favor of builder methods on `AgentBuilder`. + +#[deprecated(since = "0.38.0", note = "use the AgentBuilder methods")] +#[doc(hidden)] +pub mod reqwest_transport; +#[doc(hidden)] +#[allow(deprecated)] +pub use reqwest_transport::ReqwestTransport; diff --git a/ic-agent/src/agent/http_transport/reqwest_transport.rs b/ic-agent/src/agent/http_transport/reqwest_transport.rs new file mode 100644 index 000000000..5876c281b --- /dev/null +++ b/ic-agent/src/agent/http_transport/reqwest_transport.rs @@ -0,0 +1,116 @@ +//! This module has been deprecated in favor of builder methods on `AgentBuilder`. +#![allow(deprecated)] +pub use reqwest; +use std::sync::Arc; + +use reqwest::Client; + +use crate::{ + agent::{ + route_provider::{RoundRobinRouteProvider, RouteProvider}, + AgentBuilder, + }, + AgentError, +}; + +/// A legacy configuration object. `AgentBuilder::with_transport` will apply these settings to the builder. +#[derive(Debug, Clone)] +pub struct ReqwestTransport { + route_provider: Arc, + client: Client, + max_response_body_size: Option, + max_tcp_error_retries: usize, +} + +impl ReqwestTransport { + /// Equivalent to [`AgentBuilder::with_url`]. + #[deprecated(since = "0.38.0", note = "Use AgentBuilder::with_url")] + pub fn create>(url: U) -> Result { + #[cfg(not(target_family = "wasm"))] + { + Self::create_with_client( + url, + Client::builder() + .use_rustls_tls() + .timeout(std::time::Duration::from_secs(360)) + .build() + .expect("Could not create HTTP client."), + ) + } + #[cfg(all(target_family = "wasm", feature = "wasm-bindgen"))] + { + Self::create_with_client(url, Client::new()) + } + } + + /// Equivalent to [`AgentBuilder::with_url`] and [`AgentBuilder::with_http_client`]. + #[deprecated( + since = "0.38.0", + note = "Use AgentBuilder::with_url and AgentBuilder::with_http_client" + )] + pub fn create_with_client>(url: U, client: Client) -> Result { + let route_provider = Arc::new(RoundRobinRouteProvider::new(vec![url.into()])?); + Self::create_with_client_route(route_provider, client) + } + + /// Equivalent to [`AgentBuilder::with_http_client`] and [`AgentBuilder::with_route_provider`]. + #[deprecated( + since = "0.38.0", + note = "Use AgentBuilder::with_http_client and AgentBuilder::with_arc_route_provider" + )] + pub fn create_with_client_route( + route_provider: Arc, + client: Client, + ) -> Result { + Ok(Self { + route_provider, + client, + max_response_body_size: None, + max_tcp_error_retries: 0, + }) + } + + /// Equivalent to [`AgentBuilder::with_max_response_body_size`]. + #[deprecated( + since = "0.38.0", + note = "Use AgentBuilder::with_max_response_body_size" + )] + pub fn with_max_response_body_size(self, max_response_body_size: usize) -> Self { + ReqwestTransport { + max_response_body_size: Some(max_response_body_size), + ..self + } + } + + /// Equivalent to [`AgentBuilder::with_max_tcp_error_retries`]. + #[deprecated( + since = "0.38.0", + note = "Use AgentBuilder::with_max_tcp_error_retries" + )] + pub fn with_max_tcp_errors_retries(self, retries: usize) -> Self { + ReqwestTransport { + max_tcp_error_retries: retries, + ..self + } + } +} + +impl AgentBuilder { + #[doc(hidden)] + #[deprecated(since = "0.38.0", note = "Use the dedicated methods on AgentBuilder")] + pub fn with_transport(self, transport: ReqwestTransport) -> Self { + let mut builder = self + .with_arc_route_provider(transport.route_provider) + .with_http_client(transport.client) + .with_max_tcp_error_retries(transport.max_tcp_error_retries); + if let Some(max_size) = transport.max_response_body_size { + builder = builder.with_max_response_body_size(max_size); + } + builder + } + #[doc(hidden)] + #[deprecated(since = "0.38.0", note = "Use the dedicated methods on AgentBuilder")] + pub fn with_arc_transport(self, transport: Arc) -> Self { + self.with_transport((*transport).clone()) + } +} diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index 683606b0a..284868a2f 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -2,6 +2,10 @@ pub(crate) mod agent_config; pub mod agent_error; pub(crate) mod builder; +// delete this module after 0.40 +#[doc(hidden)] +#[deprecated(since = "0.38.0", note = "use the AgentBuilder methods")] +pub mod http_transport; pub(crate) mod nonce; pub(crate) mod response_authentication; pub mod route_provider; @@ -207,43 +211,6 @@ impl fmt::Debug for Agent { } } -/// Install a process-wide rustls [`CryptoProvider`] if none is already installed. -/// -/// Called when [`Agent::new`] builds its default [`reqwest::Client`]. Reqwest's -/// `rustls-no-provider` feature defers the provider choice to whichever -/// `CryptoProvider` is registered as the process default; this function makes -/// the choice based on the active cargo features so users don't have to install -/// one themselves. -/// -/// The call is idempotent: `install_default` returns `Err` if a default was -/// already set, which we ignore. That means an application that installs its -/// own provider before constructing an `Agent` wins. -/// -/// Feature precedence: `tls-aws-lc-rs` wins over `tls-ring` when both are -/// enabled, preserving additivity (enabling `tls-ring` on top of the default -/// never silently flips the installed provider). -#[cfg(not(target_family = "wasm"))] -pub(crate) fn install_default_crypto_provider() { - #[cfg(any(feature = "tls-aws-lc-rs", feature = "tls-ring"))] - { - // Cheap fast-path: if a default is already installed (by us on a prior - // `Agent::new`, or by the application), skip constructing a provider. - // The check has a benign TOCTOU race — `install_default()` is itself - // atomic, so concurrent installers still produce a single winner and - // the others' `Err` is discarded. - if rustls::crypto::CryptoProvider::get_default().is_some() { - return; - } - #[cfg(feature = "tls-aws-lc-rs")] - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); - #[cfg(all(feature = "tls-ring", not(feature = "tls-aws-lc-rs")))] - let _ = rustls::crypto::ring::default_provider().install_default(); - } - // If neither feature is enabled, do nothing. The user is expected to either - // call `with_http_client` or install a provider themselves before building - // the agent; otherwise reqwest will panic when constructing its TLS config. -} - impl Agent { /// Create an instance of an [`AgentBuilder`] for building an [`Agent`]. This is simpler than /// using the [`AgentConfig`] and [`Agent::new()`]. @@ -258,7 +225,6 @@ impl Agent { client: config.client.unwrap_or_else(|| { #[cfg(not(target_family = "wasm"))] { - install_default_crypto_provider(); Client::builder() .use_rustls_tls() .timeout(Duration::from_secs(360)) diff --git a/ic-agent/src/agent/route_provider/dynamic_routing/mod.rs b/ic-agent/src/agent/route_provider/dynamic_routing/mod.rs index 7e408a5dd..e914bcd10 100644 --- a/ic-agent/src/agent/route_provider/dynamic_routing/mod.rs +++ b/ic-agent/src/agent/route_provider/dynamic_routing/mod.rs @@ -77,11 +77,7 @@ //! // Node::new("")?, //! ]; //! -//! // Build dynamic route provider with HTTP client. Because the client is -//! // built directly (not via `Agent::new`), a rustls `CryptoProvider` must -//! // be installed before `reqwest::Client::new()` — `Agent::new` would -//! // normally do this for you. -//! let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); +//! // Build dynamic route provider with HTTP client //! let http_client = Arc::new(reqwest::Client::new()); //! let route_provider = DynamicRouteProviderBuilder::new(seed_nodes, http_client, None) //! // Set how often to fetch the latest API boundary node topology diff --git a/ic-agent/tests/crypto_provider_default.rs b/ic-agent/tests/crypto_provider_default.rs deleted file mode 100644 index c2712b857..000000000 --- a/ic-agent/tests/crypto_provider_default.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Verify that `Agent::new` installs the rustls `CryptoProvider` matching the -//! active cargo features (`tls-aws-lc-rs` or `tls-ring`). -//! -//! In its own integration-test file for process isolation: `CryptoProvider`'s -//! process-wide default slot is one-shot, so sharing a binary with other tests -//! that pre-install a provider would make ordering matter. - -#![cfg(not(target_family = "wasm"))] -#![cfg(any(feature = "tls-ring", feature = "tls-aws-lc-rs"))] - -use ic_agent::Agent; -use rustls::crypto::CryptoProvider; - -#[test] -fn default_client_installs_expected_provider() { - let _agent = Agent::builder() - .with_url("https://ic0.app") - .build() - .expect("Agent build should succeed with a provider feature enabled"); - - let installed = CryptoProvider::get_default().expect("a provider must be installed"); - - // aws-lc-rs wins when both features are on (additive rule). - #[cfg(feature = "tls-aws-lc-rs")] - let expected = rustls::crypto::aws_lc_rs::default_provider(); - #[cfg(all(feature = "tls-ring", not(feature = "tls-aws-lc-rs")))] - let expected = rustls::crypto::ring::default_provider(); - - // Compare the full `&'static dyn SecureRandom` wide pointer (data + vtable). - // Casting to `*const ()` would drop the vtable and could alias across - // ZST-backed impls; wide-pointer equality keeps the type identity. - assert!( - std::ptr::eq(installed.secure_random, expected.secure_random), - "installed provider does not match the one selected by active features" - ); -} diff --git a/ic-agent/tests/crypto_provider_idempotent.rs b/ic-agent/tests/crypto_provider_idempotent.rs deleted file mode 100644 index 5473a4440..000000000 --- a/ic-agent/tests/crypto_provider_idempotent.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! Verify that `Agent::new` does not overwrite a `CryptoProvider` that the -//! application installed first, and does not panic in that case. -//! -//! In its own integration-test file for process isolation: the prior test in -//! `crypto_provider_default.rs` is the inverse setup (ic-agent installs first), -//! and `CryptoProvider`'s default slot is one-shot per process. - -#![cfg(not(target_family = "wasm"))] -#![cfg(any(feature = "tls-ring", feature = "tls-aws-lc-rs"))] - -use ic_agent::Agent; -use rustls::crypto::CryptoProvider; - -#[test] -fn application_provider_wins() { - // Pick the *opposite* of what ic-agent would install, to detect overwrites. - #[cfg(feature = "tls-aws-lc-rs")] - let user_choice = rustls::crypto::ring::default_provider(); - #[cfg(all(feature = "tls-ring", not(feature = "tls-aws-lc-rs")))] - let user_choice = rustls::crypto::aws_lc_rs::default_provider(); - - let user_ptr: *const dyn rustls::crypto::SecureRandom = user_choice.secure_random; - user_choice - .install_default() - .expect("test must run before any other provider is installed"); - - // ic-agent builds its default client; should not panic, and should not - // change the installed default. - let _agent = Agent::builder() - .with_url("https://ic0.app") - .build() - .expect("Agent build should succeed"); - - let installed = CryptoProvider::get_default().expect("provider still installed"); - // Compare the full `&'static dyn SecureRandom` wide pointer (data + vtable); - // casting to `*const ()` would drop the vtable and could alias for ZSTs. - assert!( - std::ptr::eq(installed.secure_random, user_ptr), - "ic-agent overwrote a previously installed CryptoProvider" - ); -} diff --git a/ic-agent/tests/crypto_provider_neither.rs b/ic-agent/tests/crypto_provider_neither.rs deleted file mode 100644 index aeaf6bf9f..000000000 --- a/ic-agent/tests/crypto_provider_neither.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! Verify that building a default `Agent` panics when neither `tls-ring` nor -//! `tls-aws-lc-rs` is enabled, because reqwest's `rustls-no-provider` feature -//! requires a process-wide `CryptoProvider` to be installed and ic-agent's -//! helper is a no-op in this configuration. -//! -//! Only compiled when *neither* TLS feature is active. The companion CI step -//! exercises this with `--no-default-features --features pem`. - -#![cfg(not(target_family = "wasm"))] -#![cfg(not(any(feature = "tls-ring", feature = "tls-aws-lc-rs")))] - -use ic_agent::Agent; - -#[test] -#[should_panic] -fn default_client_panics_without_provider() { - // Reqwest panics with "No provider set" when it cannot find an installed - // CryptoProvider. `Agent::builder().build()` triggers `Client::builder()` - // which is where the panic surfaces. - let _ = Agent::builder().with_url("https://ic0.app").build(); -} diff --git a/ref-tests/Cargo.toml b/ref-tests/Cargo.toml index c93996d95..16d540b32 100644 --- a/ref-tests/Cargo.toml +++ b/ref-tests/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] candid = { workspace = true } -ic-agent = { workspace = true, features = ["pem", "tls-aws-lc-rs"] } +ic-agent = { workspace = true, features = ["pem"] } ic-certification = { workspace = true } ic-ed25519 = { workspace = true } ic-identity-hsm = { workspace = true }