# How to Use PkarrResolver with Iroh: Publishing and Resolving DHT Records

> Learn how to use PkarrResolver with Iroh to publish and resolve mutable DHT records. This guide covers DNS-style lookups using cryptographically signed packets with the iroh-dns crate.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-07-15

---

**The PkarrResolver in Iroh enables DNS-style lookups for mutable DHT entries using cryptographically signed packets, implemented through the `iroh-dns` crate by creating `SignedPacket` instances, publishing them via relays, and resolving TXT records through the high-level resolver API.**

The [Iroh](https://github.com/n0-computer/iroh) networking stack implements the pkarr protocol to provide decentralized, mutable name resolution over a distributed hash table. Using **PkarrResolver with Iroh**, you can publish DNS records that are signed by Ed25519 keys and resolve them using standard DNS semantics, with all verification handled automatically by the library.

## Understanding PkarrResolver in Iroh

The PkarrResolver is the component that handles DNS-style lookups for mutable entries stored in the DHT using the pkarr packet format. A pkarr packet consists of a 32-byte public key, a 64-byte Ed25519 signature, an 8-byte monotonic timestamp, and a compressed DNS message containing the actual records.

According to the Iroh source code, this functionality resides primarily in the `iroh-dns` crate, where the core `SignedPacket` type in [`iroh-dns/src/pkarr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/pkarr.rs) manages cryptographic signing and verification, while the resolver logic in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs) orchestrates queries through the relay network.

## Creating Signed Packets

To publish data, you first create a `SignedPacket` using the `SignedPacket::from_txt_strings` method defined in [`iroh-dns/src/pkarr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/pkarr.rs). This method takes a secret key, a DNS name, the TXT record values, and a TTL.

```rust
use iroh_dns::pkarr::SignedPacket;
use iroh_base::SecretKey;

// Generate a new secret key
let secret = SecretKey::generate();

// Create a signed packet with TXT records
let packet = SignedPacket::from_txt_strings(
    &secret,
    "_iroh",                     // DNS name relative to the key zone
    vec!["value=example"],       // TXT record content
    300,                         // TTL in seconds
)?;

```

For loading packets from storage or handling raw bytes, use the lower-level `SignedPacket::from_parts_unchecked` method:

```rust
let restored = SignedPacket::from_parts_unchecked(
    public_key_bytes,
    signature_bytes,
    Timestamp::from_micros(ts),
    &dns_bytes,
)?;

```

## Publishing Packets via Relay

Once created, the packet must be published to the DHT through an Iroh relay. The `SignedPacket::to_relay_payload` method serializes the packet (everything after the public key), which is then sent via the relay client defined in [`iroh-relay/src/client.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/client.rs).

```rust
use iroh_relay::client::RelayClient;

// Connect to a relay
let relay = RelayClient::new("wss://relay.iroh.example".parse()?)?;

// Serialize to relay payload format
let payload = packet.to_relay_payload();

// Publish to the DHT keyed by the public key
relay.publish(&secret.public(), &payload).await?;

```

## Resolving Names with PkarrResolver

To resolve published records, instantiate the `Resolver` from `iroh-dns` and use the `resolve_txt` method. This constructs a DNS query, sends it through the relay network, and returns the parsed TXT records after verifying the signature using `SignedPacket::from_relay_payload`.

```rust
// Create a resolver instance
let resolver = iroh_dns::Resolver::new(relay);

// Resolve a specific DNS name
let txts = resolver
    .resolve_txt("_iroh")
    .await?;  // Returns Vec<String>

println!("Resolved TXT records: {:?}", txts);

```

After verification, you can also extract all records using `SignedPacket::txt_records(name)` for specific names or `SignedPacket::all_txt_records()` to list every record in the packet.

## Key Source Files

The implementation of PkarrResolver spans several key files in the Iroh repository:

- **[`iroh-dns/src/pkarr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/pkarr.rs)**: Defines `SignedPacket`, including signing, verification, and record extraction methods.
- **[`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs)**: Contains the high-level resolver that builds DNS queries and parses responses.
- **[`iroh-relay/src/client.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/client.rs)**: Implements the relay client used to publish and fetch pkarr payloads.
- **[`iroh-base/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/lib.rs)**: Provides core cryptographic types including `PublicKey`, `SecretKey`, and `Signature`.

## Summary

- **PkarrResolver with Iroh** provides DNS-style resolution over a DHT using cryptographically signed packets.
- Create packets using `SignedPacket::from_txt_strings` in [`iroh-dns/src/pkarr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/pkarr.rs).
- Publish payloads via `RelayClient::publish` after serializing with `to_relay_payload`.
- Resolve records using `iroh_dns::Resolver` and `resolve_txt`, which automatically verifies Ed25519 signatures.
- The packet format includes a 32-byte public key, 64-byte signature, 8-byte timestamp, and compressed DNS message.

## Frequently Asked Questions

### How does PkarrResolver verify the authenticity of DHT records?

The resolver verifies records by reconstructing the `SignedPacket` using `SignedPacket::from_relay_payload`, which validates the 64-byte Ed25519 signature against the 32-byte public key embedded in the packet. This ensures that only the holder of the corresponding secret key could have published the data, providing cryptographic authenticity for all resolved TXT records.

### Can I use PkarrResolver without running a relay?

While the resolver architecture is designed to work with relays for reliable DHT access, the underlying `SignedPacket` logic in [`iroh-dns/src/pkarr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/pkarr.rs) is network-agnostic. You could theoretically resolve packets directly from DHT nodes if you implement the gossip protocol, but the standard `iroh_dns::Resolver` in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs) expects a `RelayClient` for query routing and response handling.

### What DNS record types does PkarrResolver support?

The current implementation focuses primarily on **TXT records** through methods like `txt_records()` and `all_txt_records()`. The pkarr packet format uses standard DNS message compression, so the underlying structure supports various record types, but the Iroh resolver API specifically exposes TXT record resolution for mutable key-value mappings in the DHT.

### How do I handle packet updates with rotating timestamps?

Pkarr packets include an 8-byte monotonic timestamp that ensures newer records overwrite older ones in the DHT. When creating packets with `SignedPacket::from_txt_strings` or `from_parts_unchecked`, the timestamp is automatically set to the current time. To update a record, simply create a new packet with the same secret key and a newer timestamp, then republish it—the DHT will retain only the latest version based on the timestamp ordering.