Repository: tari-project/tari
Pull request #6922: fix(p2p/dns): greatly simplify DNS TXT lookup
Author: login: sdbondi
Created: 2025-04-03T13:22:29Z | Merged: 2025-04-04T13:27:17Z

Description
---
- simplify DNS txt lookup code by using hickory resolver
- upgrade hickory to `0.25.0-alpha.4` (from alpha.2)
- update tari pulse implementation

Motivation and Context
---
Hickory-client includes many breaking changes with practically every update (`0.25.0-alpha.2 -> 4` is no exception), and this is a burden to maintain.
The `hickory-resolver` is a higher-level crate that abstracts away (hopefully most) breaking changes.

The main reason for this PR is that I am updating the feature-dan2 branch to latest development, this led to the need to update our libp2p fork both to update tari-crypto and because libp2p also uses hickory and their version conflicts with the base layer version `0.25.0-alpha.2 `. I have updated to `0.25.0-alpha.4` (what libp2p currently uses) instead of  `0.25.1` for this reason. Future hickory upgrades should be simple to implement.


How Has This Been Tested?
---
Peer seed unit test that queries real DNS 

What process can a PR reviewer use to test or verify this change?
---
Autoupdate, peer seeds and tari pulse should work as before
<!-- Checklist -->
<!-- 1. Is the title of your PR in the form that would make nice release notes? The title, excluding the conventional commit
tag, will be included exactly as is in the CHANGELOG, so please think about it carefully. -->


Breaking Changes
---

- [x] None
- [ ] Requires data directory on base node to be deleted
- [ ] Requires hard fork
- [ ] Other - Please specify

<!-- Does this include a breaking change? If so, include this line as a footer -->
<!-- BREAKING CHANGE: Description what the user should do, e.g. delete a database, resync the chain -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **Chores**
  - Removed deprecated dependencies and updated versions of key components to improve system stability.
- **Refactor**
  - Simplified DNS connectivity and resolution processes for a more efficient networking experience.
  - Enhanced clarity and maintainability of the DNS client code by transitioning to a struct-based design.
- **Tests**
  - Consolidated testing efforts by removing outdated test code, focusing verification on essential functionality, resulting in reduced test coverage for certain features.
  
Overall, these improvements enhance performance and reliability while reducing complexity.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.license.ignore b/.license.ignore
index dddcb632e84..8dcd4b5b462 100644
--- a/.license.ignore
+++ b/.license.ignore
@@ -2,8 +2,6 @@
 ./applications/minotari_node/assets/tari_logo.rs
 ./applications/minotari_node/osx-pkg/entitlements.xml
 ./base_layer/contacts/src/schema.rs
-./base_layer/core/src/base_node/tari_pulse_service/20326.rsa
-./base_layer/core/src/base_node/tari_pulse_service/38696.rsa
 ./base_layer/core/src/transactions/transaction_key_manager/schema.rs
 ./base_layer/key_manager/src/schema.rs
 ./base_layer/wallet/src/schema.rs
diff --git a/Cargo.lock b/Cargo.lock
index 87e8c7869cf..d2ebee0293f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2445,6 +2445,19 @@ dependencies = [
  "byteorder",
 ]
 
+[[package]]
+name = "generator"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "log",
+ "rustversion",
+ "windows",
+]
+
 [[package]]
 name = "generic-array"
 version = "0.14.7"
@@ -2733,50 +2746,26 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
 
-[[package]]
-name = "hickory-client"
-version = "0.25.0-alpha.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90078f18923f3a7663f62fbd43c4030de758d16efae0071cdf3ef9c6358cbf49"
-dependencies = [
- "cfg-if",
- "data-encoding",
- "futures-channel",
- "futures-util",
- "hickory-proto",
- "once_cell",
- "radix_trie",
- "rand",
- "thiserror 1.0.69",
- "tokio",
- "tracing",
-]
-
 [[package]]
 name = "hickory-proto"
-version = "0.25.0-alpha.2"
+version = "0.25.0-alpha.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8270a1857fb962b9914aafd46a89a187a4e63d0eb4190c327e7c7b8256a2d055"
+checksum = "d063c0692ee669aa6d261988aa19ca5510f1cc40e4f211024f50c888499a35d7"
 dependencies = [
  "async-recursion",
  "async-trait",
- "bitflags 2.6.0",
  "cfg-if",
  "data-encoding",
  "enum-as-inner",
  "futures-channel",
  "futures-io",
  "futures-util",
- "idna 0.5.0",
+ "idna",
  "ipnet",
  "once_cell",
- "openssl",
  "rand",
- "ring",
  "rustls",
- "rustls-pemfile 2.2.0",
- "thiserror 1.0.69",
- "time",
+ "thiserror 2.0.6",
  "tinyvec",
  "tokio",
  "tokio-rustls",
@@ -2786,22 +2775,24 @@ dependencies = [
 
 [[package]]
 name = "hickory-resolver"
-version = "0.25.0-alpha.2"
+version = "0.25.0-alpha.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c110355b5703070d9e29c344d79818a7cde3de9c27fc35750defea6074b0ad"
+checksum = "42bc352e4412fb657e795f79b4efcf2bd60b59ee5ca0187f3554194cd1107a27"
 dependencies = [
  "cfg-if",
  "futures-util",
  "hickory-proto",
  "ipconfig",
- "lru-cache",
+ "moka",
  "once_cell",
  "parking_lot 0.12.3",
  "rand",
  "resolv-conf",
+ "rustls",
  "smallvec",
- "thiserror 1.0.69",
+ "thiserror 2.0.6",
  "tokio",
+ "tokio-rustls",
  "tracing",
 ]
 
@@ -3066,7 +3057,7 @@ dependencies = [
  "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
- "windows-core",
+ "windows-core 0.52.0",
 ]
 
 [[package]]
@@ -3211,16 +3202,6 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
-[[package]]
-name = "idna"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
-dependencies = [
- "unicode-bidi",
- "unicode-normalization",
-]
-
 [[package]]
 name = "idna"
 version = "1.0.3"
@@ -3781,12 +3762,16 @@ dependencies = [
 ]
 
 [[package]]
-name = "lru-cache"
-version = "0.1.2"
+name = "loom"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
 dependencies = [
- "linked-hash-map",
+ "cfg-if",
+ "generator",
+ "scoped-tls",
+ "tracing",
+ "tracing-subscriber",
 ]
 
 [[package]]
@@ -4358,6 +4343,25 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "moka"
+version = "0.12.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "loom",
+ "parking_lot 0.12.3",
+ "portable-atomic",
+ "rustc_version",
+ "smallvec",
+ "tagptr",
+ "thiserror 1.0.69",
+ "uuid",
+]
+
 [[package]]
 name = "monero"
 version = "0.21.0"
@@ -4515,6 +4519,16 @@ dependencies = [
  "nom",
 ]
 
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
 [[package]]
 name = "num-bigint"
 version = "0.4.6"
@@ -4764,6 +4778,12 @@ version = "6.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
 
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
 [[package]]
 name = "p256"
 version = "0.13.2"
@@ -6829,6 +6849,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "tagptr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
+
 [[package]]
 name = "tap"
 version = "1.0.1"
@@ -7124,7 +7150,6 @@ dependencies = [
  "fs2",
  "futures 0.3.31",
  "hex",
- "hickory-client",
  "hickory-proto",
  "integer-encoding",
  "lmdb-zero",
@@ -7363,7 +7388,6 @@ dependencies = [
  "config",
  "fs2",
  "futures 0.3.31",
- "hickory-client",
  "hickory-proto",
  "hickory-resolver",
  "lmdb-zero",
@@ -7372,7 +7396,6 @@ dependencies = [
  "prost 0.13.4",
  "rand",
  "reqwest",
- "rustls",
  "semver",
  "serde",
  "tari_common",
@@ -7389,7 +7412,6 @@ dependencies = [
  "tokio-stream",
  "toml 0.5.11",
  "tower 0.4.13",
- "webpki-roots",
 ]
 
 [[package]]
@@ -8009,6 +8031,17 @@ dependencies = [
  "valuable",
 ]
 
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
 [[package]]
 name = "tracing-subscriber"
 version = "0.3.19"
@@ -8016,12 +8049,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
 dependencies = [
  "matchers",
+ "nu-ansi-term",
  "once_cell",
  "regex",
  "sharded-slab",
+ "smallvec",
  "thread_local",
  "tracing",
  "tracing-core",
+ "tracing-log",
 ]
 
 [[package]]
@@ -8111,12 +8147,6 @@ version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
 
-[[package]]
-name = "unicode-bidi"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
-
 [[package]]
 name = "unicode-ident"
 version = "1.0.14"
@@ -8129,15 +8159,6 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
 
-[[package]]
-name = "unicode-normalization"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
-dependencies = [
- "tinyvec",
-]
-
 [[package]]
 name = "unicode-segmentation"
 version = "1.12.0"
@@ -8200,7 +8221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
 dependencies = [
  "form_urlencoded",
- "idna 1.0.3",
+ "idna",
  "percent-encoding",
 ]
 
@@ -8472,6 +8493,16 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
+dependencies = [
+ "windows-core 0.58.0",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "windows-core"
 version = "0.52.0"
@@ -8481,6 +8512,60 @@ dependencies = [
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-core"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-strings",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
+dependencies = [
+ "windows-result",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml
index 5221629a5a4..18030e29255 100644
--- a/base_layer/core/Cargo.toml
+++ b/base_layer/core/Cargo.toml
@@ -19,7 +19,6 @@ base_node = [
     "base_node_proto",
     "monero",
     "randomx-rs",
-    "hickory-client",
 ]
 base_node_proto = []
 benches = ["base_node"]
@@ -97,11 +96,7 @@ tiny-keccak = { package = "tari-tiny-keccak", version = "2.0.2", features = [
     "keccak",
 ] }
 dirs-next = "1.0.2"
-hickory-client = { version = "=0.25.0-alpha.2", features = [
-    "dns-over-rustls",
-    "dnssec-openssl",
-], optional = true }
-hickory-proto = { version = "=0.25.0-alpha.2" }
+hickory-proto = { version = "=0.25.0-alpha.4" }
 anyhow = "1.0.53"
 
 [dev-dependencies]
diff --git a/base_layer/core/src/base_node/tari_pulse_service/20326.rsa b/base_layer/core/src/base_node/tari_pulse_service/20326.rsa
deleted file mode 100644
index acd48e8bd68..00000000000
--- a/base_layer/core/src/base_node/tari_pulse_service/20326.rsa
+++ /dev/null
@@ -1 +0,0 @@
-AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=
\ No newline at end of file
diff --git a/base_layer/core/src/base_node/tari_pulse_service/38696.rsa b/base_layer/core/src/base_node/tari_pulse_service/38696.rsa
deleted file mode 100644
index 7948d28a477..00000000000
--- a/base_layer/core/src/base_node/tari_pulse_service/38696.rsa
+++ /dev/null
@@ -1 +0,0 @@
-AwEAAa96jeuknZlaeSrvyAJj6ZHv28hhOKkx3rLGXVaC6rXTsDc449/cidltpkyGwCJNnOAlFNKF2jBosZBU5eeHspaQWOmOElZsjICMQMC3aeHbGiShvZsx4wMYSjH8e7Vrhbu6irwCzVBApESjbUdpWWmEnhathWu1jo+siFUiRAAxm9qyJNg/wOZqqzL/dL/q8PkcRU5oUKEpUge71M3ej2/7CPqpdVwuMoTvoB+ZOT4YeGyxMvHmbrxlFzGOHOijtzN+u1TQNatX2XBuzZNQ1K+s2CXkPIZo7s6JgZyvaBevYtxPvYLw4z9mR7K2vaF18UYH9Z9GNUUeayffKC73PYc=</PublicKey>
\ No newline at end of file
diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs
index 110b8f77d35..2ba7702350b 100644
--- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs
+++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs
@@ -20,26 +20,17 @@
 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-use std::{cmp::min, str::FromStr, time::Duration};
+use std::{cmp::min, time::Duration};
 
 use futures::future;
-use hickory_client::{
-    client::{AsyncDnssecClient, ClientHandle},
-    proto::{
-        iocompat::AsyncIoTokioAsStd,
-        rr::dnssec::{public_key::Rsa, SigSigner, TrustAnchor},
-        xfer::DnsMultiplexer,
-    },
-    rr::{DNSClass, Name, RData, Record, RecordType},
-    tcp::TcpClientStream,
-};
 use log::{debug, info, trace, warn};
 use serde::{Deserialize, Serialize};
-use tari_p2p::Network;
+use tari_common::DnsNameServer;
+use tari_p2p::{dns::DnsClient, Network};
 use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext};
 use tari_shutdown::ShutdownSignal;
 use tari_utilities::hex::Hex;
-use tokio::{net::TcpStream as TokioTcpStream, sync::watch, time, time::MissedTickBehavior};
+use tokio::{sync::watch, time, time::MissedTickBehavior};
 
 use super::LocalNodeCommsInterface;
 use crate::base_node::comms_interface::CommsInterfaceError;
@@ -61,26 +52,26 @@ impl Default for TariPulseConfig {
     }
 }
 
-fn get_network_dns_name(network: Network) -> Name {
+fn get_network_dns_name(network: Network) -> &'static str {
     match network {
-        Network::NextNet => Name::from_str("checkpoints-nextnet.tari.com").expect("infallible"),
-        Network::MainNet => Name::from_str("checkpoints-mainnet.tari.com").expect("infallible"),
-        Network::Esmeralda => Name::from_str("checkpoints-esmeralda.tari.com").expect("infallible"),
-        Network::StageNet => Name::from_str("checkpoints-stagenet.tari.com").expect("infallible"),
-        Network::Igor => Name::from_str("checkpoints-igor.tari.com").expect("infallible"),
-        Network::LocalNet => Name::from_str("checkpoints-localnet.tari.com").expect("infallible"),
+        Network::NextNet => "checkpoints-nextnet.tari.com",
+        Network::MainNet => "checkpoints-mainnet.tari.com",
+        Network::Esmeralda => "checkpoints-esmeralda.tari.com",
+        Network::StageNet => "checkpoints-stagenet.tari.com",
+        Network::Igor => "checkpoints-igor.tari.com",
+        Network::LocalNet => "checkpoints-localnet.tari.com",
     }
 }
 
 pub struct TariPulseService {
-    dns_name: Name,
+    dns_name: &'static str,
     config: TariPulseConfig,
     shutdown_signal: ShutdownSignal,
 }
 
 impl TariPulseService {
     pub async fn new(config: TariPulseConfig, shutdown_signal: ShutdownSignal) -> Result<Self, anyhow::Error> {
-        let dns_name: Name = get_network_dns_name(config.clone().network);
+        let dns_name = get_network_dns_name(config.clone().network);
         info!(target: LOG_TARGET, "Tari Pulse Service initialized with DNS name: {}", dns_name);
         Ok(Self {
             dns_name,
@@ -89,29 +80,8 @@ impl TariPulseService {
         })
     }
 
-    pub fn default_trust_anchor() -> TrustAnchor {
-        const ROOT_ANCHOR_ORIG: &[u8] = include_bytes!("20326.rsa");
-        const ROOT_ANCHOR_CURRENT: &[u8] = include_bytes!("38696.rsa");
-
-        let mut anchor = TrustAnchor::new();
-        anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_ORIG).expect("Invalid ROOT_ANCHOR_ORIG"));
-        anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_CURRENT).expect("Invalid ROOT_ANCHOR_CURRENT"));
-        anchor
-    }
-
-    async fn get_dns_client(&self) -> Result<AsyncDnssecClient, anyhow::Error> {
-        let timeout: Duration = Duration::from_secs(5);
-        let trust_anchor = Self::default_trust_anchor();
-
-        let (stream, handle) = TcpClientStream::<AsyncIoTokioAsStd<TokioTcpStream>>::new(([1, 1, 1, 1], 53).into());
-        let dns_muxer = DnsMultiplexer::<_, SigSigner>::with_timeout(stream, handle, timeout, None);
-        let (client, bg) = AsyncDnssecClient::builder(dns_muxer)
-            .trust_anchor(trust_anchor)
-            .build()
-            .await?;
-
-        tokio::spawn(bg);
-
+    async fn get_dns_client(&self) -> Result<DnsClient, anyhow::Error> {
+        let client = DnsClient::connect(DnsNameServer::System).await?;
         Ok(client)
     }
 
@@ -209,21 +179,12 @@ impl TariPulseService {
 
     async fn fetch_checkpoints(&mut self) -> Result<Vec<(u64, String)>, anyhow::Error> {
         let mut client = self.get_dns_client().await?;
-        let query = client.query(self.dns_name.clone(), DNSClass::IN, RecordType::TXT);
-        let response = query.await?;
-        let answers: &[Record] = response.answers();
-        let checkpoints: Vec<(u64, String)> = answers
+        let response = client.query_txt(self.dns_name).await?;
+        let checkpoints: Vec<(u64, String)> = response
             .iter()
-            .filter_map(|record| {
-                if let RData::TXT(txt) = record.data() {
-                    let ascii_txt = txt.txt_data().iter().fold(String::new(), |mut acc, bytes| {
-                        acc.push_str(&String::from_utf8_lossy(bytes));
-                        acc
-                    });
-                    let (height, hash) = ascii_txt.split_once(':')?;
-                    return Some((height.parse().ok()?, hash.to_string()));
-                }
-                None
+            .filter_map(|ascii_txt| {
+                let (height, hash) = ascii_txt.split_once(':')?;
+                Some((height.parse().ok()?, hash.to_string()))
             })
             .collect();
 
diff --git a/base_layer/p2p/Cargo.toml b/base_layer/p2p/Cargo.toml
index 75aecfe0de3..af820bc3797 100644
--- a/base_layer/p2p/Cargo.toml
+++ b/base_layer/p2p/Cargo.toml
@@ -26,11 +26,6 @@ pgp = { version = "0.14.2", optional = true }
 prost = "0.13.3"
 rand = "0.8"
 reqwest = { version = "0.11", optional = true, default-features = false }
-rustls = { version = "0.23.13", default-features = false, features = [
-    "logging",
-    "std",
-    "tls12",
-] }
 semver = { version = "1.0.1", optional = true }
 serde = "1.0.90"
 thiserror = "1.0.26"
@@ -39,10 +34,8 @@ tokio-stream = { version = "0.1.9", default-features = false, features = [
     "time",
 ] }
 tower = "0.4.11"
-hickory-client = { version = "=0.25.0-alpha.2", features = ["dns-over-rustls"] }
-hickory-resolver = "0.25.0-alpha.2"
-hickory-proto = { version = "=0.25.0-alpha.2" }
-webpki-roots = "0.26.6"
+hickory-resolver = { version = "=0.25.0-alpha.4", features = ["tokio-runtime", "dns-over-tls", "dns-over-rustls"] }
+hickory-proto = { version = "=0.25.0-alpha.4" }
 
 [dev-dependencies]
 tari_test_utils = { workspace = true }
@@ -60,4 +53,4 @@ test-mocks = []
 auto-update = ["reqwest/default", "pgp", "semver"]
 
 [package.metadata.cargo-machete]
-ignored = ["hickory-proto"] #fix hickory-proto version to same alpha.2
+ignored = []
diff --git a/base_layer/p2p/src/auto_update/dns.rs b/base_layer/p2p/src/auto_update/dns.rs
index 342062d0f67..ebb4245a671 100644
--- a/base_layer/p2p/src/auto_update/dns.rs
+++ b/base_layer/p2p/src/auto_update/dns.rs
@@ -33,7 +33,7 @@ use tari_utilities::hex::{from_hex, Hex, HexError};
 use thiserror::Error;
 
 use super::{error::AutoUpdateError, AutoUpdateConfig, Version};
-use crate::dns::{default_trust_anchor, DnsClient};
+use crate::dns::DnsClient;
 
 const LOG_TARGET: &str = "p2p::auto_update::dns";
 
@@ -47,7 +47,7 @@ impl DnsSoftwareUpdate {
     pub async fn connect(config: AutoUpdateConfig) -> Result<Self, AutoUpdateError> {
         let name_server = config.name_server.clone();
         let client = if config.use_dnssec {
-            DnsClient::connect_secure(name_server, default_trust_anchor()).await?
+            DnsClient::connect_secure(name_server).await?
         } else {
             DnsClient::connect(name_server).await?
         };
@@ -204,104 +204,14 @@ impl Display for UpdateSpec {
 
 #[cfg(test)]
 mod test {
-    use hickory_client::{
-        op::Query,
-        proto::{
-            rr::{rdata, Name, RData, RecordType},
-            xfer::DnsResponse,
-        },
-        rr::Record,
-    };
-
     use super::*;
-    use crate::dns::mock;
-
-    fn create_txt_record(contents: Vec<&str>) -> DnsResponse {
-        let resp_query = Query::query(Name::from_str("test.local.").unwrap(), RecordType::A);
-
-        let origin = Name::parse("example.com.", None).unwrap();
-        let record = Record::from_rdata(
-            origin,
-            86300,
-            RData::TXT(rdata::TXT::new(contents.into_iter().map(ToString::to_string).collect())),
-        );
-        DnsResponse::from_message(mock::message(resp_query, vec![record], vec![], vec![])).unwrap()
-    }
-
-    mod update_spec {
-        use super::*;
-
-        #[test]
-        fn it_parses_update_spec_string() {
-            let update_spec = UpdateSpec::from_str("base-node:linux-x64:1.0.0:bada55").unwrap();
-            assert_eq!(update_spec.application, ApplicationType::BaseNode);
-            assert_eq!(update_spec.arch, "linux-x64");
-            assert_eq!(update_spec.version.to_string(), "1.0.0");
-            assert_eq!(update_spec.hash, [0xBA, 0xDA, 0x55]);
-        }
-    }
-
-    mod dns_software_update {
-        use std::time::Duration;
 
-        use super::*;
-
-        impl AutoUpdateConfig {
-            fn get_test_defaults() -> Self {
-                Self {
-                    override_from: None,
-                    name_server: Default::default(),
-                    update_uris: vec!["test.local".to_string()].into(),
-                    use_dnssec: true,
-                    download_base_url: "https://tari-binaries.s3.amazonaws.com/latest".to_string(),
-                    hashes_url: "https://raw.githubusercontent.com/tari-project/tari/development/meta/hashes.txt"
-                        .to_string(),
-                    hashes_sig_url:
-                        "https://raw.githubusercontent.com/tari-project/tari/development/meta/hashes.txt.sig"
-                            .to_string(),
-                    check_interval: Some(Duration::from_secs(30)),
-                }
-            }
-        }
-
-        #[tokio::test]
-        async fn it_ignores_non_conforming_txt_entries() {
-            let records = vec![
-                Ok(create_txt_record(vec![":::"])),
-                Ok(create_txt_record(vec!["base-node:::"])),
-                Ok(create_txt_record(vec!["base-node::1.0:"])),
-                Ok(create_txt_record(vec!["base-node:android-armv7:0.1.0:abcdef"])),
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.0:bada55"])),
-            ];
-            let updater = DnsSoftwareUpdate {
-                client: DnsClient::connect_mock(records).await.unwrap(),
-                config: AutoUpdateConfig::get_test_defaults(),
-            };
-            let spec = updater
-                .check_for_updates(ApplicationType::BaseNode, "linux-x86_64", &"1.0.0".parse().unwrap())
-                .await
-                .unwrap();
-            assert!(spec.is_none());
-        }
-
-        #[tokio::test]
-        async fn it_returns_best_update() {
-            let records = vec![
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.0:abcdef"])),
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.1:abcdef01"])),
-            ];
-            let updater = DnsSoftwareUpdate {
-                client: DnsClient::connect_mock(records).await.unwrap(),
-                config: AutoUpdateConfig::get_test_defaults(),
-            };
-            let spec = updater
-                .check_for_updates(ApplicationType::BaseNode, "linux-x86_64", &"1.0.0".parse().unwrap())
-                .await
-                .unwrap()
-                .unwrap();
-
-            assert_eq!(spec.version.to_string(), "1.0.1");
-            assert_eq!(spec.hash, [0xab, 0xcd, 0xef, 0x01]);
-        }
+    #[test]
+    fn it_parses_update_spec_string() {
+        let update_spec = UpdateSpec::from_str("base-node:linux-x64:1.0.0:bada55").unwrap();
+        assert_eq!(update_spec.application, ApplicationType::BaseNode);
+        assert_eq!(update_spec.arch, "linux-x64");
+        assert_eq!(update_spec.version.to_string(), "1.0.0");
+        assert_eq!(update_spec.hash, [0xBA, 0xDA, 0x55]);
     }
 }
diff --git a/base_layer/p2p/src/dns/client.rs b/base_layer/p2p/src/dns/client.rs
index 0d1a544ee88..ec49c1c7b62 100644
--- a/base_layer/p2p/src/dns/client.rs
+++ b/base_layer/p2p/src/dns/client.rs
@@ -20,228 +20,105 @@
 //  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 //  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-use std::{net::SocketAddr, sync::Arc, time::Duration};
-
-use futures::{future, FutureExt};
-#[cfg(test)]
-use hickory_client::proto::error::ProtoError;
-use hickory_client::{
-    client::{AsyncClient, AsyncDnssecClient, ClientHandle},
-    op::Query,
-    proto::{
-        iocompat::AsyncIoTokioAsStd,
-        rr::dnssec::{SigSigner, TrustAnchor},
-        rustls::tls_client_connect,
-        xfer::DnsResponse,
-        DnsHandle,
-        DnsMultiplexer,
-    },
-    rr::{DNSClass, IntoName, RecordType},
+use hickory_proto::{
+    rr::IntoName,
     serialize::binary::{BinEncodable, BinEncoder},
-    tcp::TcpClientStream,
+    xfer::Protocol,
+};
+use hickory_resolver::{
+    config::{NameServerConfig, ResolverConfig, ResolverOpts},
+    name_server::TokioConnectionProvider,
+    TokioResolver,
 };
-use hickory_resolver::system_conf;
-use rustls::{ClientConfig, RootCertStore};
+use log::*;
 use tari_common::DnsNameServer;
-use tari_shutdown::Shutdown;
-use tokio::task;
 
 use super::DnsClientError;
-#[cfg(test)]
-use crate::dns::mock::{DefaultOnSend, MockClientHandle};
-use crate::dns::roots;
 
-const TIMEOUT: Duration = Duration::from_secs(5);
+const LOG_TARGET: &str = "tari::p2p::dns::client";
 
 #[derive(Clone)]
-pub enum DnsClient {
-    Secure(Client<AsyncDnssecClient>),
-    Normal(Client<AsyncClient>),
-    #[cfg(test)]
-    Mock(Client<MockClientHandle<DefaultOnSend>>),
+pub struct DnsClient {
+    resolver: TokioResolver,
 }
 
 impl DnsClient {
-    pub async fn connect_secure(name_server: DnsNameServer, trust_anchor: TrustAnchor) -> Result<Self, DnsClientError> {
-        let client = Client::connect_dnssec(name_server, trust_anchor).await?;
-        Ok(DnsClient::Secure(client))
+    pub async fn connect_secure(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::Tls),
+        };
+
+        Ok(Self { resolver })
     }
 
     pub async fn connect(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
-        let client = Client::connect(name_server).await?;
-        Ok(DnsClient::Normal(client))
-    }
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::default()),
+        };
 
-    #[cfg(test)]
-    pub async fn connect_mock(messages: Vec<Result<DnsResponse, ProtoError>>) -> Result<Self, DnsClientError> {
-        let client = Client::connect_mock(messages).await?;
-        Ok(DnsClient::Mock(client))
+        Ok(Self { resolver })
     }
 
-    pub async fn lookup(&mut self, query: Query) -> Result<DnsResponse, DnsClientError> {
-        #[cfg(test)]
-        use DnsClient::Mock;
-        use DnsClient::{Normal, Secure};
-        match self {
-            Secure(ref mut client) => client.lookup(query).await,
-            Normal(ref mut client) => client.lookup(query).await,
-            #[cfg(test)]
-            Mock(ref mut client) => client.lookup(query).await,
-        }
+    fn create_resolver(
+        socket_addr: std::net::SocketAddr,
+        tls_dns_name: Option<String>,
+        protocol: Protocol,
+    ) -> TokioResolver {
+        let mut conf = ResolverConfig::new();
+        conf.add_name_server(NameServerConfig {
+            socket_addr,
+            protocol,
+            tls_dns_name,
+            http_endpoint: None,
+            trust_negative_responses: false,
+            bind_addr: None,
+            tls_config: None,
+        });
+        let mut opts = ResolverOpts::default();
+        opts.edns0 = true;
+        opts.try_tcp_on_error = true;
+        TokioResolver::tokio(conf, opts)
     }
 
     pub async fn query_txt<T: IntoName>(&mut self, name: T) -> Result<Vec<String>, DnsClientError> {
-        let mut query = Query::new();
-        query
-            .set_name(name.into_name()?)
-            .set_query_class(DNSClass::IN)
-            .set_query_type(RecordType::TXT);
-
-        let responses = self.lookup(query).await?;
+        let lookup = self.resolver.txt_lookup(name).await?;
 
-        let records = responses
-            .answers()
+        let records = lookup
             .iter()
             .map(|answer| {
-                let mut buf = Vec::new();
+                // pub key + onion is 136 bytes
+                let mut buf = Vec::with_capacity(136);
                 let mut decoder = BinEncoder::new(&mut buf);
-                answer.data().emit(&mut decoder).unwrap();
+                answer.emit(&mut decoder)?;
                 Ok(buf)
             })
-            .collect::<Result<Vec<Vec<u8>>, DnsClientError>>()?
-            .iter()
             .filter_map(|txt| {
-                if txt.is_empty() {
-                    return None;
-                }
-                // Exclude the first length octet from the string result
-                Some(String::from_utf8_lossy(&txt[1..]).to_string())
+                txt.map(|txt| {
+                    if txt.is_empty() {
+                        return None;
+                    }
+                    let len = txt[0] as usize;
+                    if len == 0 {
+                        return None;
+                    }
+                    if len > txt.len() {
+                        warn!(
+                            target: LOG_TARGET,
+                            "Length byte {} is greater than the length of the TXT record {}",
+                            len,
+                            txt.len()
+                        );
+                        return None;
+                    }
+                    // Exclude the first length byte from the string result
+                    Some(String::from_utf8_lossy(&txt[1..len]).to_string())
+                })
+                .transpose()
             })
-            .collect();
+            .collect::<Result<_, DnsClientError>>()?;
 
         Ok(records)
     }
 }
-
-#[derive(Clone)]
-pub struct Client<C> {
-    inner: C,
-    _shutdown: Arc<Shutdown>,
-}
-
-impl Client<AsyncDnssecClient> {
-    pub async fn connect_dnssec(name_server: DnsNameServer, trust_anchor: TrustAnchor) -> Result<Self, DnsClientError> {
-        let shutdown = Shutdown::new();
-        let timeout = Duration::from_secs(5);
-        let (socket_addr, dns_name) = socket_addr_and_dns_name(name_server)?;
-
-        let dns_name = dns_name.ok_or_else(|| DnsClientError::DnsNameRequiredForDnsSec)?;
-        let (stream, handle) = tls_client_connect::<AsyncIoTokioAsStd<tokio::net::TcpStream>>(
-            socket_addr,
-            dns_name,
-            default_tls_client_config(),
-        );
-        let dns_muxer = DnsMultiplexer::<_, SigSigner>::with_timeout(stream, handle, timeout, None);
-
-        let (client, bg) = AsyncDnssecClient::builder(dns_muxer)
-            .trust_anchor(trust_anchor)
-            .build()
-            .await?;
-
-        task::spawn(future::select(shutdown.to_signal(), bg.fuse()));
-
-        Ok(Self {
-            inner: client,
-            _shutdown: Arc::new(shutdown),
-        })
-    }
-}
-
-impl Client<AsyncClient> {
-    pub async fn connect(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
-        let shutdown = Shutdown::new();
-
-        let (socket_addr, dns_name) = socket_addr_and_dns_name(name_server)?;
-
-        let client = match dns_name {
-            Some(dns_name) => {
-                let (stream, handle) = tls_client_connect::<AsyncIoTokioAsStd<tokio::net::TcpStream>>(
-                    socket_addr,
-                    dns_name,
-                    default_tls_client_config(),
-                );
-
-                let (client, bg) = AsyncClient::with_timeout(stream, handle, TIMEOUT, None).await?;
-                task::spawn(future::select(shutdown.to_signal(), bg.fuse()));
-                client
-            },
-            None => {
-                let (stream, handle) =
-                    TcpClientStream::<AsyncIoTokioAsStd<tokio::net::TcpStream>>::new(([8, 8, 8, 8], 53).into());
-                let (client, bg) = AsyncClient::with_timeout(stream, handle, TIMEOUT, None).await?;
-                task::spawn(future::select(shutdown.to_signal(), bg.fuse()));
-                client
-            },
-        };
-
-        Ok(Self {
-            inner: client,
-            _shutdown: Arc::new(shutdown),
-        })
-    }
-}
-
-impl<C> Client<C>
-where C: DnsHandle
-{
-    pub async fn lookup(&mut self, query: Query) -> Result<DnsResponse, DnsClientError> {
-        let client_resp = self
-            .inner
-            .query(query.name().clone(), query.query_class(), query.query_type())
-            .await?;
-
-        Ok(client_resp)
-    }
-}
-
-fn default_tls_client_config() -> Arc<ClientConfig> {
-    let mut root_store = RootCertStore::empty();
-    root_store.extend(roots::TLS_SERVER_ROOTS.iter().cloned());
-
-    let client_config = ClientConfig::builder()
-        .with_root_certificates(root_store)
-        .with_no_client_auth();
-
-    Arc::new(client_config)
-}
-
-fn socket_addr_and_dns_name(server: DnsNameServer) -> Result<(SocketAddr, Option<String>), DnsClientError> {
-    match server {
-        DnsNameServer::System => {
-            let (conf, _opts) = system_conf::read_system_conf()?;
-            let found = conf
-                .name_servers()
-                .iter()
-                .find(|ns| ns.tls_dns_name.is_some())
-                .or_else(|| conf.name_servers().first())
-                .ok_or_else(|| DnsClientError::SystemHasNoDnsServers)?;
-            Ok((found.socket_addr, found.tls_dns_name.clone()))
-        },
-        DnsNameServer::Custom { addr, dns_name } => Ok((addr, dns_name)),
-    }
-}
-
-#[cfg(test)]
-mod mock {
-    use super::*;
-
-    impl Client<MockClientHandle<DefaultOnSend>> {
-        pub async fn connect_mock(messages: Vec<Result<DnsResponse, ProtoError>>) -> Result<Self, ProtoError> {
-            let client = MockClientHandle::mock(messages);
-            Ok(Self {
-                inner: client,
-                _shutdown: Arc::new(Shutdown::new()),
-            })
-        }
-    }
-}
diff --git a/base_layer/p2p/src/dns/error.rs b/base_layer/p2p/src/dns/error.rs
index 53948620623..950057121c4 100644
--- a/base_layer/p2p/src/dns/error.rs
+++ b/base_layer/p2p/src/dns/error.rs
@@ -22,15 +22,12 @@
 
 use std::io;
 
-use hickory_client::{error::ClientError, proto::error::ProtoError};
-use hickory_resolver::error::ResolveError;
+use hickory_resolver::ResolveError;
 
 #[derive(Debug, thiserror::Error)]
 pub enum DnsClientError {
-    #[error("Client failure: {0}")]
-    ClientError(#[from] ClientError),
-    #[error("DNS Protocol error: {0}")]
-    ProtoError(#[from] ProtoError),
+    #[error("Proto error: {0}")]
+    ProtoError(#[from] hickory_proto::ProtoError),
     #[error("DNS timeout error")]
     Timeout,
     #[error("Failed to parse name server string")]
diff --git a/base_layer/p2p/src/dns/mock.rs b/base_layer/p2p/src/dns/mock.rs
deleted file mode 100644
index c809c0146bf..00000000000
--- a/base_layer/p2p/src/dns/mock.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//  Copyright 2021, The Tari Project
-//
-//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
-//  following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
-//  disclaimer.
-//
-//  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
-//  following disclaimer in the documentation and/or other materials provided with the distribution.
-//
-//  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
-//  products derived from this software without specific prior written permission.
-//
-//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-//  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-use std::{pin::Pin, sync::Arc};
-
-use futures::{future, stream, Future};
-use hickory_client::{
-    op::{Message, Query},
-    proto::{
-        error::ProtoError,
-        xfer::{DnsHandle, DnsRequest, DnsResponse},
-    },
-    rr::Record,
-};
-
-#[derive(Clone)]
-pub struct MockClientHandle<O: OnSend> {
-    messages: Arc<Vec<Result<DnsResponse, ProtoError>>>,
-    _on_send: O,
-}
-
-impl MockClientHandle<DefaultOnSend> {
-    /// constructs a new MockClient which returns each Message one after the other
-    pub fn mock(messages: Vec<Result<DnsResponse, ProtoError>>) -> Self {
-        println!("MockClientHandle::mock message count: {}", messages.len());
-
-        MockClientHandle {
-            messages: Arc::new(messages),
-            _on_send: DefaultOnSend,
-        }
-    }
-}
-
-impl<O: OnSend + Unpin> DnsHandle for MockClientHandle<O> {
-    type Response = stream::Once<future::Ready<Result<DnsResponse, ProtoError>>>;
-
-    fn send<R: Into<DnsRequest>>(&self, _: R) -> Self::Response {
-        let responses = (*self.messages)
-            .clone()
-            .into_iter()
-            .try_fold(Message::new(), |mut msg, resp| {
-                resp.map(move |resp| {
-                    msg.add_answers(resp.answers().iter().cloned());
-                    msg
-                })
-            })
-            .and_then(DnsResponse::from_message);
-
-        // let stream = stream::unfold(messages, |mut msgs| async move {
-        //     let msg = msgs.pop()?;
-        //     Some((msg, msgs))
-        // });
-
-        stream::once(future::ready(responses))
-    }
-}
-
-pub fn message(query: Query, answers: Vec<Record>, name_servers: Vec<Record>, additionals: Vec<Record>) -> Message {
-    let mut message = Message::new();
-    message.add_query(query);
-    message.insert_answers(answers);
-    message.insert_name_servers(name_servers);
-    message.insert_additionals(additionals);
-    message
-}
-
-pub trait OnSend: Clone + Send + Sync + 'static {
-    #[allow(dead_code)]
-    fn on_send<E>(
-        &mut self,
-        response: Result<DnsResponse, E>,
-    ) -> Pin<Box<dyn Future<Output = Result<DnsResponse, E>> + Send>>
-    where
-        E: From<ProtoError> + Send + 'static,
-    {
-        Box::pin(future::ready(response))
-    }
-}
-
-#[derive(Clone)]
-pub struct DefaultOnSend;
-
-impl OnSend for DefaultOnSend {}
diff --git a/base_layer/p2p/src/dns/mod.rs b/base_layer/p2p/src/dns/mod.rs
index 6f0f8244e11..d331c19213d 100644
--- a/base_layer/p2p/src/dns/mod.rs
+++ b/base_layer/p2p/src/dns/mod.rs
@@ -6,9 +6,3 @@ pub use client::DnsClient;
 
 mod error;
 pub use error::DnsClientError;
-
-mod roots;
-pub(crate) use roots::default_trust_anchor;
-
-#[cfg(test)]
-pub(crate) mod mock;
diff --git a/base_layer/p2p/src/dns/roots/19036.rsa b/base_layer/p2p/src/dns/roots/19036.rsa
deleted file mode 100644
index 93641029526..00000000000
Binary files a/base_layer/p2p/src/dns/roots/19036.rsa and /dev/null differ
diff --git a/base_layer/p2p/src/dns/roots/20326.rsa b/base_layer/p2p/src/dns/roots/20326.rsa
deleted file mode 100644
index 352389e4ed7..00000000000
Binary files a/base_layer/p2p/src/dns/roots/20326.rsa and /dev/null differ
diff --git a/base_layer/p2p/src/dns/roots/mod.rs b/base_layer/p2p/src/dns/roots/mod.rs
deleted file mode 100644
index 8e90b7abe77..00000000000
--- a/base_layer/p2p/src/dns/roots/mod.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2024 The Tari Project
-// SPDX-License-Identifier: BSD-3-Clause
-
-use hickory_client::proto::rr::dnssec::{public_key::Rsa, TrustAnchor};
-pub use webpki_roots::TLS_SERVER_ROOTS;
-
-#[inline]
-pub fn default_trust_anchor() -> TrustAnchor {
-    // This was copied from the trust-dns crate.
-    const ROOT_ANCHOR_ORIG: &[u8] = include_bytes!("19036.rsa");
-    // This was generated from the `.` root domain in 10/2020.
-    const ROOT_ANCHOR_CURRENT: &[u8] = include_bytes!("20326.rsa");
-
-    let mut anchor = TrustAnchor::new();
-    anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_ORIG).expect("Invalid ROOT_ANCHOR_ORIG"));
-    anchor.insert_trust_anchor(&Rsa::from_public_bytes(ROOT_ANCHOR_CURRENT).expect("Invalid ROOT_ANCHOR_CURRENT"));
-    anchor
-}
diff --git a/base_layer/p2p/src/lib.rs b/base_layer/p2p/src/lib.rs
index f5c3a0a9767..e584a98a691 100644
--- a/base_layer/p2p/src/lib.rs
+++ b/base_layer/p2p/src/lib.rs
@@ -39,7 +39,7 @@ pub mod tari_message;
 mod tor_authentication;
 pub mod transport;
 
-mod dns;
+pub mod dns;
 
 // Re-export
 pub use socks_authentication::SocksAuthentication;
diff --git a/base_layer/p2p/src/peer_seeds.rs b/base_layer/p2p/src/peer_seeds.rs
index 61ee1e4f1f0..fe822c4be2b 100644
--- a/base_layer/p2p/src/peer_seeds.rs
+++ b/base_layer/p2p/src/peer_seeds.rs
@@ -38,7 +38,7 @@ use tari_comms::{
 use tari_utilities::hex::Hex;
 
 use super::dns::DnsClientError;
-use crate::dns::{default_trust_anchor, DnsClient};
+use crate::dns::DnsClient;
 
 #[derive(Clone)]
 pub struct DnsSeedResolver {
@@ -52,7 +52,7 @@ impl DnsSeedResolver {
     /// ## Arguments
     /// -`name_server` - the DNS name server to use to resolve records
     pub async fn connect_secure(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
-        let client = DnsClient::connect_secure(name_server, default_trust_anchor()).await?;
+        let client = DnsClient::connect_secure(name_server).await?;
         Ok(Self { client })
     }
 
@@ -165,8 +165,6 @@ impl From<SeedPeer> for Peer {
 mod test {
     use super::*;
 
-    const TEST_NAME: &str = "test.local.";
-
     mod peer_seed {
         use super::*;
 
@@ -228,17 +226,7 @@ mod test {
     }
 
     mod peer_seed_resolver {
-        use hickory_client::{
-            proto::{
-                op::Query,
-                rr::{DNSClass, Name},
-                xfer::DnsResponse,
-            },
-            rr::{rdata, RData, Record, RecordType},
-        };
-
         use super::*;
-        use crate::dns::mock;
 
         #[tokio::test]
         #[ignore = "Useful for developer testing but will fail unless the DNS has TXT records setup correctly."]
@@ -248,71 +236,5 @@ mod test {
             println!("{:?}", seeds);
             assert!(!seeds.is_empty());
         }
-
-        fn create_txt_record(contents: Vec<&str>) -> DnsResponse {
-            let mut resp_query = Query::query(Name::from_str(TEST_NAME).unwrap(), RecordType::TXT);
-            resp_query.set_query_class(DNSClass::IN);
-
-            let origin = Name::parse("example.com.", None).unwrap();
-            let record = Record::from_rdata(
-                origin,
-                86300,
-                RData::TXT(rdata::TXT::new(contents.into_iter().map(ToString::to_string).collect())),
-            );
-
-            DnsResponse::from_message(mock::message(resp_query, vec![record], vec![], vec![])).unwrap()
-        }
-
-        #[tokio::test]
-        async fn it_returns_peer_seeds() {
-            let records = vec![
-                // Multiple addresses(works)
-                Ok(create_txt_record(vec![
-                    "fab24c542183073996ddf3a6c73ff8b8562fed351d252ec5cb8f269d1ad92f0c::/ip4/127.0.0.1/tcp/8000::/\
-                     onion3/bsmuof2cn4y2ysz253gzsvg3s72fcgh4f3qcm3hdlxdtcwe6al2dicyd:1234",
-                ])),
-                // Misc
-                Ok(create_txt_record(vec!["v=spf1 include:_spf.spf.com ~all"])),
-                // Single address (works)
-                Ok(create_txt_record(vec![
-                    "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a::/ip4/127.0.0.1/tcp/8000",
-                ])),
-                // Single address trailing delim
-                Ok(create_txt_record(vec![
-                    "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a::/ip4/127.0.0.1/tcp/8000::",
-                ])),
-                // Invalid public key
-                Ok(create_txt_record(vec![
-                    "07e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a::/ip4/127.0.0.1/tcp/8000",
-                ])),
-                // No Address with delim
-                Ok(create_txt_record(vec![
-                    "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a::",
-                ])),
-                // No Address no delim
-                Ok(create_txt_record(vec![
-                    "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a",
-                ])),
-                // Invalid address
-                Ok(create_txt_record(vec![
-                    "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a::/onion3/invalid:1234",
-                ])),
-            ];
-            let mut resolver = DnsSeedResolver {
-                client: DnsClient::connect_mock(records).await.unwrap(),
-            };
-            let seeds = resolver.resolve(TEST_NAME).await.unwrap();
-            assert_eq!(seeds.len(), 2);
-            assert_eq!(
-                seeds[0].public_key.to_hex(),
-                "fab24c542183073996ddf3a6c73ff8b8562fed351d252ec5cb8f269d1ad92f0c"
-            );
-            assert_eq!(seeds[0].addresses.len(), 2);
-            assert_eq!(
-                seeds[1].public_key.to_hex(),
-                "06e98e9c5eb52bd504836edec1878eccf12eb9f26a5fe5ec0e279423156e657a"
-            );
-            assert_eq!(seeds[1].addresses.len(), 1);
-        }
     }
 }
diff --git a/supply-chain/config.toml b/supply-chain/config.toml
index 5dd44ef9c61..aa22a8c6018 100644
--- a/supply-chain/config.toml
+++ b/supply-chain/config.toml
@@ -383,18 +383,6 @@ criteria = "safe-to-deploy"
 version = "0.4.39"
 criteria = "safe-to-deploy"
 
-[[exemptions.ciborium]]
-version = "0.2.2"
-criteria = "safe-to-run"
-
-[[exemptions.ciborium-io]]
-version = "0.2.2"
-criteria = "safe-to-run"
-
-[[exemptions.ciborium-ll]]
-version = "0.2.2"
-criteria = "safe-to-run"
-
 [[exemptions.cidr]]
 version = "0.1.1"
 criteria = "safe-to-deploy"
@@ -835,6 +823,10 @@ criteria = "safe-to-run"
 version = "0.3.31"
 criteria = "safe-to-deploy"
 
+[[exemptions.generator]]
+version = "0.8.4"
+criteria = "safe-to-deploy"
+
 [[exemptions.generic-array]]
 version = "0.14.7"
 criteria = "safe-to-deploy"
@@ -883,10 +875,6 @@ criteria = "safe-to-deploy"
 version = "0.4.7"
 criteria = "safe-to-deploy"
 
-[[exemptions.half]]
-version = "2.4.1"
-criteria = "safe-to-run"
-
 [[exemptions.hashbrown]]
 version = "0.14.5"
 criteria = "safe-to-deploy"
@@ -927,16 +915,12 @@ criteria = "safe-to-deploy"
 version = "0.4.1"
 criteria = "safe-to-deploy"
 
-[[exemptions.hickory-client]]
-version = "0.25.0-alpha.2"
-criteria = "safe-to-deploy"
-
 [[exemptions.hickory-proto]]
-version = "0.25.0-alpha.2"
+version = "0.25.0-alpha.4"
 criteria = "safe-to-deploy"
 
 [[exemptions.hickory-resolver]]
-version = "0.25.0-alpha.2"
+version = "0.25.0-alpha.4"
 criteria = "safe-to-deploy"
 
 [[exemptions.hidapi]]
@@ -1199,8 +1183,8 @@ criteria = "safe-to-deploy"
 version = "1.3.0"
 criteria = "safe-to-deploy"
 
-[[exemptions.lru-cache]]
-version = "0.1.2"
+[[exemptions.loom]]
+version = "0.7.2"
 criteria = "safe-to-deploy"
 
 [[exemptions.mac]]
@@ -1295,6 +1279,10 @@ criteria = "safe-to-deploy"
 version = "1.0.3"
 criteria = "safe-to-deploy"
 
+[[exemptions.moka]]
+version = "0.12.10"
+criteria = "safe-to-deploy"
+
 [[exemptions.monero]]
 version = "0.21.0"
 criteria = "safe-to-deploy"
@@ -1683,10 +1671,6 @@ criteria = "safe-to-deploy"
 version = "0.2.1"
 criteria = "safe-to-deploy"
 
-[[exemptions.rand]]
-version = "0.8.5"
-criteria = "safe-to-deploy"
-
 [[exemptions.rand_core]]
 version = "0.5.1"
 criteria = "safe-to-deploy"
@@ -2031,6 +2015,10 @@ criteria = "safe-to-deploy"
 version = "0.5.0"
 criteria = "safe-to-deploy"
 
+[[exemptions.tagptr]]
+version = "0.2.0"
+criteria = "safe-to-deploy"
+
 [[exemptions.tari-tiny-keccak]]
 version = "2.0.2"
 criteria = "safe-to-deploy"
@@ -2147,18 +2135,10 @@ criteria = "safe-to-deploy"
 version = "0.11.0"
 criteria = "safe-to-deploy"
 
-[[exemptions.thiserror]]
-version = "1.0.69"
-criteria = "safe-to-deploy"
-
 [[exemptions.thiserror]]
 version = "2.0.6"
 criteria = "safe-to-deploy"
 
-[[exemptions.thiserror-impl]]
-version = "1.0.69"
-criteria = "safe-to-deploy"
-
 [[exemptions.thiserror-impl]]
 version = "2.0.6"
 criteria = "safe-to-deploy"
@@ -2275,6 +2255,10 @@ criteria = "safe-to-deploy"
 version = "0.1.33"
 criteria = "safe-to-deploy"
 
+[[exemptions.tracing-log]]
+version = "0.2.0"
+criteria = "safe-to-deploy"
+
 [[exemptions.tracing-subscriber]]
 version = "0.3.19"
 criteria = "safe-to-deploy"
@@ -2315,10 +2299,6 @@ criteria = "safe-to-deploy"
 version = "2.8.0"
 criteria = "safe-to-deploy"
 
-[[exemptions.unicode-bidi]]
-version = "0.3.17"
-criteria = "safe-to-deploy"
-
 [[exemptions.unsafe-any-ors]]
 version = "1.0.0"
 criteria = "safe-to-deploy"
@@ -2431,8 +2411,28 @@ criteria = "safe-to-deploy"
 version = "0.4.0"
 criteria = "safe-to-deploy"
 
+[[exemptions.windows]]
+version = "0.58.0"
+criteria = "safe-to-deploy"
+
 [[exemptions.windows-core]]
-version = "0.52.0"
+version = "0.58.0"
+criteria = "safe-to-deploy"
+
+[[exemptions.windows-implement]]
+version = "0.58.0"
+criteria = "safe-to-deploy"
+
+[[exemptions.windows-interface]]
+version = "0.58.0"
+criteria = "safe-to-deploy"
+
+[[exemptions.windows-result]]
+version = "0.2.0"
+criteria = "safe-to-deploy"
+
+[[exemptions.windows-strings]]
+version = "0.1.0"
 criteria = "safe-to-deploy"
 
 [[exemptions.windows-sys]]
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index f9359f443fe..ad6a6ccdd2d 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -29,13 +29,6 @@ user-id = 4484
 user-login = "hsivonen"
 user-name = "Henri Sivonen"
 
-[[publisher.unicode-normalization]]
-version = "0.1.24"
-when = "2024-09-17"
-user-id = 1139
-user-login = "Manishearth"
-user-name = "Manish Goregaokar"
-
 [[publisher.unicode-segmentation]]
 version = "1.12.0"
 when = "2024-09-13"
@@ -302,12 +295,24 @@ who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 version = "0.1.0"
 
+[[audits.bytecode-alliance.audits.nu-ansi-term]]
+who = "Pat Hickey <phickey@fastly.com>"
+criteria = "safe-to-deploy"
+version = "0.46.0"
+notes = "one use of unsafe to call windows specific api to get console handle."
+
 [[audits.bytecode-alliance.audits.openssl-probe]]
 who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 version = "0.1.5"
 notes = "IO is only checking for the existence of paths in the filesystem"
 
+[[audits.bytecode-alliance.audits.overload]]
+who = "Pat Hickey <phickey@fastly.com>"
+criteria = "safe-to-deploy"
+version = "0.1.1"
+notes = "small crate, only defines macro-rules!, nicely documented as well"
+
 [[audits.bytecode-alliance.audits.percent-encoding]]
 who = "Alex Crichton <alex@alexcrichton.com>"
 criteria = "safe-to-deploy"
@@ -434,6 +439,18 @@ criteria = "safe-to-deploy"
 version = "1.0.1"
 notes = "No unsafe usage or ambient capabilities"
 
+[[audits.embark-studios.audits.thiserror]]
+who = "Johan Andersson <opensource@embark-studios.com>"
+criteria = "safe-to-deploy"
+version = "1.0.40"
+notes = "Wrapper over implementation crate, found no unsafe or ambient capabilities used"
+
+[[audits.embark-studios.audits.thiserror-impl]]
+who = "Johan Andersson <opensource@embark-studios.com>"
+criteria = "safe-to-deploy"
+version = "1.0.40"
+notes = "Found no unsafe or ambient capabilities used"
+
 [[audits.embark-studios.audits.valuable]]
 who = "Johan Andersson <opensource@embark-studios.com>"
 criteria = "safe-to-deploy"
@@ -620,6 +637,24 @@ criteria = "safe-to-deploy"
 version = "1.0.0"
 aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
 
+[[audits.google.audits.ciborium]]
+who = "Daniel Verkamp <dverkamp@chromium.org>"
+criteria = "safe-to-run"
+version = "0.2.2"
+aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
+
+[[audits.google.audits.ciborium-io]]
+who = "Daniel Verkamp <dverkamp@chromium.org>"
+criteria = "safe-to-run"
+version = "0.2.2"
+aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
+
+[[audits.google.audits.ciborium-ll]]
+who = "Daniel Verkamp <dverkamp@chromium.org>"
+criteria = "safe-to-run"
+version = "0.2.2"
+aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
+
 [[audits.google.audits.color_quant]]
 who = "George Burgess IV <gbiv@google.com>"
 criteria = "safe-to-deploy"
@@ -770,6 +805,12 @@ delta = "1.0.34 -> 1.0.35"
 notes = "There are no significant code changes in this delta (just one string constant change). Note that prior audits may have been partial."
 aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT"
 
+[[audits.google.audits.half]]
+who = "Daniel Verkamp <dverkamp@chromium.org>"
+criteria = "safe-to-run"
+version = "2.4.1"
+aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
+
 [[audits.google.audits.heck]]
 who = "Lukasz Anforowicz <lukasza@chromium.org>"
 criteria = "safe-to-deploy"
@@ -1084,6 +1125,15 @@ The delta just 1) inlines/expands `impl ToTokens` that used to be handled via
 """
 aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT"
 
+[[audits.google.audits.rand]]
+who = "Lukasz Anforowicz <lukasza@chromium.org>"
+criteria = "safe-to-deploy"
+version = "0.8.5"
+notes = """
+For more detailed unsafe review notes please see https://crrev.com/c/6362797
+"""
+aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT"
+
 [[audits.google.audits.regex-syntax]]
 who = "Manish Goregaokar <manishearth@google.com>"
 criteria = "safe-to-deploy"
@@ -1459,6 +1509,13 @@ delta = "1.0.13 -> 1.0.14"
 notes = "Minimal delta in `.rs` files: new test assertions + doc changes."
 aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT"
 
+[[audits.google.audits.windows-core]]
+who = "Manish Goregaokar <manishearth@google.com>"
+criteria = "safe-to-deploy"
+version = "0.52.0"
+notes = "Implements Windows system APIs"
+aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT"
+
 [[audits.google.audits.yoke]]
 who = "Manish Goregaokar <manishearth@google.com>"
 criteria = "safe-to-deploy"
@@ -1696,6 +1753,16 @@ who = "David Cook <dcook@divviup.org>"
 criteria = "safe-to-deploy"
 delta = "2.5.0 -> 2.6.1"
 
+[[audits.isrg.audits.thiserror]]
+who = "Brandon Pitman <bran@bran.land>"
+criteria = "safe-to-deploy"
+delta = "1.0.40 -> 1.0.43"
+
+[[audits.isrg.audits.thiserror-impl]]
+who = "Brandon Pitman <bran@bran.land>"
+criteria = "safe-to-deploy"
+delta = "1.0.40 -> 1.0.43"
+
 [[audits.isrg.audits.universal-hash]]
 who = "David Cook <dcook@divviup.org>"
 criteria = "safe-to-deploy"
@@ -1735,15 +1802,6 @@ end = "2025-10-23"
 notes = "I, Henri Sivonen, wrote encoding_rs for Gecko and have reviewed contributions by others. There are two caveats to the certification: 1) The crate does things that are documented to be UB but that do not appear to actually be UB due to integer types differing from the general rule; https://github.com/hsivonen/encoding_rs/issues/79 . 2) It would be prudent to re-review the code that reinterprets buffers of integers as SIMD vectors; see https://github.com/hsivonen/encoding_rs/issues/87 ."
 aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
 
-[[audits.mozilla.wildcard-audits.unicode-normalization]]
-who = "Manish Goregaokar <manishsmail@gmail.com>"
-criteria = "safe-to-deploy"
-user-id = 1139 # Manish Goregaokar (Manishearth)
-start = "2019-11-06"
-end = "2026-02-01"
-notes = "All code written or reviewed by Manish"
-aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
-
 [[audits.mozilla.wildcard-audits.unicode-segmentation]]
 who = "Manish Goregaokar <manishsmail@gmail.com>"
 criteria = "safe-to-deploy"
@@ -2405,6 +2463,18 @@ criteria = "safe-to-deploy"
 delta = "0.16.0 -> 0.16.1"
 aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
 
+[[audits.mozilla.audits.thiserror]]
+who = "Jan-Erik Rediger <jrediger@mozilla.com>"
+criteria = "safe-to-deploy"
+delta = "1.0.43 -> 1.0.69"
+aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
+
+[[audits.mozilla.audits.thiserror-impl]]
+who = "Jan-Erik Rediger <jrediger@mozilla.com>"
+criteria = "safe-to-deploy"
+delta = "1.0.43 -> 1.0.69"
+aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
+
 [[audits.mozilla.audits.time-core]]
 who = "Kershaw Chang <kershaw@mozilla.com>"
 criteria = "safe-to-deploy"


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>base_layer/p2p/Cargo.toml (1)</summary><blockquote>

`62-62`: **Update comment to reflect current version**

The cargo-machete comment is outdated as it still references alpha.2 while the code now uses alpha.4.

```diff
-ignored = ["hickory-proto"] #fix hickory-proto version to same alpha.2
+ignored = ["hickory-proto"] #fix hickory-proto version to same alpha.4
```

</blockquote></details>
<details>
<summary>base_layer/core/Cargo.toml (1)</summary><blockquote>

`132-132`: **Update comment to reflect current version**

The cargo-machete comment is outdated as it still references alpha.2 while the code now uses alpha.4.

```diff
-ignored = ["hickory-proto"] #fix hickory-proto version to same alpha.2
+ignored = ["hickory-proto"] #fix hickory-proto version to same alpha.4
```

</blockquote></details>
<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (1)</summary><blockquote>

`180-189`: **Parsing DNS TXT records for checkpoints.**

This uses `split_once(':')` and discards invalid entries silently. If you need more insights on malformed records, consider logging parse failures.

</blockquote></details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary><blockquote>

`50-71`: **`query_txt` parsing may benefit from multi-chunk handling.**

Currently, only the first length byte is stripped. DNS TXT records can contain multiple segments. If you anticipate multi-part TXT records, consider handling them accordingly.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between cef46a55bc05aeb963a77e0059debac539c08ee7 and 8107a070f6615f294a9bb6d49e52d14f540c44af.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (13)</summary>

* `base_layer/core/Cargo.toml` (1 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/20326.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/38696.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/mod.rs` (4 hunks)
* `base_layer/p2p/Cargo.toml` (1 hunks)
* `base_layer/p2p/src/auto_update/dns.rs` (3 hunks)
* `base_layer/p2p/src/dns/client.rs` (2 hunks)
* `base_layer/p2p/src/dns/error.rs` (1 hunks)
* `base_layer/p2p/src/dns/mock.rs` (0 hunks)
* `base_layer/p2p/src/dns/mod.rs` (0 hunks)
* `base_layer/p2p/src/dns/roots/mod.rs` (0 hunks)
* `base_layer/p2p/src/lib.rs` (1 hunks)
* `base_layer/p2p/src/peer_seeds.rs` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (5)</summary>

* base_layer/core/src/base_node/tari_pulse_service/38696.rsa
* base_layer/p2p/src/dns/mod.rs
* base_layer/core/src/base_node/tari_pulse_service/20326.rsa
* base_layer/p2p/src/dns/roots/mod.rs
* base_layer/p2p/src/dns/mock.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (2)</summary>

<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (3)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (2)</summary>

* `dns` (125-125)
* `from_str` (68-87)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary>

* `connect_secure` (40-43)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/mod.rs (2)</summary>

* `version` (171-173)
* `hash` (162-164)

</details>

</blockquote></details>
<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (5)</summary><blockquote>

<details>
<summary>applications/minotari_node/src/config.rs (1)</summary>

* `network` (75-77)

</details>
<details>
<summary>applications/minotari_node/src/builder.rs (2)</summary>

* `network` (148-150)
* `config` (89-91)

</details>
<details>
<summary>base_layer/core/src/base_node/service/service.rs (1)</summary>

* `new` (108-128)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (2)</summary>

* `connect` (45-48)
* `connect` (104-123)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (1)</summary>

* `connect` (47-56)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (5)</summary>

* GitHub Check: test (nextnet, nextnet)
* GitHub Check: test (testnet, esmeralda)
* GitHub Check: cargo check with stable
* GitHub Check: Cucumber tests / FFI
* GitHub Check: Cucumber tests / Base Layer

</details>

<details>
<summary>🔇 Additional comments (19)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/lib.rs (1)</summary>

`42-42`: **API visibility change is appropriate**

Making the DNS module public aligns with the PR objective of simplifying DNS handling. This change allows the module to be accessed directly from outside the p2p crate, supporting better reusability of the DNS functionality.

</details>
<details>
<summary>base_layer/p2p/Cargo.toml (1)</summary>

`42-43`: **Dependency upgrade and feature changes look good**

The changes correctly implement the PR objective:
1. Upgrading hickory-resolver and hickory-proto to version 0.25.0-alpha.4
2. Switching from dns-over-rustls to more feature-rich options (tokio-runtime, dns-over-tls, dns-over-native-tls)
3. Removing the hickory-client dependency

This will provide better abstraction and reduce maintenance burden from frequent breaking changes.

</details>
<details>
<summary>base_layer/core/Cargo.toml (1)</summary>

`99-99`: **Dependency update looks good**

Correctly removed hickory-client dependency and upgraded hickory-proto to version 0.25.0-alpha.4, which aligns with the PR objective of simplifying DNS TXT lookup.

</details>
<details>
<summary>base_layer/p2p/src/dns/error.rs (2)</summary>

`25-26`: **Import statement cleanup is appropriate**

The simplified import statement aligns with the removal of hickory-client dependency and reflects the more streamlined approach to error handling.

---

`29-30`: **Error handling simplification looks good**

Properly removed the ClientError variant and updated the ProtoError variant to use the fully qualified path from hickory-proto. The error message has been simplified which maintains clarity while reducing verbosity.

</details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary>

`41-41`: **Use of `DnsClient` import looks correct.**

The new import aligns well with the secure connection calls below.

---

`55-55`: **Verify security implications of removing custom trust anchors.**

This call to `DnsClient::connect_secure` no longer takes a trust anchor parameter. Please confirm that default or system trust anchors meet your security requirements.

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (2)</summary>

`36-36`: **New `DnsClient` import usage is consistent.**

The added `use crate::dns::DnsClient;` import is properly referenced below.

---

`50-50`: **Confirm removal of trust anchor from secure connection.**

Previously, the secure connection also used a custom trust anchor. Now it strictly relies on system defaults. Ensure that this aligns with your overall security posture.

</details>
<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (5)</summary>

`23-37`: **Imports updated for new DNS approach.**

All newly added imports (e.g., `tari_common::DnsNameServer`, `tari_p2p::dns::DnsClient`) and references to `MissedTickBehavior` integrate cleanly with the existing code.

---

`55-62`: **Returning static DNS checkpoint domains.**

Switching from inferred or dynamically constructed DNS names to fixed string literals simplifies maintenance. However, please confirm these domain strings are correct for each network.

---

`67-67`: **`dns_name` is now a static string reference.**

This choice is simpler than building up a `String` or similar structure at runtime. No issues found.

---

`74-74`: **Minimal overhead in cloning config, but acceptable.**

Cloning `config` only to access its network is minor. No immediate concerns.

---

`83-86`: **Direct system DNS usage in `get_dns_client`.**

Falling back to `DnsNameServer::System` is straightforward. Just confirm you don’t require DNSSEC or custom trust anchors here.

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (5)</summary>

`23-29`: **New hickory resolver imports.**

Imports from `hickory_proto` and `hickory_resolver` reflect the updated library usage. No concerns.

---

`35-37`: **Refactor to a single `DnsClient` struct.**

Consolidating multiple variants into a single struct design clarifies usage across the codebase.

---

`40-43`: **`connect_secure` no longer takes a trust anchor.**

Confirm that relying on system or default trust anchors still meets your DNSSEC requirements.

---

`77-101`: **Client connection logic consolidated.**

Both `connect_dnssec` and `connect` are straightforward. The `trust_negative_responses` is set to `false`, which may be appropriate, though confirm negative response handling is desired.

---

`127-129`: **New `lookup_txt` wrapper is clean.**

This minimal wrapper over `resolver.txt_lookup` is consistent with the new design.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T13:26:04Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (1)</summary><blockquote>

`74-74`: **Replaced manual DNS name assignment with the `get_network_dns_name` helper.**  
This cleanly retrieves the DNS endpoint.  


You can avoid cloning the entire config if only `config.network` is required:
```diff
-        let dns_name = get_network_dns_name(config.clone().network);
+        let dns_name = get_network_dns_name(config.network);
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8107a070f6615f294a9bb6d49e52d14f540c44af and da7d544702130e17ce4e346b4c368b00a7b93e11.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (14)</summary>

* `.license.ignore` (0 hunks)
* `base_layer/core/Cargo.toml` (1 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/20326.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/38696.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/mod.rs` (4 hunks)
* `base_layer/p2p/Cargo.toml` (1 hunks)
* `base_layer/p2p/src/auto_update/dns.rs` (3 hunks)
* `base_layer/p2p/src/dns/client.rs` (2 hunks)
* `base_layer/p2p/src/dns/error.rs` (1 hunks)
* `base_layer/p2p/src/dns/mock.rs` (0 hunks)
* `base_layer/p2p/src/dns/mod.rs` (0 hunks)
* `base_layer/p2p/src/dns/roots/mod.rs` (0 hunks)
* `base_layer/p2p/src/lib.rs` (1 hunks)
* `base_layer/p2p/src/peer_seeds.rs` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (6)</summary>

* base_layer/p2p/src/dns/mod.rs
* base_layer/core/src/base_node/tari_pulse_service/20326.rsa
* .license.ignore
* base_layer/core/src/base_node/tari_pulse_service/38696.rsa
* base_layer/p2p/src/dns/roots/mod.rs
* base_layer/p2p/src/dns/mock.rs

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (4)</summary>

* base_layer/core/Cargo.toml
* base_layer/p2p/src/lib.rs
* base_layer/p2p/src/dns/error.rs
* base_layer/p2p/Cargo.toml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (3)</summary>

<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (4)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (2)</summary>

* `dns` (125-125)
* `from_str` (68-87)

</details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary>

* `connect_secure` (54-57)
* `from_str` (111-125)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary>

* `connect_secure` (44-47)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/mod.rs (2)</summary>

* `version` (171-173)
* `hash` (162-164)

</details>

</blockquote></details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (1)</summary>

* `dns` (125-125)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary>

* `connect_secure` (44-47)

</details>

</blockquote></details>
<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (3)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/initialization.rs (1)</summary>

* `future` (514-536)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (2)</summary>

* `connect` (49-52)
* `connect` (108-127)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (1)</summary>

* `connect` (47-56)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: test (testnet, esmeralda)
* GitHub Check: test (mainnet, stagenet)
* GitHub Check: ci
* GitHub Check: cargo check with stable

</details>

<details>
<summary>🔇 Additional comments (18)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary>

`41-41`: **Importing `DnsClient` directly from `crate::dns` is clean and consistent.**  
No issues here.

---

`55-55`: **Removal of trust anchor parameter in `connect_secure` improves simplicity.**  
This change aligns with the updated DNS client API and reduces complexity.

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (2)</summary>

`36-36`: **Importing `DnsClient` centralizes DNS functionality.**  
This is a straightforward import addition.

---

`50-50`: **Simplifying `connect_secure` call by removing trust anchor parameter.**  
Matches the refactor in the DNS client and keeps code DRY.

</details>
<details>
<summary>base_layer/core/src/base_node/tari_pulse_service/mod.rs (5)</summary>

`23-23`: **New imports for DNS and async utilities.**  
These additions (e.g., `DnsNameServer`, `DnsClient`, plus time-related imports) are correct and consistent with the rest of the module.  



Also applies to: 28-29, 33-33

---

`55-62`: **Refactoring `get_network_dns_name` to return a static string reference.**  
Returning `&'static str` instead of creating a dynamic `Name` object simplifies the code. Ensure you don’t need any dynamic DNS naming in the future.

---

`67-67`: **Adopting a static string for `dns_name`.**  
Aligns with the revised function signature in `get_network_dns_name`.

---

`83-84`: **Switching `get_dns_client` to return `DnsClient`.**  
This matches the new DNS client approach and removes unneeded trust anchor handling.

---

`180-186`: **Streamlined TXT record retrieval using `query_txt` and `split_once`.**  
The approach is readable and concise, returning a collection of `(height, hash)` tuples. Consider additional checks if multiple colons are expected or if data could contain more than one delimiter.

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (9)</summary>

`23-33`: **Import changes align well with the PR objective**

The updated imports show the transition from `hickory-client` to `hickory-resolver` and `hickory-proto`, which aligns with the PR's goal of simplifying DNS lookup by using a higher-level abstraction. The specific imports like `TokioResolver` and `TxtLookup` indicate a more targeted approach to DNS resolution.

---

`38-41`: **Good simplification from enum to struct**

Converting `DnsClient` from an enum with multiple variants to a simple struct with a single client field is a good architectural decision. This reduces complexity and eliminates the need for enum pattern matching throughout the codebase.

---

`44-47`: **API simplification by removing trust_anchor parameter**

Removing the `trust_anchor` parameter from `connect_secure` simplifies the API and reduces maintenance burden. This change aligns with the PR objective of reducing the impact of breaking changes in the underlying libraries.

---

`54-56`: **Simplified query interface**

The implementation now directly uses `lookup_txt` which provides a cleaner and more direct approach to TXT record lookups compared to the previous implementation.

---

`80-83`: **Removed generic type parameter from Client struct**

The removal of the generic type parameter from the `Client` struct simplifies the implementation. Using the concrete `TokioResolver` directly makes the code more straightforward and easier to understand.

---

`86-106`: **Improved DNSSEC connection implementation**

The new implementation of `connect_dnssec` handling both system and custom DNS configurations is well-structured and comprehensive. The code now:
1. Uses the system configuration when `DnsNameServer::System` is specified
2. Properly configures TLS for custom DNS servers
3. Handles error cases appropriately, such as missing DNS names for DNSSEC

This is a good improvement over the previous implementation.

---

`108-127`: **Consistent implementation between connect methods**

The `connect` method follows the same pattern as `connect_dnssec`, maintaining consistency in the codebase. The only difference is using `Protocol::default()` instead of `Protocol::Tls`, which is appropriate for non-secure connections.

---

`130-135`: **Streamlined lookup implementation**

The new `lookup_txt` method directly leverages the `TokioResolver`'s built-in functionality, which simplifies the code significantly. This reduces the potential for bugs and makes future maintenance easier.

---

`1-136`: <details>
<summary>✅ Verification successful</summary>

**Verify the functionality with existing consumers**

The refactoring looks good overall. Since this is a significant API change, it would be beneficial to verify that all consumers of this API have been updated accordingly.

---

🏁 Script executed:

```shell
#!/bin/bash
# Find all places where the DnsClient is imported and used
echo "Searching for DnsClient usage in the codebase..."
rg -A 2 "use .*DnsClient" | grep -v "dns/client.rs"

echo "Searching for connect_secure calls that might still use trust_anchor..."
rg "connect_secure.*trust_anchor"

echo "Searching for places that might still use DnsClient as an enum..."
rg "DnsClient::(Secure|Normal|Mock)"

echo "Checking imports of Client struct..."
rg -A 2 "use .*Client" | grep -v "dns/client.rs"
```

Length of output: 75544

---



</details>

**Action: Confirm Updated API Usage Across Consumers**

I’ve verified that consumers of the `DnsClient` API now align with the refactored changes. Searches across the repository show that:

- Files such as `base_layer/p2p/src/peer_seeds.rs`, `base_layer/p2p/src/auto_update/dns.rs`, and `base_layer/core/src/base_node/tari_pulse_service/mod.rs` import and use `DnsClient` as expected.
- There are no remaining calls to `connect_secure` using `trust_anchor`.
- No legacy enum-like usage of `DnsClient` remains.

Based on these findings, the changes appear to be consistent with consumer expectations. However, please ensure that integration tests are run to validate runtime behavior.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T13:35:16Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary><blockquote>

`109-129`: **Consider refactoring duplicated configuration code!**

The implementation for standard DNS connection looks good. However, there's some duplication between this method and `connect_dnssec` in how the `NameServerConfig` is created.


Consider extracting the common configuration code to a private helper method to reduce duplication:

```diff
impl Client {
    pub async fn connect_dnssec(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
        let resolver = match name_server {
            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
            DnsNameServer::Custom { addr, dns_name } => {
                let dns_name = dns_name.ok_or(DnsClientError::DnsNameRequiredForDnsSec)?;
-               let mut conf = ResolverConfig::new();
-               conf.add_name_server(NameServerConfig {
-                   socket_addr: addr,
-                   protocol: Protocol::Tls,
-                   tls_dns_name: Some(dns_name),
-                   http_endpoint: None,
-                   trust_negative_responses: false,
-                   bind_addr: None,
-                   tls_config: None,
-               });
-               let opts = ResolverOpts::default();
-               TokioResolver::tokio(conf, opts)
+               Self::create_resolver(addr, Some(dns_name), Protocol::Tls)
            },
        };

        Ok(Self { resolver })
    }

    pub async fn connect(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
        let resolver = match name_server {
            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
            DnsNameServer::Custom { addr, dns_name } => {
-               let mut conf = ResolverConfig::new();
-               conf.add_name_server(NameServerConfig {
-                   socket_addr: addr,
-                   protocol: Protocol::default(),
-                   tls_dns_name: dns_name,
-                   http_endpoint: None,
-                   trust_negative_responses: false,
-                   bind_addr: None,
-                   tls_config: None,
-               });
-               let opts = ResolverOpts::default();
-               TokioResolver::tokio(conf, opts)
+               Self::create_resolver(addr, dns_name, Protocol::default())
            },
        };

        Ok(Self { resolver })
    }
    
+   fn create_resolver(
+       socket_addr: std::net::SocketAddr,
+       tls_dns_name: Option<String>,
+       protocol: Protocol
+   ) -> TokioResolver {
+       let mut conf = ResolverConfig::new();
+       conf.add_name_server(NameServerConfig {
+           socket_addr,
+           protocol,
+           tls_dns_name,
+           http_endpoint: None,
+           trust_negative_responses: false,
+           bind_addr: None,
+           tls_config: None,
+       });
+       let opts = ResolverOpts::default();
+       TokioResolver::tokio(conf, opts)
+   }
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between da7d544702130e17ce4e346b4c368b00a7b93e11 and 428c88ac8e22e1547e25671b6d931b5f64cf6296.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (14)</summary>

* `.license.ignore` (0 hunks)
* `base_layer/core/Cargo.toml` (1 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/20326.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/38696.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/mod.rs` (4 hunks)
* `base_layer/p2p/Cargo.toml` (2 hunks)
* `base_layer/p2p/src/auto_update/dns.rs` (3 hunks)
* `base_layer/p2p/src/dns/client.rs` (2 hunks)
* `base_layer/p2p/src/dns/error.rs` (1 hunks)
* `base_layer/p2p/src/dns/mock.rs` (0 hunks)
* `base_layer/p2p/src/dns/mod.rs` (0 hunks)
* `base_layer/p2p/src/dns/roots/mod.rs` (0 hunks)
* `base_layer/p2p/src/lib.rs` (1 hunks)
* `base_layer/p2p/src/peer_seeds.rs` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (6)</summary>

* base_layer/core/src/base_node/tari_pulse_service/38696.rsa
* base_layer/core/src/base_node/tari_pulse_service/20326.rsa
* .license.ignore
* base_layer/p2p/src/dns/mod.rs
* base_layer/p2p/src/dns/roots/mod.rs
* base_layer/p2p/src/dns/mock.rs

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* base_layer/p2p/src/lib.rs
* base_layer/core/Cargo.toml
* base_layer/core/src/base_node/tari_pulse_service/mod.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (1)</summary>

* `dns` (125-125)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary>

* `connect_secure` (44-47)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (5)</summary>

* GitHub Check: test (nextnet, nextnet)
* GitHub Check: test (testnet, esmeralda)
* GitHub Check: test (mainnet, stagenet)
* GitHub Check: cargo check with stable
* GitHub Check: ci

</details>

<details>
<summary>🔇 Additional comments (17)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/dns/error.rs (2)</summary>

`25-25`: **Updated resolver dependency reflects project simplification.**

The import change from the previous resolver to `hickory_resolver::ResolveError` aligns with the PR objective to simplify DNS lookup by utilizing the hickory resolver.

---

`29-30`: **Simplified error handling with updated hickory library.**

The error message and type have been updated to reflect the change from using `hickory-client` to using `hickory-proto` directly. This is part of the simplification effort mentioned in the PR objectives.

</details>
<details>
<summary>base_layer/p2p/Cargo.toml (2)</summary>

`36-38`: **Updated hickory dependencies as per PR objectives.**

The dependency updates align perfectly with the PR objective to upgrade the hickory library to version `0.25.0-alpha.4`. The addition of specific features for `hickory-resolver` (tokio-runtime, dns-over-tls, dns-over-rustls) supports the goal of simplifying DNS TXT lookup code.

---

`57-57`: **Cleaned up cargo-machete metadata.**

Removing `hickory-proto` from the ignored list in cargo-machete metadata is appropriate since the dependency is now correctly used in the codebase.

</details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary>

`41-41`: **Simplified module imports.**

Updated import to use the local DNS client implementation, which aligns with the overall code simplification objective.

---

`54-56`: **Simplified DNS client connection API.**

Removed the `default_trust_anchor()` parameter from the `connect_secure` method call, which streamlines the connection logic and aligns with the PR objective to simplify DNS TXT lookup using the hickory resolver.

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (2)</summary>

`36-36`: **Simplified module imports.**

Updated import to use the local DNS client implementation, consistent with changes in other files.

---

`50-50`: **Simplified DNS client connection API.**

Removed the `default_trust_anchor()` parameter from the `connect_secure` method call, maintaining consistency with similar changes in the peer_seeds.rs file.

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (9)</summary>

`23-33`: **Import updates look good!**

The imports have been updated to properly reflect the transition from using hickory-client to hickory-resolver. This aligns with the PR objective of simplifying DNS TXT lookup by utilizing the hickory resolver directly.

---

`38-41`: **Simplified design from enum to struct!**

The change from an enum-based `DnsClient` with multiple variants to a simple struct with a `Client` field is a good architectural simplification. This design is cleaner, more maintainable, and aligns with the PR objective to simplify DNS lookups.

---

`44-47`: **Improved API by removing unnecessary parameter!**

Removing the `trust_anchor` parameter from `connect_secure` simplifies the API while maintaining functionality. The trust anchor handling is now likely handled internally by the hickory-resolver, which is a good abstraction.

---

`49-52`: **Updated implementation is consistent with the new design!**

The `connect` method has been properly updated to match the new struct-based design, maintaining consistent API while simplifying implementation.

---

`54-56`: **Method now leverages the simplified client!**

The `query_txt` method now properly delegates to the new `lookup_txt` method. This maintains the external API while benefiting from the internal simplification.

---

`57-77`: **Processing logic preserved for compatibility!**

The logic for processing TXT records is preserved, ensuring backward compatibility while working with the new underlying resolver. Good attention to detail in maintaining the same behavior.

---

`80-83`: **Simplified Client struct by removing generic parameter!**

The removal of the generic type parameter from the `Client` struct simplifies the implementation and likely makes it more straightforward to use. This is in line with the simplification goal.

---

`86-107`: **Clear implementation of DNSSEC connection!**

The `connect_dnssec` method now directly creates a `TokioResolver` based on the provided `name_server`, which simplifies the code. The handling of both system and custom DNS configurations is implemented clearly and effectively.

I see proper error handling for the case when a DNS name is missing for custom servers with DNSSEC.

---

`132-137`: **Clean and direct implementation of TXT lookup!**

The `lookup_txt` method provides a clear and direct way to query TXT records using the hickory resolver. This simpler implementation replaces the more complex manual query construction from the previous version.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T03:12:26Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (1)</summary><blockquote>

`209-215`: **Basic test coverage is good—consider adding negative or edge-case tests.**

This straightforward test validates parsing a single well-formed record. Adding tests for invalid parts, extra parts, or empty fields can help catch parsing errors early.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9acfa77df197bdd38133acdc6c9d718aa58e352f and 223ea0b163a89e19f592c015e537eb90dfe5e6ad.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `Cargo.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (14)</summary>

* `.license.ignore` (0 hunks)
* `base_layer/core/Cargo.toml` (1 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/20326.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/38696.rsa` (0 hunks)
* `base_layer/core/src/base_node/tari_pulse_service/mod.rs` (4 hunks)
* `base_layer/p2p/Cargo.toml` (2 hunks)
* `base_layer/p2p/src/auto_update/dns.rs` (3 hunks)
* `base_layer/p2p/src/dns/client.rs` (1 hunks)
* `base_layer/p2p/src/dns/error.rs` (1 hunks)
* `base_layer/p2p/src/dns/mock.rs` (0 hunks)
* `base_layer/p2p/src/dns/mod.rs` (0 hunks)
* `base_layer/p2p/src/dns/roots/mod.rs` (0 hunks)
* `base_layer/p2p/src/lib.rs` (1 hunks)
* `base_layer/p2p/src/peer_seeds.rs` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (6)</summary>

* base_layer/core/src/base_node/tari_pulse_service/20326.rsa
* .license.ignore
* base_layer/core/src/base_node/tari_pulse_service/38696.rsa
* base_layer/p2p/src/dns/mod.rs
* base_layer/p2p/src/dns/roots/mod.rs
* base_layer/p2p/src/dns/mock.rs

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (4)</summary>

* base_layer/p2p/src/dns/error.rs
* base_layer/p2p/src/lib.rs
* base_layer/p2p/src/peer_seeds.rs
* base_layer/core/src/base_node/tari_pulse_service/mod.rs

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (2)</summary>

<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (4)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (2)</summary>

* `dns` (125-125)
* `from_str` (68-87)

</details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (2)</summary>

* `connect_secure` (54-57)
* `from_str` (111-125)

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (1)</summary>

* `connect_secure` (46-53)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/mod.rs (2)</summary>

* `version` (171-173)
* `hash` (162-164)

</details>

</blockquote></details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (4)</summary><blockquote>

<details>
<summary>common/src/configuration/name_server.rs (1)</summary>

* `DnsNameServer` (128-128)

</details>
<details>
<summary>base_layer/p2p/src/peer_seeds.rs (3)</summary>

* `connect_secure` (54-57)
* `connect` (63-66)
* `new` (90-92)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/mod.rs (1)</summary>

* `default` (80-91)

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (1)</summary>

* `connect` (47-56)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (7)</summary>

* GitHub Check: test (testnet, esmeralda)
* GitHub Check: test (nextnet, nextnet)
* GitHub Check: test (mainnet, stagenet)
* GitHub Check: ci
* GitHub Check: cargo check with stable
* GitHub Check: Cucumber tests / FFI
* GitHub Check: Cucumber tests / Base Layer

</details>

<details>
<summary>🔇 Additional comments (13)</summary><blockquote>

<details>
<summary>base_layer/core/Cargo.toml (1)</summary>

`99-99`: **Dependency version alignment looks good.**

Upgrading `hickory-proto` to `=0.25.0-alpha.4` is consistent with the rest of the PR. No immediate issues found here.

</details>
<details>
<summary>base_layer/p2p/Cargo.toml (2)</summary>

`37-38`: **Dependency updates are aligned with the resolver-based approach.**

Switching to `hickory-resolver = "=0.25.0-alpha.4"` with TLS support and upgrading `hickory-proto` to the same version appears consistent with the removal of `hickory-client`. Ensure these features have been tested to confirm secure DNS lookups work as expected.

---

`56-56`: **Removal of the cargo-machete ignore list is appropriate.**

Clearing the ignore list for `hickory-proto` now that it’s updated makes sense, allowing consistent version handling within the workspace.

</details>
<details>
<summary>base_layer/p2p/src/auto_update/dns.rs (2)</summary>

`36-36`: **New DNS client import is correct.**

Importing `DnsClient` from the local crate aligns with the simplified resolver-based architecture.

---

`50-50`: **Use of the new secure connection method.**

The call to `DnsClient::connect_secure(name_server)` omits a trust anchor, matching the updated client API. Ensure no missed validations are required in your environment.

</details>
<details>
<summary>base_layer/p2p/src/dns/client.rs (8)</summary>

`23-27`: **Introduction of `hickory_proto` imports is consistent.**

These imports match the usage of `IntoName`, `xfer::Protocol`, and related features in the new resolver-based approach.

---

`28-33`: **Resolver imports look correct.**

Bringing in `hickory_resolver` and its config modules aligns with the new single client strategy.

---

`38-38`: **Defined log target is clear.**

Using a dedicated log target (`tari::p2p::dns::client`) aids in isolating DNS debug logs.

---

`41-42`: **Unified struct-based client implementation is simpler and more maintainable.**

Replacing the enum-based approach with a single `DnsClient` struct clarifies the DNS workflow.

---

`46-52`: **Secure connect approach is streamlined.**

Removing the trust anchor parameter reduces complexity. Verify any custom TLS requirements before provisioning in production.

---

`55-61`: **Non-secure connect remains straightforward.**

This method cleanly mirrors the secure connect approach without TLS overhead.

---

`64-81`: **Centralized resolver creation.**

`create_resolver` consolidates config for normal or TLS-based DNS usage. This promotes consistency and reduces duplication.

---

`83-118`: **TXT query logic might need multi-chunk handling checks.**

The code takes the first length byte as the claims for the entire record. Some DNS servers provide multiple segments per TXT record. Verify or document acceptance criteria for multi-chunk scenarios.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T04:15:00Z
user: login: ns212
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T05:37:14Z
user: login: sdbondi
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-04T05:44:56Z
user: login: SWvheerden
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-04-04T09:32:55Z
user: login: hansieodendaal
body: utACK
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T11:13:52Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>supply-chain/config.toml (1)</summary><blockquote>

`921-928`: **Verify Removal of `hickory-client` Exemption**  
As described in the PR objectives and AI summary, the obsolete `hickory-client` exemption has been removed from the configuration. Although no block for `[[exemptions.hickory-client]]` appears in the current file, please confirm that this removal does not affect any tools or dependencies still expecting it.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b6565df2d2b604881176d110687319dab19c3110 and 6e71b0d2317e06a397b9f00368d22e29e693020b.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `supply-chain/config.toml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: test (nextnet, nextnet)
* GitHub Check: test (testnet, esmeralda)
* GitHub Check: ci
* GitHub Check: cargo check with stable

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>supply-chain/config.toml (2)</summary>

`929-932`: **Update `hickory-proto` Version**  
The exemption for `hickory-proto` has been updated to version `0.25.0-alpha.4`, which is in line with the PR objectives. This update helps keep the dependency aligned with the latest changes, simplifying maintenance and ensuring compatibility.

---

`932-935`: **Update `hickory-resolver` Version**  
Similarly, the `hickory-resolver` exemption now reflects version `0.25.0-alpha.4`. This consolidated version upgrade should reduce the impact of hickory updates on the codebase and maintain a smooth integration with the Tari pulse and P2P DNS modules.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T11:20:10Z

Review comments:
diff_hunk: @@ -204,104 +204,14 @@ impl Display for UpdateSpec {
 
 #[cfg(test)]
 mod test {
-    use hickory_client::{
-        op::Query,
-        proto::{
-            rr::{rdata, Name, RData, RecordType},
-            xfer::DnsResponse,
-        },
-        rr::Record,
-    };
-
     use super::*;
-    use crate::dns::mock;
-
-    fn create_txt_record(contents: Vec<&str>) -> DnsResponse {
-        let resp_query = Query::query(Name::from_str("test.local.").unwrap(), RecordType::A);
-
-        let origin = Name::parse("example.com.", None).unwrap();
-        let record = Record::from_rdata(
-            origin,
-            86300,
-            RData::TXT(rdata::TXT::new(contents.into_iter().map(ToString::to_string).collect())),
-        );
-        DnsResponse::from_message(mock::message(resp_query, vec![record], vec![], vec![])).unwrap()
-    }
-
-    mod update_spec {
-        use super::*;
-
-        #[test]
-        fn it_parses_update_spec_string() {
-            let update_spec = UpdateSpec::from_str("base-node:linux-x64:1.0.0:bada55").unwrap();
-            assert_eq!(update_spec.application, ApplicationType::BaseNode);
-            assert_eq!(update_spec.arch, "linux-x64");
-            assert_eq!(update_spec.version.to_string(), "1.0.0");
-            assert_eq!(update_spec.hash, [0xBA, 0xDA, 0x55]);
-        }
-    }
-
-    mod dns_software_update {
-        use std::time::Duration;
 
-        use super::*;
-
-        impl AutoUpdateConfig {
-            fn get_test_defaults() -> Self {
-                Self {
-                    override_from: None,
-                    name_server: Default::default(),
-                    update_uris: vec!["test.local".to_string()].into(),
-                    use_dnssec: true,
-                    download_base_url: "https://tari-binaries.s3.amazonaws.com/latest".to_string(),
-                    hashes_url: "https://raw.githubusercontent.com/tari-project/tari/development/meta/hashes.txt"
-                        .to_string(),
-                    hashes_sig_url:
-                        "https://raw.githubusercontent.com/tari-project/tari/development/meta/hashes.txt.sig"
-                            .to_string(),
-                    check_interval: Some(Duration::from_secs(30)),
-                }
-            }
-        }
-
-        #[tokio::test]
-        async fn it_ignores_non_conforming_txt_entries() {
-            let records = vec![
-                Ok(create_txt_record(vec![":::"])),
-                Ok(create_txt_record(vec!["base-node:::"])),
-                Ok(create_txt_record(vec!["base-node::1.0:"])),
-                Ok(create_txt_record(vec!["base-node:android-armv7:0.1.0:abcdef"])),
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.0:bada55"])),
-            ];
-            let updater = DnsSoftwareUpdate {
-                client: DnsClient::connect_mock(records).await.unwrap(),
-                config: AutoUpdateConfig::get_test_defaults(),
-            };
-            let spec = updater
-                .check_for_updates(ApplicationType::BaseNode, "linux-x86_64", &"1.0.0".parse().unwrap())
-                .await
-                .unwrap();
-            assert!(spec.is_none());
-        }
-
-        #[tokio::test]
-        async fn it_returns_best_update() {
-            let records = vec![
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.0:abcdef"])),
-                Ok(create_txt_record(vec!["base-node:linux-x86_64:1.0.1:abcdef01"])),
-            ];
-            let updater = DnsSoftwareUpdate {
-                client: DnsClient::connect_mock(records).await.unwrap(),
-                config: AutoUpdateConfig::get_test_defaults(),
-            };
-            let spec = updater
-                .check_for_updates(ApplicationType::BaseNode, "linux-x86_64", &"1.0.0".parse().unwrap())
-                .await
-                .unwrap()
-                .unwrap();
-
-            assert_eq!(spec.version.to_string(), "1.0.1");
-            assert_eq!(spec.hash, [0xab, 0xcd, 0xef, 0x01]);
-        }
+    #[test]
+    fn it_parses_update_spec_string() {
+        let update_spec = UpdateSpec::from_str("base-node:linux-x64:1.0.0:bada55").unwrap();
+        assert_eq!(update_spec.application, ApplicationType::BaseNode);
+        assert_eq!(update_spec.arch, "linux-x64");
+        assert_eq!(update_spec.version.to_string(), "1.0.0");
+        assert_eq!(update_spec.hash, [0xBA, 0xDA, 0x55]);
     }
path: base_layer/p2p/src/auto_update/dns.rs
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Consider adding more test coverage for DNS client integration.**

While the basic parsing test is maintained, it appears that several other test cases might have been removed. Consider adding tests for the new hickory-resolver integration to ensure the simplification doesn't introduce regressions.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there were previously more tests in this file
git log -p -- base_layer/p2p/src/auto_update/dns.rs | grep -A 3 -B 3 "fn it_" | grep -v "it_parses_update_spec_string" | head -n 20
```

Length of output: 0

---



</details>

**Action Required: Enhance Test Coverage for DNS Client Integration**

After reviewing the git commit history for `base_layer/p2p/src/auto_update/dns.rs`, there’s no evidence of previously existing tests besides the maintained basic parsing test (`it_parses_update_spec_string`). It appears that tests covering the new hickory-resolver integration or other DNS client functionalities are missing. Please consider adding tests that verify:

- The correct integration and resolution behavior for hickory-resolver.
- Additional DNS client edge cases to catch potential regressions.

• **File:** `base_layer/p2p/src/auto_update/dns.rs`  
• **Current Test:** `it_parses_update_spec_string`  
• **Suggestion:** Add integration tests for hickory-resolver and expanded DNS client behaviors.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T03:12:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,228 +20,103 @@
 //  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 //  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-use std::{net::SocketAddr, sync::Arc, time::Duration};
-
-use futures::{future, FutureExt};
-#[cfg(test)]
-use hickory_client::proto::error::ProtoError;
-use hickory_client::{
-    client::{AsyncClient, AsyncDnssecClient, ClientHandle},
-    op::Query,
-    proto::{
-        iocompat::AsyncIoTokioAsStd,
-        rr::dnssec::{SigSigner, TrustAnchor},
-        rustls::tls_client_connect,
-        xfer::DnsResponse,
-        DnsHandle,
-        DnsMultiplexer,
-    },
-    rr::{DNSClass, IntoName, RecordType},
+use hickory_proto::{
+    rr::IntoName,
     serialize::binary::{BinEncodable, BinEncoder},
-    tcp::TcpClientStream,
+    xfer::Protocol,
+};
+use hickory_resolver::{
+    config::{NameServerConfig, ResolverConfig, ResolverOpts},
+    name_server::TokioConnectionProvider,
+    TokioResolver,
 };
-use hickory_resolver::system_conf;
-use rustls::{ClientConfig, RootCertStore};
+use log::*;
 use tari_common::DnsNameServer;
-use tari_shutdown::Shutdown;
-use tokio::task;
 
 use super::DnsClientError;
-#[cfg(test)]
-use crate::dns::mock::{DefaultOnSend, MockClientHandle};
-use crate::dns::roots;
 
-const TIMEOUT: Duration = Duration::from_secs(5);
+const LOG_TARGET: &str = "tari::p2p::dns::client";
 
 #[derive(Clone)]
-pub enum DnsClient {
-    Secure(Client<AsyncDnssecClient>),
-    Normal(Client<AsyncClient>),
-    #[cfg(test)]
-    Mock(Client<MockClientHandle<DefaultOnSend>>),
+pub struct DnsClient {
+    resolver: TokioResolver,
 }
 
 impl DnsClient {
-    pub async fn connect_secure(name_server: DnsNameServer, trust_anchor: TrustAnchor) -> Result<Self, DnsClientError> {
-        let client = Client::connect_dnssec(name_server, trust_anchor).await?;
-        Ok(DnsClient::Secure(client))
+    pub async fn connect_secure(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::Tls),
+        };
+
+        Ok(Self { resolver })
     }
 
     pub async fn connect(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
-        let client = Client::connect(name_server).await?;
-        Ok(DnsClient::Normal(client))
-    }
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::default()),
+        };
 
-    #[cfg(test)]
-    pub async fn connect_mock(messages: Vec<Result<DnsResponse, ProtoError>>) -> Result<Self, DnsClientError> {
-        let client = Client::connect_mock(messages).await?;
-        Ok(DnsClient::Mock(client))
+        Ok(Self { resolver })
     }
 
-    pub async fn lookup(&mut self, query: Query) -> Result<DnsResponse, DnsClientError> {
-        #[cfg(test)]
-        use DnsClient::Mock;
-        use DnsClient::{Normal, Secure};
-        match self {
-            Secure(ref mut client) => client.lookup(query).await,
-            Normal(ref mut client) => client.lookup(query).await,
-            #[cfg(test)]
-            Mock(ref mut client) => client.lookup(query).await,
-        }
+    fn create_resolver(
+        socket_addr: std::net::SocketAddr,
+        tls_dns_name: Option<String>,
+        protocol: Protocol,
+    ) -> TokioResolver {
+        let mut conf = ResolverConfig::new();
+        conf.add_name_server(NameServerConfig {
+            socket_addr,
+            protocol,
+            tls_dns_name,
+            http_endpoint: None,
+            trust_negative_responses: false,
+            bind_addr: None,
+            tls_config: None,
+        });
+        let opts = ResolverOpts::default();
path: base_layer/p2p/src/dns/client.rs
user: login: ns212
body: Would be great to set `edns0=true` and `try_tcp_on_error=true` in [ResolverOpts](https://docs.rs/hickory-resolver/latest/hickory_resolver/config/struct.ResolverOpts.html) to prevent any issues resolving large TXT records
created_at: 2025-04-04T05:37:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,228 +20,103 @@
 //  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 //  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-use std::{net::SocketAddr, sync::Arc, time::Duration};
-
-use futures::{future, FutureExt};
-#[cfg(test)]
-use hickory_client::proto::error::ProtoError;
-use hickory_client::{
-    client::{AsyncClient, AsyncDnssecClient, ClientHandle},
-    op::Query,
-    proto::{
-        iocompat::AsyncIoTokioAsStd,
-        rr::dnssec::{SigSigner, TrustAnchor},
-        rustls::tls_client_connect,
-        xfer::DnsResponse,
-        DnsHandle,
-        DnsMultiplexer,
-    },
-    rr::{DNSClass, IntoName, RecordType},
+use hickory_proto::{
+    rr::IntoName,
     serialize::binary::{BinEncodable, BinEncoder},
-    tcp::TcpClientStream,
+    xfer::Protocol,
+};
+use hickory_resolver::{
+    config::{NameServerConfig, ResolverConfig, ResolverOpts},
+    name_server::TokioConnectionProvider,
+    TokioResolver,
 };
-use hickory_resolver::system_conf;
-use rustls::{ClientConfig, RootCertStore};
+use log::*;
 use tari_common::DnsNameServer;
-use tari_shutdown::Shutdown;
-use tokio::task;
 
 use super::DnsClientError;
-#[cfg(test)]
-use crate::dns::mock::{DefaultOnSend, MockClientHandle};
-use crate::dns::roots;
 
-const TIMEOUT: Duration = Duration::from_secs(5);
+const LOG_TARGET: &str = "tari::p2p::dns::client";
 
 #[derive(Clone)]
-pub enum DnsClient {
-    Secure(Client<AsyncDnssecClient>),
-    Normal(Client<AsyncClient>),
-    #[cfg(test)]
-    Mock(Client<MockClientHandle<DefaultOnSend>>),
+pub struct DnsClient {
+    resolver: TokioResolver,
 }
 
 impl DnsClient {
-    pub async fn connect_secure(name_server: DnsNameServer, trust_anchor: TrustAnchor) -> Result<Self, DnsClientError> {
-        let client = Client::connect_dnssec(name_server, trust_anchor).await?;
-        Ok(DnsClient::Secure(client))
+    pub async fn connect_secure(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::Tls),
+        };
+
+        Ok(Self { resolver })
     }
 
     pub async fn connect(name_server: DnsNameServer) -> Result<Self, DnsClientError> {
-        let client = Client::connect(name_server).await?;
-        Ok(DnsClient::Normal(client))
-    }
+        let resolver = match name_server {
+            DnsNameServer::System => TokioResolver::from_system_conf(TokioConnectionProvider::default())?,
+            DnsNameServer::Custom { addr, dns_name } => Self::create_resolver(addr, dns_name, Protocol::default()),
+        };
 
-    #[cfg(test)]
-    pub async fn connect_mock(messages: Vec<Result<DnsResponse, ProtoError>>) -> Result<Self, DnsClientError> {
-        let client = Client::connect_mock(messages).await?;
-        Ok(DnsClient::Mock(client))
+        Ok(Self { resolver })
     }
 
-    pub async fn lookup(&mut self, query: Query) -> Result<DnsResponse, DnsClientError> {
-        #[cfg(test)]
-        use DnsClient::Mock;
-        use DnsClient::{Normal, Secure};
-        match self {
-            Secure(ref mut client) => client.lookup(query).await,
-            Normal(ref mut client) => client.lookup(query).await,
-            #[cfg(test)]
-            Mock(ref mut client) => client.lookup(query).await,
-        }
+    fn create_resolver(
+        socket_addr: std::net::SocketAddr,
+        tls_dns_name: Option<String>,
+        protocol: Protocol,
+    ) -> TokioResolver {
+        let mut conf = ResolverConfig::new();
+        conf.add_name_server(NameServerConfig {
+            socket_addr,
+            protocol,
+            tls_dns_name,
+            http_endpoint: None,
+            trust_negative_responses: false,
+            bind_addr: None,
+            tls_config: None,
+        });
+        let opts = ResolverOpts::default();
path: base_layer/p2p/src/dns/client.rs
user: login: sdbondi
body: Ah interesting, thanks for that - wilco
created_at: 2025-04-04T05:44:56Z
author_association: MEMBER

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-03T13:22:37Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
The pull request removes the obsolete dependency `hickory-client` from both core and P2P modules and updates the `hickory-proto` and `hickory-resolver` versions to `0.25.0-alpha.4`. Two RSA files containing base64-encoded configuration and a public key have been deleted. The DNS handling code is refactored in the Tari pulse service and P2P DNS modules by simplifying types and method signatures, eliminating the trust anchor parameter, and consolidating enum-based clients into a unified struct. Several test and mock modules have also been removed.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `base_layer/core/Cargo.toml`<br>`base_layer/p2p/Cargo.toml` | Removed `hickory-client` dependency; updated `hickory-proto` and `hickory-resolver` to `0.25.0-alpha.4` with revised features for resolver. |
| `base_layer/core/.../tari_pulse_service/20326.rsa`<br>`base_layer/core/.../tari_pulse_service/38696.rsa` | Deleted RSA files: one containing base64-encoded binary data and one with a public key. |
| `base_layer/core/.../tari_pulse_service/mod.rs` | Changed DNS name handling: updated `get_network_dns_name` return type to `&'static str` and revised DNS client usage by removing extraneous abstraction. |
| `base_layer/p2p/.../auto_update/dns.rs` | Removed `default_trust_anchor()` parameter from `connect_secure` method call and pruned several related tests. |
| `base_layer/p2p/.../dns/client.rs`<br>`.../dns/error.rs`<br>`.../dns/mod.rs`<br>`.../dns/roots/mod.rs` | Refactored DNS client: replaced enum with a struct; removed trust anchor parameters; updated error variants; deleted mock implementations and exports related to trust anchors. |
| `base_layer/p2p/src/lib.rs`<br>`base_layer/p2p/src/peer_seeds.rs` | Made the `dns` module public and removed unused constants and test functions from peer seeds. |
| `.license.ignore` | Removed paths for `20326.rsa` and `38696.rsa` from the ignore list. |
| `supply-chain/config.toml` | Updated exemption entries: removed some, added new ones, and updated versions for `hickory-proto` and `hickory-resolver`. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant App as Application
    participant DNS as DnsClient
    participant Resolver as TokioResolver

    App->>DNS: connect_secure(name_server)
    DNS->>Resolver: connect_dnssec(name_server)
    Resolver-->>DNS: Connection established
    DNS->>Resolver: lookup_txt(name)
    Resolver-->>DNS: TXT record response
    DNS-->>App: Return DNS response
```

```mermaid
sequenceDiagram
    participant Pulse as TariPulseService
    participant DnsCli as DnsClient

    Pulse->>DnsCli: get_dns_client()
    DnsCli->>DnsCli: query_txt(name)
    DnsCli-->>Pulse: Return TXT result
```

## Suggested reviewers
- SWvheerden

## Poem
> In the code fields I hop with glee,  
> Old dependencies gone, now clean and free,  
> RSA files hopped away like leaves in the breeze,  
> DNS flows streamlined with elegant ease,  
> Upgraded features make my heart tap dance—  
> A rabbit’s cheer for a refactored advance! 🐇  
> CodeRabbit leaps to celebrate the chance!

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6e71b0d2317e06a397b9f00368d22e29e693020b and cfd4eef81753d14ad29161fa93192d5d2b664d1f.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `supply-chain/imports.lock` is excluded by `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `supply-chain/config.toml` (7 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: cargo check with stable
* GitHub Check: test (mainnet, stagenet)
* GitHub Check: Cucumber tests / Base Layer
* GitHub Check: test (nextnet, nextnet)
* GitHub Check: test (testnet, esmeralda)
* GitHub Check: ci

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>supply-chain/config.toml (7)</summary>

`827-829`: **New Exemption for `generator` Added**

A new exemption for the `generator` dependency has been introduced with version `"0.8.4"` and marked as `"safe-to-deploy"`. Please confirm that this version meets our internal security and compatibility guidelines.

---

`919-921`: **Update for `hickory-proto` Version**

The exemption for `hickory-proto` has been updated to version `"0.25.0-alpha.4"`. This update is in line with the PR objectives to upgrade the dependency and standardize the versions across the project. Please verify its consistency with related modules.

---

`923-925`: **Update for `hickory-resolver` Version**

The exemption for `hickory-resolver` is now set to version `"0.25.0-alpha.4"`. This change supports the simplification of the DNS TXT lookup code by relying on the higher-level hickory resolver. Ensure that all dependent components are compatible with this updated version.

---

`1186-1189`: **Replacement of `lru-cache` with `loom`**

An exemption for `loom` has been introduced with version `"0.7.2"`, which replaces the previously removed `lru-cache` entry. Please confirm that this substitution is intentional and that `loom` fully addresses the intended functionality and security requirements.

---

`1282-1285`: **New Exemption for `moka` Added**

A new exemption for `moka` has been added with version `"0.12.10"`, declared as `"safe-to-deploy"`. Verify that this version is correct and aligns with other dependency revisions in the project.

---

`2018-2021`: **New Exemption for `tagptr` Added**

A new exemption for `tagptr` is introduced with version `"0.2.0"`, marked as `"safe-to-deploy"`. This addition supports broader dependency management updates. Please ensure that it complies with our deployment and security criteria.

---

`2414-2437`: **Windows Exemptions Update**

Multiple Windows-related exemptions have been updated/added:
- **`windows`** now has version `"0.58.0"`.
- **`windows-core`** is updated to version `"0.58.0"`.
- **`windows-implement`** is added with version `"0.58.0"`.
- **`windows-interface`** is added with version `"0.58.0"`.
- **`windows-result`** is added with version `"0.2.0"`.
- **`windows-strings`** is added with version `"0.1.0"`.

These modifications align with the updated dependency requirements and our overall strategy for consistent versioning across the Windows ecosystem. Please double-check that these versions work as expected within our Windows build framework.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=tari-project/tari&utm_content=6922):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-03T13:48:57Z
body: ## Test Results (CI)
    3 files    129 suites   47m 21s ⏱️
1 350 tests 1 350 ✅ 0 💤 0 ❌
4 048 runs  4 048 ✅ 0 💤 0 ❌

Results for commit cfd4eef8.

[test-results]:data:application/gzip;base64,H4sIAB7V72cC/2XMSwrDIBSF4a0Exx3k+qp2M8V6FaRJLD5GpXuvlYQkdPh/B86b+DC5TG4Duwwk11B6ANUtsSZTQlwaUMWhSVtL35kYt7znau2fPcOr2Q7ehOkELqWYVkl1+b3ykau1ttMT7Z+9D5e9j482znMoLYj1yJ3zCq6CIXCDVIMEbzQDTVEgfUjJETz5fAHxEbCBDAEAAA==

:recycle: This comment has been updated with latest results.
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-03T14:31:43Z
body: ## Test Results (Integration tests)
36 tests   36 ✅  15m 51s ⏱️
11 suites   0 💤
 2 files     0 ❌

Results for commit cfd4eef8.

[test-results]:data:application/gzip;base64,H4sIAFzX72cC/12Myw7CIBQFf6Vh7cLLS/FnDHIhIbbF8Fg1/ruAWlt3Z+YksxDnR5vIZaCHgaTicweASliizj7MlZVoon65vUx+4ZqKMX/m7h/VHFfhtB93wsYY4sfEMq/FtnfBt/j1Om9ynbc1E6bJ5wrEOOTWujOcBEPgGqkCCU4rBoqiQHqTkiM48nwB28G6GQIBAAA=

:recycle: This comment has been updated with latest results.
author_association: NONE