#iroh #tracker #gossipsub #networking #pubsub

iroh-topic-tracker

Iroh universal (gossipsub) topic tracker

12 releases

0.1.11 Feb 7, 2025
0.1.10 Feb 6, 2025
0.1.9 Jan 26, 2025

#703 in Network programming

Download history 592/week @ 2025-01-14 218/week @ 2025-01-21 33/week @ 2025-01-28 260/week @ 2025-02-04 17/week @ 2025-02-11

549 downloads per month

MIT license

42KB
318 lines

iroh-topic-tracker

Crates.io Docs.rs

A tracker for Iroh NodeId's in GossipSub topics.

This library integrates with iroh-gossip to automate peer discovery and includes a hosted BOOTSTRAP_NODE for seamless topic tracking without you needing to host anything. Your peers can discover each other even if both are behind NATs.


Overview

The crate provides a TopicTracker to manage and discover peers participating in shared GossipSub topics. It leverages Iroh's direct connectivity and Router to handle protocol routing.

Features

  • Automatic peer discovery via iroh-gossip (enabled with iroh-gossip-auto-discovery feature).
  • Dedicated bootstrap node support for topic tracking.
  • Simple API to fetch active peers for a topic.

Getting Started

Prerequisites

Add the crate to your Cargo.toml with the required features:

[dependencies]
iroh-topic-tracker = { version = "0.1", features = ["iroh-gossip-auto-discovery"] }

Automatic Discovery

Enable iroh-gossip integration to automate peer discovery for topics:

use futures_lite::StreamExt;
use iroh::Endpoint;
use iroh_gossip::net::{Event, Gossip, GossipEvent};
use iroh_topic_tracker::{integrations::iroh_gossip::*, topic_tracker::Topic};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Configure Iroh endpoint with discovery
    let endpoint = Endpoint::builder().discovery_n0().bind().await?;

    // Configure gossip protocol with auto-discovery
    let gossip = Gossip::builder()
        .spawn_with_auto_discovery(endpoint.clone())
        .await?;

    // Join a topic and start tracking
    let topic = Topic::from_passphrase("my-iroh-gossip-topic");
    let (sink, mut stream) = gossip.subscribe_and_join(topic.into()).await?.split();

    // Read from stream ..
    while let Some(event) = stream.next().await {
        if let Ok(Event::Gossip(GossipEvent::Received(msg))) = event {

            // Do something with msg...
            let msg_text = String::from_utf8(msg.content.to_vec()).unwrap();

        }
    }

    // .. or Send to Sink
    sink.broadcast("my msg goes here".into()).await.unwrap();

    Ok(())
}

Basic Setup with Iroh

use iroh::{protocol::Router, Endpoint};
use iroh_topic_tracker::topic_tracker::{Topic, TopicTracker};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Configure Iroh endpoint with discovery
    let endpoint = Endpoint::builder().discovery_n0().bind().await?;

    // Initialize topic tracker
    let topic_tracker = TopicTracker::new(&endpoint);

    // Attach to Iroh router
    let router = Router::builder(endpoint.clone())
        .accept(TopicTracker::ALPN, topic_tracker.clone())
        .spawn()
        .await?;

    // Track peers in a topic
    let topic = Topic::from_passphrase("my-secret-topic");
    let peers = topic_tracker.get_topic_nodes(&topic).await?;

    Ok(())
}

Examples

Run a Topic Tracker Node

Start a dedicated tracker node:

cargo run --example server

Note: Update secret.rs with your SecretKey and configure BOOTSTRAP_NODES in topic_tracker.rs for secure communication.

Query Active Peers

Fetch the latest NodeIds for a topic:

cargo run --example client

Building

Optimized release build for the tracker server:

cargo build --release --example server

License

This project is licensed under either of

at your option.

Contribution

Unless explicitly stated, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.

Dependencies

~45–79MB
~1.5M SLoC