---
title: Discover peers
description: Activate signed presence beacons or local-link mDNS with a bounded peer book and automatic dialing.
---

Choose the source that matches where peers meet:

- Use mDNS for peers on the same local network.
- Use signed discovery when peers already share a pubsub mesh.
- Enable both when the application needs both sources.

Both sources feed one bounded peer book and one automatic-dial policy.

## Enable signed discovery

```bash
cargo add minip2p-rs --features discovery
```

Signed discovery publishes application-scoped presence beacons over pubsub:

```rust
let mut node = minip2p::Endpoint::builder()
    .discovery()
    .bind_quic_dual_stack()?;

node.listen_all()?;
```

`.discovery_config(...)` selects a custom topic, publication cadence, and
announcement limit. Tune the shared address book and dial policy with
`.peer_discovery_config(...)`.

Discovery can dial direct addresses announced by other peers without a relay.
A configured relay is still required for relay circuits, reservations, and
relay-assisted hole punching:

```rust
let node = minip2p::Endpoint::builder()
    .relay(relay)
    .discovery()
    .bind_quic_dual_stack()?;
```

## Enable local mDNS

```bash
cargo add minip2p-rs --features mdns
```

Then enable it on the endpoint:

```rust
let node = minip2p::Endpoint::builder()
    .mdns()
    .bind_quic_dual_stack()?;
```

mDNS needs no pubsub or relay. Its observations are unauthenticated until the
transport verifies the remote peer, and its automatic dials remain direct-only.
`KnownPeer::beacon_addrs` and `KnownPeer::mdns_addrs` show where each address
came from.

Enable both methods on the same builder when the application needs LAN and
pubsub-based discovery.

## How peers appear

Each endpoint periodically publishes a signed beacon containing its current
dialable address snapshot. Discovery:

1. verifies the beacon identity and signature;
2. normalizes and bounds the advertised addresses;
3. updates the TTL-based known-peer book;
4. starts or cancels NAT-aware dials according to discovery policy.

Address-less beacons can refresh peer presence without starting a dial.
Wildcard listen addresses are filtered because another peer cannot dial them.

## Observe the address book

```rust
for peer in node.known_peers() {
    println!(
        "peer={} connected={} addresses={:?}",
        peer.peer,
        peer.connected,
        peer.addrs,
    );
}

for event in node.take_discovery_events() {
    println!("{event:?}");
}
```

`DiscoveryEvent` reports peers being discovered, updated, or expired, plus
automatic dial failures and rejected beacons. Use
`next_discovery_event(deadline)` when a synchronous loop wants one focused
event.

## Customize policy

```rust
use minip2p::{BeaconConfig, Endpoint, PeerDiscoveryConfig};

let beacon = BeaconConfig {
    topic: "my-app/discovery/v1".into(),
    ..BeaconConfig::default()
};
let policy = PeerDiscoveryConfig {
    max_known_peers: 256,
    ..PeerDiscoveryConfig::default()
};

let node = Endpoint::builder()
    .discovery_config(beacon)?
    .peer_discovery_config(policy)?
    .bind_quic_dual_stack()?;
```

`BeaconConfig` controls the pubsub topic, cadence, and local announcement cap.
`PeerDiscoveryConfig` is shared by signed discovery and mDNS; it controls peer
and address bounds, source TTLs, automatic dialing, tie breaking, retry
backoff, and mDNS dial-rate limits. Invalid bounds are rejected before a socket
is allocated.

:::warning
Discovery beacons are always required to be signed. Unsigned discovery
beacons are rejected even when application pubsub was configured with
`allow_unsigned: true`.
:::

:::note
minip2p owns the discovery topic. Manually subscribing is redundant, and
its pubsub messages are consumed before reaching application pubsub events.
Calling `unsubscribe` for that topic returns
`PubsubError::DiscoveryTopicReserved`.
:::

For a complete mesh demonstration, use the existing
[`minip2p-chat` example](https://github.com/deepso7/minip2p/tree/main/examples/chat).
It combines discovery, gossipsub, relay circuits, and direct upgrades.
