### Setup and Usage of iroh-gossip with iroh Source: https://docs.rs/iroh-gossip/latest/iroh_gossip This example demonstrates how to set up and use the iroh-gossip protocol in conjunction with the iroh networking library. It covers creating an iroh endpoint, initializing the gossip protocol, setting up a router, subscribing to a topic, broadcasting messages, and receiving messages. ```rust use iroh::{protocol::Router, Endpoint, EndpointId, endpoint::presets}; use iroh_gossip::{api::Event, Gossip, TopicId}; use n0_error::{Result, StdResultExt}; use n0_future::StreamExt; #[tokio::main] async fn main() -> Result<()> { // create an iroh endpoint that includes the standard discovery mechanisms // we've built at number0 let endpoint = Endpoint::bind(presets::N0).await?; // build gossip protocol let gossip = Gossip::builder().spawn(endpoint.clone()); // setup router let router = Router::builder(endpoint) .accept(iroh_gossip::ALPN, gossip.clone()) .spawn(); // gossip swarms are centered around a shared "topic id", which is a 32 byte identifier let topic_id = TopicId::from_bytes([23u8; 32]); // and you need some bootstrap peers to join the swarm let bootstrap_peers = bootstrap_peers(); // then, you can subscribe to the topic and join your initial peers let (sender, mut receiver) = gossip .subscribe(topic_id, bootstrap_peers) .await? .split(); // you might want to wait until you joined at least one other peer: receiver.joined().await?; // then, you can broadcast messages to all other peers! sender.broadcast(b"hello world this is a gossip message".to_vec().into()).await?; // and read messages from others! while let Some(event) = receiver.next().await { match event? { Event::Received(message) => { println!("received a message: {:?}", std::str::from_utf8(&message.content)); } _ => {} } } // clean shutdown makes sure that other peers are notified that you went offline router.shutdown().await.std_context("shutdown router")?; Ok(()) } fn bootstrap_peers() -> Vec { // insert your bootstrap peers here, or get them from your environment vec![] } ``` -------------------------------- ### Actor Setup Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Performs the initial setup for the actor, including watching for address updates and handling the initial address. Returns a stream of address updates. ```rust async fn setup(&mut self) -> impl Stream + Send + Unpin + use<> { let addr_update_stream = self.endpoint.watch_addr().stream(); let initial_addr = self.endpoint.addr(); self.handle_addr_update(initial_addr).await; addr_update_stream } ``` -------------------------------- ### Setting up and Using Iroh Gossip Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/index.html This example demonstrates how to set up an iroh endpoint, initialize the gossip protocol, and use it to subscribe to a topic, broadcast messages, and receive messages from peers. It requires the 'net' feature flag. ```rust use iroh::{protocol::Router, Endpoint, EndpointId, endpoint::presets}; use iroh_gossip::{api::Event, Gossip, TopicId}; use n0_error::{Result, StdResultExt}; use n0_future::StreamExt; #[tokio::main] async fn main() -> Result<()> { // create an iroh endpoint that includes the standard discovery mechanisms // we've built at number0 let endpoint = Endpoint::bind(presets::N0).await?; // build gossip protocol let gossip = Gossip::builder().spawn(endpoint.clone()); // setup router let router = Router::builder(endpoint) .accept(iroh_gossip::ALPN, gossip.clone()) .spawn(); // gossip swarms are centered around a shared "topic id", which is a 32 byte identifier let topic_id = TopicId::from_bytes([23u8; 32]); // and you need some bootstrap peers to join the swarm let bootstrap_peers = bootstrap_peers(); // then, you can subscribe to the topic and join your initial peers let (sender, mut receiver) = gossip .subscribe(topic_id, bootstrap_peers) .await?; .split(); // you might want to wait until you joined at least one other peer: receiver.joined().await?; // then, you can broadcast messages to all other peers! sender.broadcast(b"hello world this is a gossip message".to_vec().into()).await?; // and read messages from others! while let Some(event) = receiver.next().await { match event? { Event::Received(message) => { println!("received a message: {:?}", std::str::from_utf8(&message.content)); } _ => {} } } // clean shutdown makes sure that other peers are notified that you went offline router.shutdown().await.std_context("shutdown router")?; Ok(()) } fn bootstrap_peers() -> Vec { // insert your bootstrap peers here, or get them from your environment vec![] } ``` -------------------------------- ### Initializing Connection Loop Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Sets up and starts the connection loop for a peer, initializing both the send and receive loops. This function handles the lifecycle of a single network connection. ```rust async fn connection_loop( from: PublicKey, conn: Connection, origin: ConnOrigin, send_rx: mpsc::Receiver, in_event_tx: mpsc::Sender, max_message_size: usize, queue: Vec, ) -> Result<(), ConnectionLoopError> { debug!(?origin, "connection established"); let mut send_loop = SendLoop::new(conn.clone(), send_rx, max_message_size); let mut recv_loop = RecvLoop::new(from, conn, in_event_tx, max_message_size); } ``` -------------------------------- ### Get Topic State Reference Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.State.html Returns an optional reference to the protocol state for a specific topic. ```rust pub fn state(&self, topic: &TopicId) -> Option<&State> ``` -------------------------------- ### Get TypeId of GossipSender Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipSender.html Gets the TypeId of the GossipSender, useful for runtime type identification. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Create a new Simulator instance Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Initializes a new simulator with a given configuration and network settings. It sets up the network and prepares for simulation. ```rust pub fn new( simulator_config: SimulatorConfig, network_config: impl Into, ) -> Self { let network_config = network_config.into(); info!("start {simulator_config:?} {network_config:?}"); let rng = rand::rngs::ChaCha12Rng::seed_from_u64(simulator_config.rng_seed); Self { network: Network::new(network_config, rng), config: simulator_config, round_stats: Default::default(), } } ``` -------------------------------- ### Get Endpoint Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Retrieves the address of the local endpoint. ```APIDOC ## pub fn endpoint(&self) -> &PI The address of your local endpoint. ``` -------------------------------- ### State::state Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/state.rs.html Gets a reference to the protocol state for a specific topic. ```APIDOC ## State::state ### Description Retrieves a reference to the protocol state associated with a given [`TopicId`]. ### Parameters - **topic** (&TopicId): A reference to the [`TopicId`] for which to get the state. ### Returns - **Option<&topic::State>**: An `Option` containing a reference to the topic's state if it exists, otherwise `None`. ``` -------------------------------- ### Simulator::new Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Creates a new simulator instance with the specified configuration. ```APIDOC ## Simulator::new ### Description Creates a new simulator instance with the specified configuration. ### Signature ```rust pub fn new(simulator_config: SimulatorConfig, network_config: impl Into) -> Self ``` ### Parameters * `simulator_config`: Configuration for the simulator. * `network_config`: Configuration for the network, convertible into `NetworkConfig`. ``` -------------------------------- ### Get Statistics Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Retrieves statistics on the number of messages sent and received. ```APIDOC ## pub fn stats(&self) -> &Stats Get stats on how many messages were sent and received. ``` -------------------------------- ### Bootstrap the network with Set mode Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Boots the network by first establishing a set of initial nodes, then connecting the remaining nodes to random peers within that set. This provides a more distributed initial connection. ```rust self.network.insert_and_join(0, TOPIC, vec![]); for i in 1..count { self.network.insert_and_join(i, TOPIC, vec![0]); } self.network.run_trips(7); for i in count..node_count { let contact = self.network.rng.random_range(0..count); self.network.insert_and_join(i, TOPIC, vec![contact]); } self.network.run_trips(20); ``` -------------------------------- ### fold Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipReceiver.html Accumulates a computation over the items of a stream, starting with an initial value. ```APIDOC ## fn fold(self, init: T, f: F) -> FoldFuture ### Description Accumulates a computation over the stream. ### Method `fold` is a method on streams. ### Parameters - `init`: The initial value for the accumulator. - `f`: A closure that takes the current accumulator value and the next stream item, returning the updated accumulator value. ### Type Parameters - `T`: The type of the accumulator and the stream items. ``` -------------------------------- ### Bootstrap the network with Single mode Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Boots the network by connecting a single initial node and then connecting all other nodes to it. This is a simple bootstrapping strategy. ```rust self.network.insert_and_join(0, TOPIC, vec![]); for i in 1..node_count { self.network.insert_and_join(i, TOPIC, vec![0]); } self.network.run_trips(20); ``` -------------------------------- ### Get Gossip Statistics Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Retrieves statistics specifically for the gossip broadcast state. ```APIDOC ## pub fn gossip_stats(&self) -> &Stats Get statistics for the gossip broadcast state TODO: Remove/replace with metrics? ``` -------------------------------- ### Get Local PeerIdentity Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.State.html Retrieves a reference to the local node's PeerIdentity. ```rust pub fn me(&self) -> &PI ``` -------------------------------- ### Simulator::bootstrap Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Bootstraps the network according to the specified mode. ```APIDOC ## Simulator::bootstrap ### Description Bootstraps the network according to the specified mode. This method sets up the initial network connections and allows it to stabilize. See [`BootstrapMode`] for details. ### Signature ```rust pub fn bootstrap(&mut self, bootstrap_mode: BootstrapMode) -> NetworkReport ``` ### Parameters * `bootstrap_mode`: The mode to use for bootstrapping the network (e.g., `Single`, `Set`). ### Returns The [`NetworkReport`] after finishing the bootstrap process. ``` -------------------------------- ### Gossip::type_id Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/net/struct.Gossip.html Gets the `TypeId` of the Gossip instance, as part of the `Any` trait implementation. ```APIDOC ## Gossip::type_id ### Description Gets the `TypeId` of `self`. ### Signature ```rust fn type_id(&self) -> TypeId ``` ``` -------------------------------- ### Create Simulator Config from Environment Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Creates a `SimulatorConfig` by reading values from environment variables. Specifically, `PEERS` is read for the number of peers, defaulting to 100 if not set. ```rust impl SimulatorConfig { /// Creates a [`SimulatorConfig`] by reading from environment variables. /// /// [`Self::peers`] is read from `PEERS`, defaulting to `100` if unset. ``` -------------------------------- ### Get Topic Statistics Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/topic.rs.html Retrieves statistics related to message sending and receiving for the topic. ```APIDOC ## stats ### Description Get stats on how many messages were sent and received. ### Method `GET` ### Endpoint `/topic/stats` ### Returns - `Stats` (Stats) - Statistics object containing `messages_sent` and `messages_received`. ``` -------------------------------- ### Create SimulatorConfig from Environment Variables Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Loads simulator configuration from environment variables. Defaults are provided if variables are not set. ```rust pub fn from_env() -> Self { let peer = read_var("PEERS", 100); Self { rng_seed: read_var("SEED", 0), peers: peer, gossip_round_timeout: Duration::from_secs(read_var("GOSSIP_ROUND_TIMEOUT", 5)), } } ``` -------------------------------- ### Time-Bound Cache Operations Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/util.rs.html Demonstrates the usage of a `TimeBoundCache`, including inserting key-value pairs with expiration times, retrieving values, checking cache size, and expiring entries based on a given time threshold. It also shows how to update the expiration time of an existing entry. ```rust let mut cache = TimeBoundCache::default(); let t0 = Instant::now(); let t1 = t0 + Duration::from_secs(1); let t2 = t0 + Duration::from_secs(2); cache.insert(1, 10, t0); cache.insert(2, 20, t1); cache.insert(3, 30, t1); cache.insert(4, 40, t2); assert_eq!(cache.get(&2), Some(&20)); assert_eq!(cache.len(), 4); let removed = cache.expire_until(t1); assert_eq!(removed, 3); assert_eq!(cache.len(), 1); assert_eq!(cache.get(&2), None); assert_eq!(cache.get(&4), Some(&40)); let t3 = t2 + Duration::from_secs(1); cache.insert(5, 50, t2); assert_eq!(cache.expires(&5), Some(&t2)); cache.insert(5, 50, t3); assert_eq!(cache.expires(&5), Some(&t3)); cache.expire_until(t2); assert_eq!(cache.get(&4), None); assert_eq!(cache.get(&5), Some(&50)); ``` -------------------------------- ### Message Size Method Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/state.rs.html Provides a method to get the postcard encoded size of a Message. ```rust impl Message { /// Get the encoded size of this message pub fn size(&self) -> postcard::Result { postcard::experimental::serialized_size(&self) } } ``` -------------------------------- ### Network::insert_with_config Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Inserts a new peer with a specific protocol configuration. Panics if the peer already exists. ```APIDOC ## Network::insert_with_config ### Description Inserts a new peer with the specified protocol config. Panics if the peer already exists. ### Signature ```rust pub fn insert_with_config(&mut self, peer_id: PI, config: Config) ``` ### Parameters - **peer_id** (PI) - The identifier of the peer to insert. - **config** (Config) - The protocol configuration for the new peer. ``` -------------------------------- ### Get Local Endpoint Address Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Returns a reference to the address of the local endpoint for the State. ```rust pub fn endpoint(&self) -> &PI ``` -------------------------------- ### Get Message Kind Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.Message.html Retrieves the kind of the Message. This method is available for any Message instance. ```rust pub fn kind(&self) -> MessageKind ``` -------------------------------- ### Create New Network Instance Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Creates a new simulated network instance. Requires a NetworkConfig and a random number generator. ```rust pub fn new(config: NetworkConfig, rng: R) -> Self ``` -------------------------------- ### Policy Combination: AND Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Creates a new `Policy` that requires both the original policy and the provided `other` policy to return `Action::Follow`. ```APIDOC ## fn and(self, other: P) -> And ### Description Creates a new `Policy` that returns `Action::Follow` only if `self` and `other` return `Action::Follow`. ### Method Policy Combination ### Parameters #### Path Parameters - `other` (P): The other policy to combine with. ### Response #### Success Response - Returns a new `And` policy. ``` -------------------------------- ### Network::elapsed Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Returns the total time elapsed since the network simulation started. ```APIDOC ## Network::elapsed ### Description Returns the time elapsed since starting the network. ### Signature ```rust pub fn elapsed(&self) -> Duration ``` ### Returns A `Duration` representing the time elapsed. ``` -------------------------------- ### Network::insert_and_join Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Inserts a new peer and makes it join a topic using provided bootstrap nodes. Panics if the peer already exists. ```APIDOC ## Network::insert_and_join ### Description Inserts a new peer and joins a topic with a set of bootstrap nodes. Panics if the peer already exists. ### Signature ```rust pub fn insert_and_join( &mut self, peer_id: PI, topic: TopicId, bootstrap: Vec, ) ``` ### Parameters - **peer_id** (PI) - The identifier of the peer to insert. - **topic** (TopicId) - The ID of the topic to join. - **bootstrap** (Vec) - A list of bootstrap peer identifiers. ``` -------------------------------- ### Get Max Message Size Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Retrieves the maximum message size configured for this gossip actor. ```rust pub fn max_message_size(&self) -> usize { self.inner.max_message_size } ``` -------------------------------- ### Policy Combination: OR Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Creates a new `Policy` that returns `Action::Follow` if either the original policy or the provided `other` policy returns `Action::Follow`. ```APIDOC ## fn or(self, other: P) -> Or ### Description Creates a new `Policy` that returns `Action::Follow` if either `self` or `other` returns `Action::Follow`. ### Method Policy Combination ### Parameters #### Path Parameters - `other` (P): The other policy to combine with. ### Response #### Success Response - Returns a new `Or` policy. ``` -------------------------------- ### Get Local Endpoint Address Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/topic.rs.html Returns a reference to the local endpoint's peer identity. ```rust impl State { /// The address of your local endpoint. pub fn endpoint(&self) -> &PI { &self.me } } ``` -------------------------------- ### Insert Peer and Join Topic Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Inserts a new peer and immediately joins a specified topic using a list of bootstrap nodes. Panics if the peer ID already exists. ```rust pub fn insert_and_join( &mut self, peer_id: PI, topic: TopicId, bootstrap: Vec, ) ``` -------------------------------- ### Get Message Statistics Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Retrieves statistics related to the number of messages sent and received by the State. ```rust pub fn stats(&self) -> &Stats ``` -------------------------------- ### Get Maximum Message Size Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.State.html Retrieves the maximum message size configured for the gossip protocol. ```rust pub fn max_message_size(&self) -> usize ``` -------------------------------- ### Create SimulatorConfig from Environment Variables Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.SimulatorConfig.html Constructs a SimulatorConfig by reading values from environment variables like PEERS, SEED, and GOSSIP_ROUND_TIMEOUT. Defaults are provided if variables are not set. ```rust pub fn from_env() -> Self Creates a `SimulatorConfig` by reading from environment variables. `Self::peers` is read from `PEERS`, defaulting to `100` if unset. `Self::rng_seed` is read from `SEED`, defaulting to `0` if unset. `Self::gossip_round_timeout` is read, as seconds, from `GOSSIP_ROUND_TIMEOUT`, defaulting to `5` if unset. ``` -------------------------------- ### Create 'And' Policy Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.RoundStatsAvg.html Creates a new Policy that requires both self and other policies to return Action::Follow. ```rust fn and(self, other: P) -> And where T: Policy, P: Policy, ``` -------------------------------- ### Get Active Connections Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Returns a vector of tuples representing all active connections between peers in the network. ```rust pub fn conns(&self) -> Vec<(PI, PI)> ``` -------------------------------- ### CloneToUninit Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/net/struct.Gossip.html Performs copy-assignment from self to a destination pointer. This is a nightly-only experimental API. ```APIDOC ## unsafe fn clone_to_uninit(&self, dest: *mut u8) ### Description Performs copy-assignment from `self` to `dest`. ### Method `clone_to_uninit` ### Parameters - `dest` (*mut u8) - The destination pointer. ### Safety This function is unsafe as it involves raw pointer manipulation. ``` -------------------------------- ### Get Maximum Latency Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/enum.LatencyConfig.html Retrieves the maximum possible latency from a LatencyConfig. This is relevant for dynamic configurations. ```rust pub fn max(&self) -> Duration ``` -------------------------------- ### take Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipTopic.html Creates a new stream that yields at most `n` items from the underlying stream. After `n` items, the stream will yield `None`. ```APIDOC ## fn take(self, n: usize) -> Take ### Description Creates a new stream of at most `n` items of the underlying stream. After `n` items have been yielded, the stream will end. ### Constraints Requires `Self: Sized`. ### Parameters * `n`: The maximum number of items to yield. ### Returns A `Take` stream that yields at most `n` items. ``` -------------------------------- ### Get Gossip Broadcast Statistics Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/topic.rs.html Retrieves specific statistics for the gossip broadcast state within the topic. ```APIDOC ## gossip_stats ### Description Get statistics for the gossip broadcast state. ### Method `GET` ### Endpoint `/topic/gossip_stats` ### Returns - `plumtree::Stats` (plumtree::Stats) - Statistics specific to the gossip module. ``` -------------------------------- ### Network::new Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Creates a new simulated network instance with the given configuration and random number generator. ```APIDOC ## Network::new ### Description Creates a new network. ### Signature ```rust pub fn new(config: NetworkConfig, rng: R) -> Self ``` ### Parameters - **config** (NetworkConfig) - The configuration for the network. - **rng** (R) - The random number generator to use for the simulation. ``` -------------------------------- ### Get Direct Neighbors Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipReceiver.html Lists the current direct neighbors of the GossipReceiver. This method returns an iterator over EndpointIds. ```rust pub fn neighbors(&self) -> impl Iterator + '_ Lists our current direct neighbors. ``` -------------------------------- ### PolicyExt::or Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipApi.html Creates a new Policy that returns Action::Follow if either self or other policies return Action::Follow. ```APIDOC ## PolicyExt::or ### Description Creates a new `Policy` that returns `Action::Follow` if either `self` or `other` returns `Action::Follow`. ### Method (Implicitly a method call on a Policy object) ### Parameters - **other**: Policy - The other policy to combine with. ### Returns - A new Policy object representing the combined logic. ``` -------------------------------- ### Get TopicId as Bytes Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.TopicId.html Returns a reference to the 32-byte array representing the TopicId. This is useful for serialization or comparison. ```rust pub fn as_bytes(&self) -> &[u8; 32] ``` -------------------------------- ### Network::insert method Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Inserts a new peer into the network using the default protocol configuration. ```rust impl Network { /// Inserts a new peer. /// /// Panics if the peer already exists. pub fn insert(&mut self, peer_id: PI) { let config = self.config.proto.clone(); self.insert_with_config(peer_id, config); } /// Inserts a new peer with the specified protocol config. /// /// Panics if the peer already exists. pub fn insert_with_config(&mut self, peer_id: PI, config: Config) { assert!( ``` -------------------------------- ### Build and Test Network with Message Broadcasting Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto.rs.html Sets up a network of 6 nodes, connects them in sections, broadcasts messages, and verifies reception. It then connects the sections and broadcasts again, asserting wider reception. ```rust let mut network = Network::new(network_config, rng); // build a network with 6 nodes for i in 0..6 { network.insert(i); } let t = [0u8; 32].into(); // let node 0 join the topic but do not connect to any peers network.command(0, t, Command::Join(vec![])); // connect nodes 1 and 2 to node 0 (1..3).for_each(|i| network.command(i, t, Command::Join(vec![0]))); // connect nodes 4 and 5 to node 3 network.command(3, t, Command::Join(vec![])); (4..6).for_each(|i| network.command(i, t, Command::Join(vec![3]))); // run ticks and drain events network.run_trips(4); let _ = network.events(); assert!(network.check_synchronicity()); // now broadcast a first message network.command( 1, t, Command::Broadcast(b"hi1".to_vec().into(), Scope::Swarm), ); network.run_trips(4); let events = network.events(); let received = events.filter(|x| matches!(x, (_, _, Event::Received(_)))); // message should be received by two other nodes assert_eq!(received.count(), 2); assert!(network.check_synchronicity()); // now connect the two sections of the swarm network.command(2, t, Command::Join(vec![5])); network.run_trips(3); let _ = network.events(); println!("{}", network.report()); // now broadcast again network.command( 1, t, Command::Broadcast(b"hi2".to_vec().into(), Scope::Swarm), ); network.run_trips(5); let events = network.events(); let received = events.filter(|x| matches!(x, (_, _, Event::Received(_)))); // message should be received by all 5 other nodes assert_eq!(received.count(), 5); assert!(network.check_synchronicity()); println!("{}", network.report()); ``` -------------------------------- ### Get Peer Information Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/hyparview.rs.html Retrieves the PeerInfo for a given peer ID. Returns PeerInfo with optional peer data. ```rust fn peer_info(&self, id: &PI) -> PeerInfo { let data = self.peer_data.get(id).cloned(); PeerInfo { id: *id, data } } ``` -------------------------------- ### Insert Peer with Custom Configuration Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Inserts a new peer with a specific protocol configuration. Panics if the peer ID already exists. ```rust pub fn insert_with_config(&mut self, peer_id: PI, config: Config) ``` -------------------------------- ### Get Neighbors from GossipReceiver Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/api.rs.html Provides an iterator over the current direct neighbors known to the `GossipReceiver`. The neighbors are stored in a `HashSet`. ```rust pub fn neighbors(&self) -> impl Iterator + '_ { self.neighbors.iter().copied() } ``` -------------------------------- ### Get Neighbors from GossipTopic Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/api.rs.html Returns an iterator over the current direct neighbors of the gossip topic. This information is provided by the `GossipReceiver`. ```rust pub fn neighbors(&self) -> impl Iterator + '_ { self.receiver.neighbors() } ``` -------------------------------- ### State::new Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/state.rs.html Creates a new instance of the protocol state. It requires the local node's PeerIdentity, initial PeerData, configuration, and a random number generator. ```APIDOC ## State::new ### Description Creates a new instance of the protocol state. It requires the local node's [`PeerIdentity`], initial [`PeerData`] (which can be updated over time), [`Config`], and a random number generator. ### Parameters - **me** (PI): The [`PeerIdentity`] of the local node. - **me_data** (PeerData): The initial [`PeerData`] for the local node. - **config** (Config): The configuration for the gossip protocol. For optimal performance, this should be identical across all nodes. - **rng** (R): A random number generator implementing `Rng + SeedableRng`. ### Panics Panics if [`Config::max_message_size`] is below [`MIN_MAX_MESSAGE_SIZE`]. ``` -------------------------------- ### Handle Incoming Connection Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Spawns a new asynchronous task to manage an incoming network connection. It sets up channels for sending and receiving messages and initiates the connection loop. ```rust fn handle_connection(&mut self, peer_id: EndpointId, origin: ConnOrigin, conn: Connection) { let (send_tx, send_rx) = mpsc::channel(SEND_QUEUE_CAP); let conn_id = conn.stable_id(); let queue = match self.peers.entry(peer_id) { Entry::Occupied(mut entry) => entry.get_mut().accept_conn(send_tx, conn_id), Entry::Vacant(entry) => { entry.insert(PeerState::Active { active_send_tx: send_tx, active_conn_id: conn_id, other_conns: Vec::new(), }); Vec::new() } }; let max_message_size = self.state.max_message_size(); let in_event_tx = self.in_event_tx.clone(); // Spawn a task for this connection self.connection_tasks.spawn( async move { let res = connection_loop( peer_id, conn.clone(), origin, send_rx, in_event_tx, max_message_size, queue, ) .await; (peer_id, conn, res) } .instrument(error_span!("conn", peer = %peer_id.fmt_short())) ); } ``` -------------------------------- ### Get Cache Size Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/util/struct.TimeBoundCache.html Returns the current number of entries stored in the TimeBoundCache. Useful for monitoring cache usage. ```rust pub fn len(&self) -> usize ``` -------------------------------- ### try_fold Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipReceiver.html Accumulates a fallible computation over the items of a stream, starting with an initial value. The computation stops if an error occurs. ```APIDOC ## fn try_fold( &mut self, init: B, f: F, ) -> TryFoldFuture<'_, Self, F, B> ### Description Accumulates a fallible computation over the stream. ### Method `try_fold` is a method on fallible streams. ### Parameters - `init`: The initial value for the accumulator. - `f`: A closure that takes the current accumulator value and the next stream item, returning a `Result` with the updated accumulator value or an error. ### Type Parameters - `T`: The type of items in the stream. - `E`: The type of error that can occur. - `B`: The type of the accumulator. ``` -------------------------------- ### Create 'Or' Policy Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.RoundStatsAvg.html Creates a new Policy that returns Action::Follow if either self or other policies return Action::Follow. ```rust fn or(self, other: P) -> Or where T: Policy, P: Policy, ``` -------------------------------- ### Connect to RPC Server Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipApi.html Establishes a connection to a remote gossip network as an RPC client. This method requires the 'rpc' crate feature to be enabled. ```rust pub async fn connect(endpoint: Endpoint, addr: SocketAddr) -> Self ``` -------------------------------- ### Get Peers from Connection ID Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Retrieves the two peer identifiers associated with a connection. This is useful for identifying the participants of a connection. ```rust fn peers(&self) -> [PI; 2] { self.0 } ``` -------------------------------- ### Get Expiration Time of an Item Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/util/struct.TimeBoundCache.html Retrieves the expiration Instant for a specific key in the cache. Returns None if the key is not present. ```rust pub fn expires(&self, key: &K) -> Option<&Instant> ``` -------------------------------- ### Subscribe to Gossip Topic (Default Options) Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipApi.html Joins a gossip topic with default options. This method does not wait for bootstrap endpoints to become available. Use `GossipTopic::joined` or `Self::subscribe_and_join` to ensure a connection. ```rust pub async fn subscribe( &self, topic_id: TopicId, bootstrap: Vec, ) -> Result ``` -------------------------------- ### Get Elapsed Network Time Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Returns the total time elapsed since the network simulation was initialized, as a `Duration` object. ```rust pub fn elapsed(&self) -> Duration ``` -------------------------------- ### Test Peer Disconnection with Quit Command Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto.rs.html Creates a network of 4 nodes, asserts initial peer connections, then simulates a node leaving using the `Quit` command and verifies that the departed peer is no longer listed in connections. ```rust let rng = ChaCha12Rng::seed_from_u64(read_var("SEED", 0)); let mut config = Config::default(); config.membership.active_view_capacity = 2; let mut network = Network::new(config.into(), rng); let num = 4; for i in 0..num { network.insert(i); } let t: TopicId = [0u8; 32].into(); // join all nodes network.command(0, t, Command::Join(vec![])); network.command(1, t, Command::Join(vec![0])); network.command(2, t, Command::Join(vec![1])); network.command(3, t, Command::Join(vec![2])); network.run_trips(2); // assert all peers appear in the connections let all_conns: HashSet = HashSet::from_iter((0u64..4).flat_map(|p| { network .neighbors(&p, &t) .into_iter() .flat_map(|x| x.into_iter()) })); assert_eq!(all_conns, HashSet::from_iter([0, 1, 2, 3])); assert!(network.check_synchronicity()); // let node 3 leave the swarm network.command(3, t, Command::Quit); network.run_trips(4); assert!(network.peer(&3).unwrap().state(&t).is_none()); // assert all peers without peer 3 appear in the connections let all_conns: HashSet = HashSet::from_iter((0..num).flat_map(|p| { network .neighbors(&p, &t) .into_iter() .flat_map(|x| x.into_iter()) })); assert_eq!(all_conns, HashSet::from_iter([0, 1, 2])); assert!(network.check_synchronicity()); ``` -------------------------------- ### Get Gossip Broadcast Statistics Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Retrieves statistics specifically for the gossip broadcast state. This might be replaced by a metrics system in the future. ```rust pub fn gossip_stats(&self) -> &Stats ``` -------------------------------- ### take Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipTopic.html Creates a new stream that yields at most `n` items from the underlying stream. Once `n` items are yielded, the new stream will end. ```APIDOC ## fn take(self, n: usize) -> Take ### Description Creates a new stream of at most `n` items of the underlying stream. ### Source [Source Link] ``` -------------------------------- ### Creating a New Gossip Address Lookup Instance Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net/address_lookup.rs.html Initializes a new GossipAddressLookup with default retention options. This is the simplest way to create an instance. ```rust pub(crate) fn new() -> Self { Self::with_opts(Default::default()) } ``` -------------------------------- ### Get Encoded Message Size Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.Message.html Calculates the encoded size of the Message. This requires the generic type PI to implement the Serialize trait. ```rust pub fn size(&self) -> Result ``` -------------------------------- ### Publish and Subscribe to Gossip Topic Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Demonstrates setting up two endpoints, joining a gossip topic, publishing messages from one endpoint, and receiving them on the other. Asserts that the correct number of messages are received. ```rust let topic: TopicId = blake3::hash(b"foobar").into(); let addr1 = EndpointAddr::new(pi1).with_relay_url(relay_url.clone()); let addr2 = EndpointAddr::new(pi2).with_relay_url(relay_url); memory_lookup.add_endpoint_info(addr1.clone()); memory_lookup.add_endpoint_info(addr2.clone()); debug!("----- joining -----"); // join the topics and wait for the connection to succeed let [sub1, mut sub2, mut sub3] = [ go1.subscribe_and_join(topic, vec![]), go2.subscribe_and_join(topic, vec![pi1]), go3.subscribe_and_join(topic, vec![pi2]), ] .try_join() .await .unwrap(); let (sink1, _stream1) = sub1.split(); let len = 2; // publish messages on endpoint1 let pub1 = spawn(async move { for i in 0..len { let message = format!("hi{i}"); info!("go1 broadcast: {message:?}"); sink1.broadcast(message.into_bytes().into()).await.unwrap(); tokio::time::sleep(Duration::from_micros(1)).await; } }); // wait for messages on endpoint2 let sub2 = spawn(async move { let mut recv = vec![]; loop { let ev = sub2.next().await.unwrap().unwrap(); info!("go2 event: {ev:?}"); if let Event::Received(msg) = ev { recv.push(msg.content); } if recv.len() == len { return recv; } } }); // wait for messages on endpoint3 let sub3 = spawn(async move { let mut recv = vec![]; loop { let ev = sub3.next().await.unwrap().unwrap(); info!("go3 event: {ev:?}"); if let Event::Received(msg) = ev { recv.push(msg.content); } if recv.len() == len { return recv; } } }); timeout(Duration::from_secs(10), pub1) .await .unwrap() .unwrap(); let recv2 = timeout(Duration::from_secs(10), sub2) .await .unwrap() .unwrap(); let recv3 = timeout(Duration::from_secs(10), sub3) .await .unwrap() .unwrap(); // We assert the received messages, but not their order. // While commonly they will be received in-order, for go3 it may happen // that the second message arrives before the first one, because it managed to // forward-join go1 before the second message is published. let expected: HashSet = (0..len) .map(|i| Bytes::from(format!("hi{i}").into_bytes())) .collect(); assert_eq!(HashSet::from_iter(recv2), expected); assert_eq!(HashSet::from_iter(recv3), expected); cancel.cancel(); for t in tasks { timeout(Duration::from_secs(10), t) .await .unwrap() .unwrap() .unwrap(); } ``` -------------------------------- ### fold Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipTopic.html Applies an asynchronous accumulating function to the stream's items, starting with an initial value, and returns the final accumulated value. ```APIDOC ## fn fold(self, init: T, f: F) -> Fold ### Description Execute an accumulating asynchronous computation over a stream, collecting all the values into one final result. ### Method `fold` ### Parameters - `self`: The stream to fold. - `init`: The initial value for the accumulator. - `f`: An asynchronous closure that takes the current accumulator value and the next item, returning the updated accumulator value. ``` -------------------------------- ### Get Other Peer from Connection ID Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Given one peer of a connection, returns the other peer. Returns None if the provided peer is not part of the connection. ```rust fn other(&self, other: PI) -> Option { if self.0[0] == other { Some(self.0[1]) } else if self.0[1] == other { Some(self.0[0]) } else { None } } ``` -------------------------------- ### connect Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipApi.html Connect to a remote as a RPC client. Requires the `rpc` feature. ```APIDOC ## connect ### Description Connect to a remote as a RPC client. ### Method `pub fn connect(endpoint: Endpoint, addr: SocketAddr) -> Self` ### Parameters - **endpoint** (Endpoint) - Description not available - **addr** (SocketAddr) - Description not available ### Returns - `Self` (GossipApi) - Description not available ``` -------------------------------- ### Get a random peer ID Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Returns the PeerId of a randomly selected peer from the network. This is useful for targeting random nodes in simulation operations. ```rust pub fn random_peer(&mut self) -> PeerId { *self .network .peers .keys() .choose(&mut self.network.rng) .unwrap() } ``` -------------------------------- ### Initialize SendLoop Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net/util.rs.html Creates a new `SendLoop` instance. It requires a `Connection`, a receiver for `ProtoMessage`s, and the maximum message size. ```rust pub(crate) fn new( conn: Connection, send_rx: mpsc::Receiver, max_message_size: usize, ) -> Self { Self { conn, max_message_size, buffer: Default::default(), streams: Default::default(), finishing: Default::default(), send_rx, } } ``` -------------------------------- ### Get Earliest Entry Timestamp Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/util.rs.html Returns a reference to the Instant of the earliest entry in the TimerMap without removing it. Returns None if the TimerMap is empty. ```rust pub fn first(&self) -> Option<&Instant> { self.heap.peek().map(|x| &x.time) } ``` -------------------------------- ### subscribe_with_opts Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.GossipApi.html Join a gossip topic with options. Returns a `GossipTopic` instantly. To wait for at least one connection to be established, you can await `GossipTopic::joined`. Messages will be queued until a first connection is available. If the internal channel becomes full, the oldest messages will be dropped from the channel. ```APIDOC ## subscribe_with_opts ### Description Join a gossip topic with options. Returns a `GossipTopic` instantly. To wait for at least one connection to be established, you can await `GossipTopic::joined`. Messages will be queued until a first connection is available. If the internal channel becomes full, the oldest messages will be dropped from the channel. ### Method `pub async fn subscribe_with_opts( &self, topic_id: TopicId, opts: JoinOptions, ) -> Result` ### Parameters - **topic_id** (TopicId) - Description not available - **opts** (JoinOptions) - Description not available ### Returns - `Result` - Description not available ``` -------------------------------- ### Handle IHave Message Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/plumtree.rs.html Marks a message as missing when an IHave message is received and starts a timer for it. This is a placeholder for the actual logic described in the paper. ```rust /// Handle receiving a [`Message::IHave`]. /// /// > When a node receives a IHAVE message, it simply marks the corresponding message as /// > missing It then starts a timer, with a predefined timeout value, and waits for the missing ``` -------------------------------- ### Dialer Initialization Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/net.rs.html Creates a new dialer instance for a given endpoint. Initializes the pending connections and pending dials maps. ```rust impl Dialer { /// Create a new dialer for a [`Endpoint`] fn new(endpoint: Endpoint) -> Self { Self { endpoint, pending: Default::default(), pending_dials: Default::default(), } } // ... } ``` -------------------------------- ### Get the number of peers in the network Source: https://docs.rs/iroh-gossip/latest/src/iroh_gossip/proto/sim.rs.html Returns the current count of peers connected to the simulated network. Provides a quick status check of the network size. ```rust pub fn peer_count(&self) -> usize { self.network.peers.len() } ``` -------------------------------- ### Creating JoinOptions with Bootstrap Endpoints Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/api/struct.JoinOptions.html Instantiates JoinOptions with specified bootstrap endpoints, using the default subscription capacity. This is useful for initiating connections to a gossip network. ```rust pub fn with_bootstrap(endpoints: impl IntoIterator) -> Self ``` -------------------------------- ### Queue and Perform Network Command Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Queues a command to be performed by a specific peer on a given topic. This method is used to send instructions to peers within the simulation. ```rust pub fn command(&mut self, peer: PI, topic: TopicId, command: Command) ``` -------------------------------- ### Get PeerData Bytes Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/struct.PeerData.html Retrieves a reference to the internal bytes::Bytes stored within the PeerData. This allows for direct access to the underlying byte buffer. ```rust pub fn inner(&self) -> &Bytes> ``` -------------------------------- ### Get Formatted Elapsed Network Time Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Returns the elapsed time of the network simulation, formatted as a string representing seconds with limited decimal places. ```rust pub fn elapsed_fmt(&self) -> String ``` -------------------------------- ### State Initialization Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/topic/struct.State.html Initializes the local state for a topic with a default random number generator. ```APIDOC ## pub fn new(me: PI, me_data: Option, config: Config) -> Self Initialize the local state with the default random number generator. ### Panics Panics if `Config::max_message_size` is below `MIN_MAX_MESSAGE_SIZE`. ``` -------------------------------- ### State::new Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/state/struct.State.html Creates a new instance of the protocol state. It requires the local node's PeerIdentity, initial PeerData, configuration, and a random number generator. Panics if the max message size in the config is too small. ```APIDOC ## State::new ### Description Creates a new protocol state instance. `me` is the `PeerIdentity` of the local node, `peer_data` is the initial `PeerData` (which can be updated over time). For the protocol to perform as recommended in the papers, the `Config` should be identical for all nodes in the network. ### Method `new(me: PI, me_data: PeerData, config: Config, rng: R) -> Self` ### Panics Panics if `Config::max_message_size` is below `MIN_MAX_MESSAGE_SIZE`. ``` -------------------------------- ### Get Specific Peer State Source: https://docs.rs/iroh-gossip/latest/iroh_gossip/proto/sim/struct.Network.html Retrieves the `State` object for a given peer ID, if that peer exists in the network. Returns `None` if the peer is not found. ```rust pub fn peer(&self, peer: &PI) -> Option<&State> ```