Discovery
Discovery is the glue that connects a Node Identifier to something we can dial. There are a few different types of discovery services, but for all of them you put a NodeID
in, and get back either the home relay of that node, or IP addresses to dial.
There are different implementations of the discovery service in iroh, the most popular of which are DNS & Local Discovery. DNS uses the same domain name system that connects "example.com" to an IP address to map node ids to relay servers, and local discovery uses your local network to find nodes to talk to on local WiFi, even if that WiFi network doesn’t have a wider internet connection.
DNS Discovery
First, let's add the n0 DNS discovery service as a default:
use iroh::{Endpoint, RelayMode};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let builder = Endpoint::builder()
.relay_mode(RelayMode::Default)
.discovery_n0();
let endpoint = builder.bind().await?;
println!("node id: {:?}", endpoint.node_id());
Ok(())
}
Now when this endpoint boots up, it will list itself on the n0 DNS service. From here we can pass along the node identifier, and other nodes can use the n0 DNS service to find the home relay of this node.
Local Discovery
Local discovery has the extra trick of being able to actually find new nodes on the local network. Before we can do that, we need to add the discovery-local-network
feature to our Cargo.toml
file:
cargo add iroh --features discovery-local-network
This will change our Cargo.toml
file [dependencies]
section to look like this:
[dependencies]
anyhow = "1.0.95"
iroh = { version = "0.31.0", features = ["discovery-local-network"] }
rand = "0.8.5"
tokio = "1.43.0"
And with that we can set up local discovery. It does add some complexity to the endpoint setup:
use iroh::discovery::local_swarm_discovery::LocalSwarmDiscovery;
use iroh::{Endpoint, RelayMode, SecretKey};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let key = SecretKey::generate(rand::rngs::OsRng);
let id = key.public();
let builder = Endpoint::builder()
.secret_key(key)
.relay_mode(RelayMode::Default)
.discovery_n0()
.discovery(Box::new(LocalSwarmDiscovery::new(id)?));
let endpoint = builder.bind().await?;
println!("node id: {:?}", endpoint.node_id());
Ok(())
}
Here we’ve added discovery to the endpoint constructor, passing in our two discovery services, and that’s it, iroh will now use these two services to get something it can dial for a given node ID.
For an example of this in action, check out the local discovery example.