Skip to main content

commonware_p2p/simulated/
network.rs

1//! Implementation of a simulated p2p network.
2
3use super::{
4    Error,
5    ingress::{self, Oracle},
6    metrics,
7    transmitter::{self, Completion},
8};
9use crate::{
10    Channel, Message as NetworkMessage, PeerSetUpdate, Recipients, TrackedPeers,
11    UnlimitedSender as _,
12    sizing::peer_set_size,
13    utils::{
14        PeerSetsAtIndex as PeerSetsAtIndexBase,
15        limited::{CheckedSender as LimitedCheckedSender, Connected, LimitedSender},
16    },
17};
18use commonware_actor::{Feedback, Unreliable};
19use commonware_codec::{DecodeExt, FixedSize};
20use commonware_cryptography::PublicKey;
21use commonware_macros::select_loop;
22use commonware_runtime::{
23    Clock, ContextCell, Handle, IoBuf, IoBufs, Listener as _, Metrics, Network as RNetwork, Quota,
24    Spawner, spawn_cell,
25    telemetry::metrics::{CounterFamily, MetricsExt as _},
26};
27use commonware_stream::utils::codec::{recv_frame, send_frame};
28use commonware_utils::{
29    NZUsize, Probability, TryCollect,
30    channel::{fallible::FallibleExt, mpsc, oneshot, ring},
31    ordered::Set,
32};
33use either::Either;
34use futures::{Sink, future};
35use rand::Rng;
36use rand_distr::{Distribution, Normal};
37use std::{
38    collections::{BTreeMap, BTreeSet, HashMap, VecDeque},
39    fmt::Debug,
40    net::{IpAddr, Ipv4Addr, SocketAddr},
41    num::NonZeroUsize,
42    pin::Pin,
43    sync::{
44        Arc,
45        atomic::{AtomicBool, Ordering},
46    },
47    time::{Duration, SystemTime},
48};
49use tracing::{debug, error, trace, warn};
50
51/// Primary and secondary [`Set`] at one peer set index.
52type PeerSetsAtIndex<P> = PeerSetsAtIndexBase<Set<P>, Set<P>>;
53
54/// Task type representing a message to be sent within the network.
55type Task<P> = (Channel, P, Recipients<P>, IoBuf);
56
57/// Overhead from prepending a channel identifier to an application payload.
58const MAX_PAYLOAD_OVERHEAD: u32 = Channel::SIZE as u32;
59
60/// Maximum supported application payload size.
61pub const MAX_SIZE: u32 = u32::MAX - MAX_PAYLOAD_OVERHEAD;
62
63struct RegistrationGuard {
64    active: Arc<AtomicBool>,
65}
66
67impl Drop for RegistrationGuard {
68    fn drop(&mut self) {
69        self.active.store(false, Ordering::Release);
70    }
71}
72
73/// Target for a message in a split receiver.
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75#[must_use]
76pub enum SplitTarget {
77    None,
78    Primary,
79    Secondary,
80    Both,
81}
82
83/// Origin of a message in a split sender.
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85#[must_use]
86pub enum SplitOrigin {
87    Primary,
88    Secondary,
89}
90
91/// A function that forwards messages from [SplitOrigin] to [Recipients].
92pub trait SplitForwarder<P: PublicKey>:
93    Fn(SplitOrigin, &Recipients<P>, &IoBuf) -> Option<Recipients<P>> + Send + Sync + Clone + 'static
94{
95}
96
97impl<P: PublicKey, F> SplitForwarder<P> for F where
98    F: Fn(SplitOrigin, &Recipients<P>, &IoBuf) -> Option<Recipients<P>>
99        + Send
100        + Sync
101        + Clone
102        + 'static
103{
104}
105
106/// A function that routes incoming [NetworkMessage]s to a [SplitTarget].
107pub trait SplitRouter<P: PublicKey>:
108    Fn(&NetworkMessage<P>) -> SplitTarget + Send + Sync + 'static
109{
110}
111
112impl<P: PublicKey, F> SplitRouter<P> for F where
113    F: Fn(&NetworkMessage<P>) -> SplitTarget + Send + Sync + 'static
114{
115}
116
117/// Reference counts for how many tracked peer sets list a peer as primary vs secondary.
118#[derive(Clone, Copy, Default)]
119struct PeerRefCounts {
120    primary: usize,
121    secondary: usize,
122}
123
124/// Configuration for the simulated network.
125pub struct Config {
126    /// Maximum size allowed for an application payload provided to a sender.
127    ///
128    /// The largest supported value is [`MAX_SIZE`].
129    ///
130    /// Providing a larger payload panics. Exchanged messages are larger due to framing overhead.
131    pub max_size: u32,
132
133    /// Maximum number of distinct identities at one peer-set index.
134    ///
135    /// This applies to the deduplicated union of a peer set's primary and secondary identities.
136    /// The simulator panics when it processes an oversized registration.
137    pub max_peers_per_set: NonZeroUsize,
138
139    /// True if peers should disconnect upon being blocked. While production networking would
140    /// typically disconnect, for testing purposes it may be useful to keep peers connected,
141    /// allowing byzantine actors the ability to continue sending messages.
142    pub disconnect_on_block: bool,
143
144    /// The maximum number of peer sets to track (`tracked_peer_sets`). When a new peer set is
145    /// tracked and this limit is exceeded, the oldest peer set is removed. Peers that are no
146    /// longer in any tracked peer set will have their links removed and messages to them will be
147    /// dropped.
148    pub tracked_peer_sets: NonZeroUsize,
149}
150
151/// Implementation of a simulated network.
152pub struct Network<E: RNetwork + Spawner + Rng + Clock + Metrics, P: PublicKey> {
153    context: ContextCell<E>,
154
155    // Maximum size of an application payload.
156    max_size: u32,
157
158    // Maximum size of an internal message containing a channel identifier and payload.
159    max_frame_size: u32,
160
161    // Maximum number of distinct identities in one peer set.
162    max_peers_per_set: usize,
163
164    // True if peers should disconnect upon being blocked.
165    // While production networking would typically disconnect, for testing purposes it may be useful
166    // to keep peers connected, allowing byzantine actors the ability to continue sending messages.
167    disconnect_on_block: bool,
168
169    // Next socket address to assign to a new peer
170    // Incremented for each new peer
171    next_addr: SocketAddr,
172
173    // Channel to receive messages from the oracle and peer sources.
174    ingress: mpsc::UnboundedReceiver<ingress::Message<P, E>>,
175
176    // Sender for peer sources to subscribe through the main ingress path.
177    ingress_sender: mpsc::UnboundedSender<ingress::Message<P, E>>,
178
179    // A map from a pair of public keys (from, to) to a link between the two peers
180    links: HashMap<(P, P), Link>,
181
182    // A map from a public key to a peer
183    peers: BTreeMap<P, Peer<P>>,
184
185    // Primary and secondary peer sets indexed by peer set ID.
186    peer_sets: BTreeMap<u64, PeerSetsAtIndex<P>>,
187
188    // Per-peer reference counts across tracked peer sets (entry removed when both are zero).
189    peer_ref_counts: BTreeMap<P, PeerRefCounts>,
190
191    // Maximum number of peer sets to track.
192    tracked_peer_sets: NonZeroUsize,
193
194    // A map of peers blocking each other
195    blocks: BTreeSet<(P, P)>,
196
197    // State of the transmitter
198    transmitter: transmitter::State<P>,
199
200    // Subscribers to primary peer set updates (used by `Manager::subscribe`).
201    subscribers: Vec<mpsc::UnboundedSender<PeerSetUpdate<P>>>,
202
203    // Subscribers to the connectable peer list (used by PeerSource for LimitedSender)
204    peer_subscribers: Vec<(P, ring::Sender<Vec<P>>)>,
205
206    // Subscribers to the set of peers a given peer blocks (used by `Blocker::blocked`).
207    blocked_subscribers: Vec<(P, ring::Sender<Set<P>>)>,
208
209    // Metrics for received and sent messages
210    received_messages: CounterFamily<metrics::Message>,
211    sent_messages: CounterFamily<metrics::Message>,
212}
213
214impl<E: RNetwork + Spawner + Rng + Clock + Metrics, P: PublicKey> Network<E, P> {
215    /// Create a new simulated network with a given runtime and configuration.
216    ///
217    /// Returns a tuple containing the network instance and the oracle that can
218    /// be used to modify the state of the network during context.
219    ///
220    /// # Panics
221    ///
222    /// Panics if [`Config::max_size`] exceeds [`MAX_SIZE`].
223    pub fn new(mut context: E, cfg: Config) -> (Self, Oracle<P, E>) {
224        let (oracle_mailbox, oracle_receiver) = mpsc::unbounded_channel();
225        let sent_messages = context.family("messages_sent", "messages sent");
226        let received_messages = context.family("messages_received", "messages received");
227        let max_frame_size = cfg
228            .max_size
229            .checked_add(MAX_PAYLOAD_OVERHEAD)
230            .expect("maximum frame size overflow");
231        // Start with a pseudo-random IP address to assign sockets to for new peers
232        let next_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from_bits(context.next_u32())), 0);
233
234        (
235            Self {
236                context: ContextCell::new(context),
237                max_size: cfg.max_size,
238                max_frame_size,
239                max_peers_per_set: cfg.max_peers_per_set.get(),
240                disconnect_on_block: cfg.disconnect_on_block,
241                tracked_peer_sets: cfg.tracked_peer_sets,
242                next_addr,
243                ingress: oracle_receiver,
244                ingress_sender: oracle_mailbox.clone(),
245                links: HashMap::new(),
246                peers: BTreeMap::new(),
247                peer_sets: BTreeMap::new(),
248                peer_ref_counts: BTreeMap::new(),
249                blocks: BTreeSet::new(),
250                transmitter: transmitter::State::new(),
251                subscribers: Vec::new(),
252                peer_subscribers: Vec::new(),
253                blocked_subscribers: Vec::new(),
254                received_messages,
255                sent_messages,
256            },
257            Oracle::new(oracle_mailbox),
258        )
259    }
260
261    /// Create a new simulated network with an initial primary peer set.
262    ///
263    /// This is a convenience for test setups that would otherwise call
264    /// [`crate::Manager::track`] immediately after construction.
265    pub async fn new_with_peers<I>(context: E, cfg: Config, peers: I) -> (Self, Oracle<P, E>)
266    where
267        I: IntoIterator<Item = P>,
268    {
269        Self::new_with_split_peers(context, cfg, peers, std::iter::empty()).await
270    }
271
272    /// Create a new simulated network with primary and secondary peers split into two sets.
273    ///
274    /// Peers are tracked at peer set ID `0` as [`TrackedPeers`], matching the most common test
275    /// setup.
276    pub async fn new_with_split_peers<I, J>(
277        context: E,
278        cfg: Config,
279        primary: I,
280        secondary: J,
281    ) -> (Self, Oracle<P, E>)
282    where
283        I: IntoIterator<Item = P>,
284        J: IntoIterator<Item = P>,
285    {
286        let (mut network, oracle) = Self::new(context, cfg);
287        network
288            .register_tracked_peer_set(
289                0,
290                TrackedPeers::new(
291                    Set::from_iter_dedup(primary),
292                    Set::from_iter_dedup(secondary),
293                ),
294            )
295            .await;
296        (network, oracle)
297    }
298
299    /// Apply a tracked peer set to network state.
300    async fn register_tracked_peer_set(&mut self, id: u64, peers: TrackedPeers<P>) -> bool {
301        // Check if peer set already exists
302        if self.peer_sets.contains_key(&id) {
303            warn!(id, "peer set already exists");
304            return false;
305        }
306
307        // Ensure that peer set is monotonically increasing
308        if let Some((last, _)) = self.peer_sets.last_key_value()
309            && id <= *last
310        {
311            warn!(
312                new_id = id,
313                old_id = last,
314                "attempted to register peer set with non-monotonically increasing ID"
315            );
316            return false;
317        }
318
319        // Validate and unpack the peer set.
320        self.assert_peer_set_size(&peers);
321        let primary = peers.primary;
322        let secondary = peers.secondary;
323        let tracked_peer_sets = self.tracked_peer_sets;
324
325        // Track primary peers.
326        for public_key in primary.iter() {
327            self.ensure_peer_exists(public_key).await;
328            self.peer_ref_counts
329                .entry(public_key.clone())
330                .or_default()
331                .primary += 1;
332        }
333
334        // Track secondary peers, treating overlaps as primary.
335        let secondary_filtered = Set::from_iter_dedup(
336            secondary
337                .iter()
338                .filter(|s| primary.position(s).is_none())
339                .cloned(),
340        );
341        for public_key in secondary_filtered.iter() {
342            self.ensure_peer_exists(public_key).await;
343            self.peer_ref_counts
344                .entry(public_key.clone())
345                .or_default()
346                .secondary += 1;
347        }
348        self.peer_sets.insert(
349            id,
350            PeerSetsAtIndex {
351                primary: primary.clone(),
352                secondary: secondary_filtered,
353            },
354        );
355
356        // Remove oldest tracked peer sets if we exceed the limit.
357        while self.peer_sets.len() > tracked_peer_sets.get() {
358            let (removed_index, sets) = self.peer_sets.pop_first().unwrap();
359            debug!(index = removed_index, "removed oldest tracked peer sets");
360
361            for public_key in sets.primary.iter() {
362                let counts = self
363                    .peer_ref_counts
364                    .get_mut(public_key)
365                    .expect("reference map out of sync with peer sets");
366                counts.primary = counts
367                    .primary
368                    .checked_sub(1)
369                    .expect("reference count underflow");
370                if counts.primary == 0 && counts.secondary == 0 {
371                    self.peer_ref_counts.remove(public_key);
372                    debug!(
373                        ?public_key,
374                        "removed peer no longer in any tracked peer set"
375                    );
376                }
377            }
378
379            for public_key in sets.secondary.iter() {
380                let counts = self
381                    .peer_ref_counts
382                    .get_mut(public_key)
383                    .expect("reference map out of sync with peer sets");
384                counts.secondary = counts
385                    .secondary
386                    .checked_sub(1)
387                    .expect("reference count underflow");
388                if counts.primary == 0 && counts.secondary == 0 {
389                    self.peer_ref_counts.remove(public_key);
390                    debug!(
391                        ?public_key,
392                        "removed peer no longer in any tracked peer set"
393                    );
394                }
395            }
396        }
397        true
398    }
399
400    /// Enforces the configured maximum over one peer set.
401    fn assert_peer_set_size(&self, peers: &TrackedPeers<P>) {
402        let peer_count = peer_set_size(peers.primary.iter(), peers.secondary.iter(), None);
403        assert!(
404            peer_count <= self.max_peers_per_set,
405            "peer set too large: {peer_count} > {}",
406            self.max_peers_per_set
407        );
408    }
409
410    /// Returns (and increments) the next available socket address.
411    ///
412    /// The port number is incremented for each call, and the IP address is incremented if the port
413    /// number overflows.
414    fn get_next_socket(&mut self) -> SocketAddr {
415        let result = self.next_addr;
416
417        // Increment the port number, or the IP address if the port number overflows.
418        // Allows the ip address to overflow (wrapping).
419        match self.next_addr.port().checked_add(1) {
420            Some(port) => {
421                self.next_addr.set_port(port);
422            }
423            None => {
424                let ip = match self.next_addr.ip() {
425                    IpAddr::V4(ipv4) => ipv4,
426                    _ => unreachable!(),
427                };
428                let next_ip = Ipv4Addr::to_bits(ip).wrapping_add(1);
429                self.next_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from_bits(next_ip)), 0);
430            }
431        }
432
433        result
434    }
435
436    /// Handle an ingress message.
437    ///
438    /// This method is called when a message is received from the oracle.
439    async fn handle_ingress(&mut self, message: ingress::Message<P, E>) {
440        // It is important to ensure that no failed receipt of a message will cause us to exit.
441        // This could happen if the caller drops the `Oracle` after updating the network topology.
442        // Thus, we create a helper function to send the result to the oracle and log any errors.
443        fn send_result<T: std::fmt::Debug>(
444            result: oneshot::Sender<Result<T, Error>>,
445            value: Result<T, Error>,
446        ) {
447            let success = value.is_ok();
448            if let Err(e) = result.send(value) {
449                error!(?e, "failed to send result to oracle (ok = {})", success);
450            }
451        }
452
453        match message {
454            ingress::Message::Send {
455                channel,
456                origin,
457                recipients,
458                message,
459                ..
460            } => {
461                self.handle_task((channel, origin, recipients, message));
462            }
463            ingress::Message::Track { id, peers } => {
464                if !self.register_tracked_peer_set(id, peers).await {
465                    return;
466                }
467
468                // Notify all subscribers about the new peer set.
469                let update = self
470                    .latest_update()
471                    .expect("latest update missing after successful track");
472                self.subscribers
473                    .retain(|subscriber| subscriber.send_lossy(update.clone()));
474
475                // Broadcast updated tracked membership to SubscribeConnected subscribers.
476                self.broadcast_peer_list();
477            }
478            ingress::Message::Register {
479                channel,
480                public_key,
481                quota,
482                result,
483            } => {
484                // If peer does not exist, then create it.
485                let _ = self.ensure_peer_exists(&public_key).await;
486
487                // Get clock for the rate limiter
488                let clock = self
489                    .context
490                    .child("rate_limiter")
491                    .with_attribute("channel", channel)
492                    .with_attribute("peer", &public_key);
493
494                // Create a sender that allows sending messages to the network for a certain channel
495                let (sender, guard) = Sender::new(
496                    public_key.clone(),
497                    channel,
498                    self.max_size,
499                    self.ingress_sender.clone(),
500                    self.connected_peers_for(&public_key),
501                    clock,
502                    quota,
503                );
504
505                // Create a receiver that allows receiving messages from the network for a certain channel
506                let peer = self.peers.get_mut(&public_key).unwrap();
507                let receiver = match peer.register(channel, guard).await {
508                    Ok(receiver) => Receiver { receiver },
509                    Err(err) => return send_result(result, Err(err)),
510                };
511
512                send_result(result, Ok((sender, receiver)))
513            }
514            ingress::Message::PeerSet { id, response } => {
515                let _ = response.send(
516                    self.peer_sets
517                        .get(&id)
518                        .map(|e| TrackedPeers::new(e.primary.clone(), e.secondary.clone())),
519                );
520            }
521            ingress::Message::Subscribe { response } => {
522                // Create a new subscription channel
523                let (sender, receiver) = mpsc::unbounded_channel();
524
525                // Send the latest peer set upon subscription.
526                if let Some(update) = self.latest_update() {
527                    sender.send_lossy(update);
528                }
529                self.subscribers.push(sender);
530
531                // Return the receiver to the caller
532                let _ = response.send(receiver);
533            }
534            ingress::Message::SubscribePeers { exclude, sender } => {
535                self.subscribe_connected(exclude, sender);
536            }
537            ingress::Message::LimitBandwidth {
538                public_key,
539                egress_cap,
540                ingress_cap,
541                result,
542            } => {
543                // If peer does not exist, then create it.
544                let _ = self.ensure_peer_exists(&public_key).await;
545
546                // Update bandwidth limits
547                let now = self.context.current();
548                let completions = self
549                    .transmitter
550                    .limit(now, &public_key, egress_cap, ingress_cap);
551                self.process_completions(completions);
552
553                // Notify the caller that the bandwidth update has been applied
554                let _ = result.send(());
555            }
556            ingress::Message::AddLink {
557                sender,
558                receiver,
559                sampler,
560                success_rate,
561                result,
562            } => {
563                // If sender or receiver does not exist, then create it.
564                let _ = self.ensure_peer_exists(&sender).await;
565                let (receiver_socket, _) = self.ensure_peer_exists(&receiver).await;
566
567                // Require link to not already exist
568                let key = (sender.clone(), receiver.clone());
569                if self.links.contains_key(&key) {
570                    return send_result(result, Err(Error::LinkExists));
571                }
572
573                let link = Link::new(
574                    self.context.as_mut(),
575                    sender,
576                    receiver,
577                    receiver_socket,
578                    sampler,
579                    success_rate,
580                    self.max_frame_size,
581                    self.received_messages.clone(),
582                );
583                self.links.insert(key, link);
584                send_result(result, Ok(()))
585            }
586            ingress::Message::RemoveLink {
587                sender,
588                receiver,
589                result,
590            } => {
591                match self.links.remove(&(sender, receiver)) {
592                    Some(_) => (),
593                    None => return send_result(result, Err(Error::LinkMissing)),
594                }
595                send_result(result, Ok(()))
596            }
597            ingress::Message::Block { from, to } => {
598                if self.blocks.insert((from.clone(), to)) {
599                    self.notify_blocked(&from);
600                }
601            }
602            ingress::Message::Unblock { from, to, result } => {
603                if self.blocks.remove(&(from.clone(), to)) {
604                    self.notify_blocked(&from);
605                }
606                send_result(result, Ok(()));
607            }
608            ingress::Message::Blocked { result } => {
609                send_result(result, Ok(self.blocks.iter().cloned().collect()))
610            }
611            ingress::Message::SubscribeBlocked { from, sender } => {
612                if sender.send_lossy(self.blocked_by(&from)) {
613                    self.blocked_subscribers.push((from, sender));
614                }
615            }
616        }
617    }
618
619    /// Ensure a peer exists, creating it if necessary.
620    ///
621    /// Returns the socket address of the peer and a boolean indicating if a new peer was created.
622    async fn ensure_peer_exists(&mut self, public_key: &P) -> (SocketAddr, bool) {
623        if !self.peers.contains_key(public_key) {
624            // Create peer
625            let socket = self.get_next_socket();
626            let peer = Peer::new(
627                self.context.child("peer"),
628                public_key.clone(),
629                socket,
630                self.max_frame_size,
631            )
632            .await;
633
634            // Once ready, add to peers
635            self.peers.insert(public_key.clone(), peer);
636
637            (socket, true)
638        } else {
639            (self.peers.get(public_key).unwrap().socket, false)
640        }
641    }
642
643    fn subscribe_connected(&mut self, exclude: P, mut sender: ring::Sender<Vec<P>>) {
644        let peers = self.connected_peers_for(&exclude);
645        if Pin::new(&mut sender).start_send(peers).is_ok() {
646            self.peer_subscribers.push((exclude, sender));
647        }
648    }
649
650    /// Returns the peers that `from` currently blocks.
651    fn blocked_by(&self, from: &P) -> Set<P> {
652        Set::from_iter_dedup(
653            self.blocks
654                .iter()
655                .filter(|(blocker, _)| blocker == from)
656                .map(|(_, blocked)| blocked.clone()),
657        )
658    }
659
660    /// Send the set of peers `from` blocks to its blocked-set subscribers, dropping
661    /// subscribers that have gone away.
662    fn notify_blocked(&mut self, from: &P) {
663        let blocked = self.blocked_by(from);
664        self.blocked_subscribers.retain(|(subscriber, sender)| {
665            subscriber != from || sender.send_lossy(blocked.clone())
666        });
667    }
668
669    /// Broadcast updated peer list to all connected peer subscribers.
670    ///
671    /// This runs when tracked membership changes ([`ingress::Message::Track`]), not when peers
672    /// are first discovered via register, links, or bandwidth limits.
673    ///
674    /// Subscribers whose receivers have been dropped are removed to prevent
675    /// memory leaks.
676    fn broadcast_peer_list(&mut self) {
677        if self.peer_subscribers.is_empty() {
678            return;
679        }
680
681        let peers: Vec<P> = self.peer_ref_counts.keys().cloned().collect();
682        let mut live_subscribers = Vec::with_capacity(self.peer_subscribers.len());
683        for (exclude, mut subscriber) in self.peer_subscribers.drain(..) {
684            let peer_list = if peers.contains(&exclude) {
685                peers
686                    .iter()
687                    .filter(|peer| *peer != &exclude)
688                    .cloned()
689                    .collect()
690            } else {
691                Vec::new()
692            };
693            if Pin::new(&mut subscriber).start_send(peer_list).is_ok() {
694                live_subscribers.push((exclude, subscriber));
695            }
696        }
697        self.peer_subscribers = live_subscribers;
698    }
699
700    /// Primary and secondary peers across all tracked peer sets (reference-counted union).
701    ///
702    /// Primary wins over secondary for the same public key: `secondary` includes only peers whose
703    /// only role across tracked sets is secondary (same as [`crate::Provider::subscribe`] for [`PeerSetUpdate::all`]).
704    fn aggregate_peer_membership(&self) -> TrackedPeers<P> {
705        let primary = self
706            .peer_ref_counts
707            .iter()
708            .filter(|(_, c)| c.primary > 0)
709            .map(|(k, _)| k.clone())
710            .try_collect()
711            .expect("BTreeMap keys are unique");
712        let secondary = Set::from_iter_dedup(
713            self.peer_ref_counts
714                .iter()
715                .filter(|(_, c)| c.secondary > 0 && c.primary == 0)
716                .map(|(k, _)| k.clone()),
717        );
718        TrackedPeers::new(primary, secondary)
719    }
720
721    /// Returns a [`PeerSetUpdate`] for the latest peer set (by id), if any.
722    fn latest_update(&self) -> Option<PeerSetUpdate<P>> {
723        let (index, entry) = self.peer_sets.last_key_value()?;
724        Some(PeerSetUpdate {
725            index: *index,
726            latest: TrackedPeers::new(entry.primary.clone(), entry.secondary.clone()),
727            all: self.aggregate_peer_membership(),
728        })
729    }
730
731    /// Peers used when expanding [`Recipients::All`] for a sender.
732    fn connected_peers_for(&self, sender: &P) -> Vec<P> {
733        if !self.peer_ref_counts.contains_key(sender) {
734            return Vec::new();
735        }
736        self.peer_ref_counts
737            .keys()
738            .filter(|peer| *peer != sender)
739            .cloned()
740            .collect()
741    }
742
743    /// Returns whether the peer is currently allowed to use the network.
744    fn is_connectable(&self, peer: &P) -> bool {
745        self.peer_ref_counts.contains_key(peer)
746    }
747}
748
749impl<E: RNetwork + Spawner + Rng + Clock + Metrics, P: PublicKey> Network<E, P> {
750    /// Process completions from the transmitter.
751    fn process_completions(&mut self, completions: Vec<Completion<P>>) {
752        for completion in completions {
753            // If there is no message to deliver, then skip
754            let Some(deliver_at) = completion.deliver_at else {
755                trace!(
756                    origin = ?completion.origin,
757                    recipient = ?completion.recipient,
758                    "message dropped before delivery",
759                );
760                continue;
761            };
762
763            // Send message to link
764            let key = (completion.origin.clone(), completion.recipient.clone());
765            let Some(link) = self.links.get_mut(&key) else {
766                // This can happen if the link is removed before the message is delivered
767                trace!(
768                    origin = ?completion.origin,
769                    recipient = ?completion.recipient,
770                    "missing link for completion",
771                );
772                continue;
773            };
774            if let Err(err) = link.send(completion.channel, completion.message, deliver_at) {
775                error!(?err, "failed to send");
776            }
777        }
778    }
779
780    /// Handle a task.
781    ///
782    /// This method is called when a task is received from the sender, which can come from
783    /// any peer in the network.
784    fn handle_task(&mut self, task: Task<P>) {
785        let (channel, origin, recipients, message) = task;
786
787        // If tracking peer sets, ensure recipient and sender are in a tracked peer set
788        if !self.is_connectable(&origin) {
789            warn!(
790                ?origin,
791                reason = "not primary or secondary",
792                "dropping message"
793            );
794            return;
795        }
796
797        // Collect recipients
798        let recipients = match recipients {
799            Recipients::All => self.connected_peers_for(&origin),
800            Recipients::Some(keys) => keys,
801            Recipients::One(key) => vec![key],
802        };
803
804        // Send to all recipients
805        let now = self.context.current();
806        for recipient in recipients {
807            // Skip self
808            if recipient == origin {
809                trace!(?recipient, reason = "self", "dropping message");
810                continue;
811            }
812
813            if !self.is_connectable(&recipient) {
814                trace!(
815                    ?origin,
816                    ?recipient,
817                    reason = "not primary or secondary",
818                    "dropping message"
819                );
820                continue;
821            }
822
823            // Determine if the sender or recipient has blocked the other
824            let o_r = (origin.clone(), recipient.clone());
825            let r_o = (recipient.clone(), origin.clone());
826            if self.disconnect_on_block
827                && (self.blocks.contains(&o_r) || self.blocks.contains(&r_o))
828            {
829                trace!(?origin, ?recipient, reason = "blocked", "dropping message");
830                continue;
831            }
832
833            // Determine if there is a link between the origin and recipient
834            let Some(link) = self.links.get_mut(&o_r) else {
835                trace!(?origin, ?recipient, reason = "no link", "dropping message");
836                continue;
837            };
838
839            // Note: Rate limiting is handled by the Sender before messages reach here.
840            // The Sender filters recipients via LimitedSender::check() or in Sender::send().
841
842            // Record sent message as soon as we determine there is a link with recipient (approximates
843            // having an open connection)
844            self.sent_messages
845                .get_or_create(&metrics::Message::new(&origin, &recipient, channel))
846                .inc();
847
848            // Sample latency
849            let latency = Duration::from_millis(link.sampler.sample(self.context.as_mut()) as u64);
850
851            // Determine if the message should be delivered
852            let should_deliver = link.success_rate.sample(self.context.as_mut());
853
854            // Enqueue message for delivery
855            let completions = self.transmitter.enqueue(
856                now,
857                origin.clone(),
858                recipient.clone(),
859                channel,
860                message.clone(),
861                latency,
862                should_deliver,
863            );
864            self.process_completions(completions);
865        }
866    }
867
868    fn queue_task(
869        high: &mut VecDeque<Task<P>>,
870        low: &mut VecDeque<Task<P>>,
871        task: Task<P>,
872        priority: bool,
873    ) {
874        if priority {
875            high.push_back(task);
876        } else {
877            low.push_back(task);
878        }
879    }
880
881    fn handle_tasks(&mut self, high: &mut VecDeque<Task<P>>, low: &mut VecDeque<Task<P>>) {
882        while let Some(task) = high.pop_front() {
883            self.handle_task(task);
884        }
885        while let Some(task) = low.pop_front() {
886            self.handle_task(task);
887        }
888    }
889
890    async fn handle_ordered_ingress(
891        &mut self,
892        mut message: ingress::Message<P, E>,
893        high: &mut VecDeque<Task<P>>,
894        low: &mut VecDeque<Task<P>>,
895    ) {
896        loop {
897            match message {
898                ingress::Message::Send {
899                    channel,
900                    origin,
901                    recipients,
902                    message,
903                    priority,
904                } => {
905                    Self::queue_task(high, low, (channel, origin, recipients, message), priority);
906                }
907                message => {
908                    self.handle_tasks(high, low);
909                    self.handle_ingress(message).await;
910                    return;
911                }
912            }
913
914            message = match self.ingress.try_recv() {
915                Ok(message) => message,
916                Err(_) => {
917                    self.handle_tasks(high, low);
918                    return;
919                }
920            };
921        }
922    }
923
924    /// Run the simulated network.
925    ///
926    /// It is not necessary to invoke this method before modifying the network topology, however,
927    /// no messages will be sent until this method is called.
928    pub fn start(mut self) -> Handle<()> {
929        spawn_cell!(self.context, self.run())
930    }
931
932    async fn run(mut self) {
933        let mut high = VecDeque::new();
934        let mut low = VecDeque::new();
935        select_loop! {
936            self.context,
937            on_start => {
938                let tick = match self.transmitter.next() {
939                    Some(when) => Either::Left(self.context.sleep_until(when)),
940                    None => Either::Right(future::pending()),
941                };
942            },
943            on_stopped => {},
944            _ = tick => {
945                let now = self.context.current();
946                let completions = self.transmitter.advance(now);
947                self.process_completions(completions);
948            },
949            Some(message) = self.ingress.recv() else break => {
950                self.handle_ordered_ingress(message, &mut high, &mut low)
951                    .await;
952            },
953        }
954    }
955}
956
957/// Provides known peers from the simulated network.
958///
959/// This is derived from tracked peer sets and is not a liveness signal.
960pub struct ConnectedPeerProvider<P: PublicKey, E: Clock> {
961    me: P,
962    ingress: mpsc::UnboundedSender<ingress::Message<P, E>>,
963    peers: Vec<P>,
964    _clock: std::marker::PhantomData<E>,
965}
966
967impl<P: PublicKey, E: Clock> Clone for ConnectedPeerProvider<P, E> {
968    fn clone(&self) -> Self {
969        Self {
970            me: self.me.clone(),
971            ingress: self.ingress.clone(),
972            peers: self.peers.clone(),
973            _clock: std::marker::PhantomData,
974        }
975    }
976}
977
978impl<P: PublicKey, E: Clock> ConnectedPeerProvider<P, E> {
979    const fn new(
980        me: P,
981        ingress: mpsc::UnboundedSender<ingress::Message<P, E>>,
982        peers: Vec<P>,
983    ) -> Self {
984        Self {
985            me,
986            ingress,
987            peers,
988            _clock: std::marker::PhantomData,
989        }
990    }
991}
992
993impl<P: PublicKey, E: Clock> Connected for ConnectedPeerProvider<P, E> {
994    type PublicKey = P;
995
996    fn peers(&self) -> Vec<Self::PublicKey> {
997        self.peers.clone()
998    }
999
1000    fn subscribe(&self) -> ring::Receiver<Vec<Self::PublicKey>> {
1001        let (sender, receiver) = ring::channel(NZUsize!(1));
1002        let _ = self.ingress.send_lossy(ingress::Message::SubscribePeers {
1003            exclude: self.me.clone(),
1004            sender,
1005        });
1006        receiver
1007    }
1008}
1009
1010/// Implementation of a [crate::Sender] for the simulated network without rate limiting.
1011///
1012/// This is the inner sender used by [`Sender`] which wraps it with rate limiting.
1013pub struct UnlimitedSender<P: PublicKey, E: Clock> {
1014    me: P,
1015    channel: Channel,
1016    max_size: u32,
1017    sender: mpsc::UnboundedSender<ingress::Message<P, E>>,
1018    active: Arc<AtomicBool>,
1019}
1020
1021impl<P: PublicKey, E: Clock> Clone for UnlimitedSender<P, E> {
1022    fn clone(&self) -> Self {
1023        Self {
1024            me: self.me.clone(),
1025            channel: self.channel,
1026            max_size: self.max_size,
1027            sender: self.sender.clone(),
1028            active: self.active.clone(),
1029        }
1030    }
1031}
1032
1033impl<P: PublicKey, E: Clock> crate::UnlimitedSender for UnlimitedSender<P, E> {
1034    type PublicKey = P;
1035
1036    fn send(
1037        &mut self,
1038        recipients: Recipients<P>,
1039        message: impl Into<IoBufs> + Send,
1040        priority: bool,
1041    ) -> Unreliable<Feedback> {
1042        let message = message.into().coalesce();
1043        assert!(
1044            message.len() <= self.max_size as usize,
1045            "message too large: {} > {}",
1046            message.len(),
1047            self.max_size
1048        );
1049
1050        if !self.active.load(Ordering::Acquire) || self.sender.is_closed() {
1051            return Unreliable::new(Feedback::Closed);
1052        }
1053
1054        // The simulated network handles send submissions and topology updates
1055        // through the same ingress queue so callers can mutate links immediately
1056        // after `send` without racing the actor.
1057        if self.sender.send_lossy(ingress::Message::Send {
1058            channel: self.channel,
1059            origin: self.me.clone(),
1060            recipients,
1061            message,
1062            priority,
1063        }) {
1064            Unreliable::new(Feedback::Ok)
1065        } else {
1066            Unreliable::new(Feedback::Closed)
1067        }
1068    }
1069}
1070
1071/// Implementation of a [crate::Sender] for the simulated network.
1072///
1073/// Also implements [crate::LimitedSender] to support rate-limit checking
1074/// before sending messages.
1075pub struct Sender<P: PublicKey, E: Clock> {
1076    limited_sender: LimitedSender<E, UnlimitedSender<P, E>, ConnectedPeerProvider<P, E>>,
1077}
1078
1079impl<P: PublicKey, E: Clock> Clone for Sender<P, E> {
1080    fn clone(&self) -> Self {
1081        Self {
1082            limited_sender: self.limited_sender.clone(),
1083        }
1084    }
1085}
1086
1087impl<P: PublicKey, E: Clock> Debug for Sender<P, E> {
1088    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1089        f.debug_struct("Sender").finish_non_exhaustive()
1090    }
1091}
1092
1093impl<P: PublicKey, E: Clock> Sender<P, E> {
1094    #[allow(clippy::too_many_arguments)]
1095    fn new(
1096        me: P,
1097        channel: Channel,
1098        max_size: u32,
1099        ingress: mpsc::UnboundedSender<ingress::Message<P, E>>,
1100        connected_peers: Vec<P>,
1101        clock: E,
1102        quota: Quota,
1103    ) -> (Self, RegistrationGuard) {
1104        let active = Arc::new(AtomicBool::new(true));
1105        let unlimited_sender = UnlimitedSender {
1106            me: me.clone(),
1107            channel,
1108            max_size,
1109            sender: ingress.clone(),
1110            active: active.clone(),
1111        };
1112        let peer_source = ConnectedPeerProvider::new(me, ingress, connected_peers);
1113        let limited_sender = LimitedSender::new(unlimited_sender, quota, clock, peer_source);
1114
1115        (Self { limited_sender }, RegistrationGuard { active })
1116    }
1117
1118    /// Split this [Sender] into a [SplitOrigin::Primary] and [SplitOrigin::Secondary] sender.
1119    pub fn split_with<F: SplitForwarder<P>>(
1120        self,
1121        forwarder: F,
1122    ) -> (SplitSender<P, E, F>, SplitSender<P, E, F>) {
1123        (
1124            SplitSender {
1125                replica: SplitOrigin::Primary,
1126                inner: self.clone(),
1127                forwarder: forwarder.clone(),
1128            },
1129            SplitSender {
1130                replica: SplitOrigin::Secondary,
1131                inner: self,
1132                forwarder,
1133            },
1134        )
1135    }
1136}
1137
1138impl<P: PublicKey, E: Clock> crate::LimitedSender for Sender<P, E> {
1139    type PublicKey = P;
1140    type Checked<'a>
1141        = crate::utils::limited::CheckedSender<'a, UnlimitedSender<P, E>>
1142    where
1143        Self: 'a;
1144
1145    fn check(
1146        &mut self,
1147        recipients: Recipients<Self::PublicKey>,
1148    ) -> Result<Self::Checked<'_>, SystemTime> {
1149        self.limited_sender.check(recipients)
1150    }
1151}
1152
1153/// A sender that routes recipients per message via a user-provided function.
1154pub struct SplitSender<P: PublicKey, E: Clock, F: SplitForwarder<P>> {
1155    replica: SplitOrigin,
1156    inner: Sender<P, E>,
1157    forwarder: F,
1158}
1159
1160impl<P: PublicKey, E: Clock, F: SplitForwarder<P>> Clone for SplitSender<P, E, F> {
1161    fn clone(&self) -> Self {
1162        Self {
1163            replica: self.replica,
1164            inner: self.inner.clone(),
1165            forwarder: self.forwarder.clone(),
1166        }
1167    }
1168}
1169
1170impl<P: PublicKey, E: Clock, F: SplitForwarder<P>> std::fmt::Debug for SplitSender<P, E, F> {
1171    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1172        f.debug_struct("SplitSender")
1173            .field("replica", &self.replica)
1174            .field("inner", &self.inner)
1175            .finish()
1176    }
1177}
1178
1179impl<P: PublicKey, E: Clock, F: SplitForwarder<P>> crate::LimitedSender for SplitSender<P, E, F> {
1180    type PublicKey = P;
1181    type Checked<'a> = SplitCheckedSender<'a, P, E, F>;
1182
1183    fn check(
1184        &mut self,
1185        recipients: Recipients<Self::PublicKey>,
1186    ) -> Result<Self::Checked<'_>, SystemTime> {
1187        Ok(SplitCheckedSender {
1188            // Perform a rate limit check with the entire set of original recipients although
1189            // the forwarder may filter these (based on message content) during send.
1190            checked: self.inner.limited_sender.check(recipients.clone())?,
1191            replica: self.replica,
1192            forwarder: self.forwarder.clone(),
1193            recipients,
1194
1195            _phantom: std::marker::PhantomData,
1196        })
1197    }
1198}
1199
1200/// A checked sender for [`SplitSender`] that defers the forwarder call to send time.
1201///
1202/// This is necessary because [`SplitForwarder`] may examine message content to determine
1203/// routing, but the message is not available at [`LimitedSender::check`] time.
1204pub struct SplitCheckedSender<'a, P: PublicKey, E: Clock, F: SplitForwarder<P>> {
1205    checked: LimitedCheckedSender<'a, UnlimitedSender<P, E>>,
1206    replica: SplitOrigin,
1207    forwarder: F,
1208    recipients: Recipients<P>,
1209
1210    _phantom: std::marker::PhantomData<E>,
1211}
1212
1213impl<'a, P: PublicKey, E: Clock, F: SplitForwarder<P>> crate::CheckedSender
1214    for SplitCheckedSender<'a, P, E, F>
1215{
1216    type PublicKey = P;
1217
1218    fn recipients(&self) -> Vec<Self::PublicKey> {
1219        crate::CheckedSender::recipients(&self.checked)
1220    }
1221
1222    fn send(self, message: impl Into<IoBufs> + Send, priority: bool) -> Unreliable<Feedback> {
1223        // Convert to IoBuf here since forwarder needs to inspect the message
1224        let message = message.into().coalesce();
1225
1226        // Determine the set of recipients that will receive the message
1227        let Some(recipients) = (self.forwarder)(self.replica, &self.recipients, &message) else {
1228            return Unreliable::Rejected;
1229        };
1230
1231        // Extract the inner sender and send directly with the new recipients
1232        //
1233        // While SplitForwarder does not enforce any relationship between the original recipients
1234        // and the new recipients, it is typically some subset of the original recipients. This
1235        // means we may over-rate limit some recipients (who are never actually sent a message here) but
1236        // we prefer this to not providing feedback at all (we would have to skip check entirely).
1237        self.checked
1238            .into_inner()
1239            .send(recipients, message, priority)
1240    }
1241}
1242
1243type MessageReceiver<P> = mpsc::UnboundedReceiver<NetworkMessage<P>>;
1244type ChannelRegistration<P> = (
1245    Channel,
1246    RegistrationGuard,
1247    oneshot::Sender<MessageReceiver<P>>,
1248);
1249
1250/// Implementation of a [crate::Receiver] for the simulated network.
1251#[derive(Debug)]
1252pub struct Receiver<P: PublicKey> {
1253    receiver: MessageReceiver<P>,
1254}
1255
1256impl<P: PublicKey> crate::Receiver for Receiver<P> {
1257    type Error = Error;
1258    type PublicKey = P;
1259
1260    async fn recv(&mut self) -> Result<NetworkMessage<Self::PublicKey>, Error> {
1261        self.receiver.recv().await.ok_or(Error::NetworkClosed)
1262    }
1263}
1264
1265impl<P: PublicKey> Receiver<P> {
1266    /// Split this [Receiver] into a [SplitTarget::Primary] and [SplitTarget::Secondary] receiver.
1267    pub fn split_with<E: Spawner, R: SplitRouter<P>>(
1268        mut self,
1269        context: E,
1270        router: R,
1271    ) -> (Self, Self) {
1272        let (primary_tx, primary_rx) = mpsc::unbounded_channel();
1273        let (secondary_tx, secondary_rx) = mpsc::unbounded_channel();
1274        context.spawn(move |_| async move {
1275            while let Some(message) = self.receiver.recv().await {
1276                // Route message to the appropriate target
1277                let direction = router(&message);
1278                match direction {
1279                    SplitTarget::None => {}
1280                    SplitTarget::Primary => {
1281                        if let Err(err) = primary_tx.send(message) {
1282                            error!(?err, "failed to send message to primary");
1283                        }
1284                    }
1285                    SplitTarget::Secondary => {
1286                        if let Err(err) = secondary_tx.send(message) {
1287                            error!(?err, "failed to send message to secondary");
1288                        }
1289                    }
1290                    SplitTarget::Both => {
1291                        if let Err(err) = primary_tx.send(message.clone()) {
1292                            error!(?err, "failed to send message to primary");
1293                        }
1294                        if let Err(err) = secondary_tx.send(message) {
1295                            error!(?err, "failed to send message to secondary");
1296                        }
1297                    }
1298                }
1299
1300                // Exit if both channels are closed
1301                if primary_tx.is_closed() && secondary_tx.is_closed() {
1302                    break;
1303                }
1304            }
1305        });
1306
1307        (
1308            Self {
1309                receiver: primary_rx,
1310            },
1311            Self {
1312                receiver: secondary_rx,
1313            },
1314        )
1315    }
1316}
1317
1318/// A peer in the simulated network.
1319///
1320/// The peer can register channels, which allows it to receive messages sent to the channel from other peers.
1321struct Peer<P: PublicKey> {
1322    // Socket address that the peer is listening on
1323    socket: SocketAddr,
1324
1325    // Control to register new channels
1326    control: mpsc::UnboundedSender<ChannelRegistration<P>>,
1327}
1328
1329impl<P: PublicKey> Peer<P> {
1330    /// Create and return a new peer.
1331    ///
1332    /// The peer will listen for incoming connections on the given `socket` address.
1333    /// `max_frame_size` is the maximum size of an internal framed message.
1334    async fn new<E: Spawner + RNetwork + Metrics + Clock>(
1335        context: E,
1336        public_key: P,
1337        socket: SocketAddr,
1338        max_frame_size: u32,
1339    ) -> Self {
1340        // The control is used to register channels.
1341        let (control_sender, mut control_receiver): (
1342            mpsc::UnboundedSender<ChannelRegistration<P>>,
1343            _,
1344        ) = mpsc::unbounded_channel();
1345
1346        // Whenever a message is received from a peer, it is placed in the inbox.
1347        // The router polls the inbox and forwards the message to the appropriate mailbox.
1348        let (inbox_sender, mut inbox_receiver) = mpsc::unbounded_channel();
1349
1350        // Spawn router
1351        context.child("router").spawn(|context| async move {
1352            // Map of channels to mailboxes (senders to particular channels)
1353            let mut mailboxes = HashMap::new();
1354
1355            // Continually listen for control messages and outbound messages
1356            select_loop! {
1357                context,
1358                on_stopped => {},
1359                // Listen for control messages, which are used to register channels
1360                Some((channel, guard, result_tx)) = control_receiver.recv() else break => {
1361                    // Register channel
1362                    let (receiver_tx, receiver_rx) = mpsc::unbounded_channel();
1363                    if mailboxes.insert(channel, (receiver_tx, guard)).is_some() {
1364                        warn!(?public_key, ?channel, "overwriting existing channel");
1365                    }
1366                    result_tx.send(receiver_rx).unwrap();
1367                },
1368
1369                // Listen for messages from the inbox, which are forwarded to the appropriate mailbox
1370                Some((channel, message)) = inbox_receiver.recv() else break => {
1371                    // Send message to mailbox
1372                    match mailboxes.get_mut(&channel) {
1373                        Some((receiver_tx, _)) => {
1374                            if let Err(err) = receiver_tx.send(message) {
1375                                debug!(?err, "failed to send message to mailbox");
1376                            }
1377                        }
1378                        None => {
1379                            trace!(
1380                                recipient = ?public_key,
1381                                channel,
1382                                reason = "missing channel",
1383                                "dropping message",
1384                            );
1385                        }
1386                    }
1387                },
1388            }
1389        });
1390
1391        // Spawn a task that accepts new connections and spawns a task for each connection
1392        let (ready_tx, ready_rx) = oneshot::channel();
1393        context.child("listener").spawn(move |context| async move {
1394            // Initialize listener
1395            let mut listener = context.bind(socket).await.unwrap();
1396            let _ = ready_tx.send(());
1397
1398            // Continually accept new connections
1399            while let Ok((_, _, mut stream)) = listener.accept().await {
1400                // New connection accepted. Spawn a task for this connection
1401                context.child("receiver").spawn({
1402                    let inbox_sender = inbox_sender.clone();
1403                    move |_| async move {
1404                        // Receive dialer's public key as a handshake
1405                        let dialer = match recv_frame(&mut stream, max_frame_size).await {
1406                            Ok(data) => data,
1407                            Err(_) => {
1408                                error!("failed to receive public key from dialer");
1409                                return;
1410                            }
1411                        };
1412                        let Ok(dialer) = P::decode(dialer.coalesce()) else {
1413                            error!("received public key is invalid");
1414                            return;
1415                        };
1416
1417                        // Continually receive messages from the dialer and send them to the inbox
1418                        while let Ok(data) = recv_frame(&mut stream, max_frame_size).await {
1419                            let data = data.coalesce();
1420                            let channel = Channel::from_be_bytes(
1421                                data.as_ref()[..Channel::SIZE].try_into().unwrap(),
1422                            );
1423                            let message = data.slice(Channel::SIZE..);
1424                            if let Err(err) =
1425                                inbox_sender.send((channel, (dialer.clone(), message)))
1426                            {
1427                                debug!(?err, "failed to send message to mailbox");
1428                                break;
1429                            }
1430                        }
1431                    }
1432                });
1433            }
1434        });
1435
1436        // Wait for listener to start before returning
1437        let _ = ready_rx.await;
1438
1439        // Return peer
1440        Self {
1441            socket,
1442            control: control_sender,
1443        }
1444    }
1445
1446    /// Register a channel with the peer.
1447    ///
1448    /// This allows the peer to receive messages sent to the channel.
1449    /// Returns a receiver that can be used to receive messages sent to the channel.
1450    async fn register(
1451        &mut self,
1452        channel: Channel,
1453        guard: RegistrationGuard,
1454    ) -> Result<MessageReceiver<P>, Error> {
1455        let (result_tx, result_rx) = oneshot::channel();
1456        self.control
1457            .send((channel, guard, result_tx))
1458            .map_err(|_| Error::NetworkClosed)?;
1459        result_rx.await.map_err(|_| Error::NetworkClosed)
1460    }
1461}
1462
1463// A unidirectional link between two peers.
1464// Messages can be sent over the link with a given latency, jitter, and success rate.
1465struct Link {
1466    sampler: Normal<f64>,
1467    success_rate: Probability,
1468    // Messages with their receive time for ordered delivery
1469    inbox: mpsc::UnboundedSender<(Channel, IoBuf, SystemTime)>,
1470}
1471
1472/// Buffered payload waiting for earlier messages on the same link to complete.
1473impl Link {
1474    #[allow(clippy::too_many_arguments)]
1475    fn new<E: Spawner + RNetwork + Clock + Metrics, P: PublicKey>(
1476        context: &mut E,
1477        dialer: P,
1478        receiver: P,
1479        socket: SocketAddr,
1480        sampler: Normal<f64>,
1481        success_rate: Probability,
1482        max_frame_size: u32,
1483        received_messages: CounterFamily<metrics::Message>,
1484    ) -> Self {
1485        // Spawn a task that will wait for messages to be sent to the link and then send them
1486        // over the network.
1487        let (inbox, mut outbox) = mpsc::unbounded_channel::<(Channel, IoBuf, SystemTime)>();
1488        context.child("link").spawn(move |context| async move {
1489            // Dial the peer and handshake by sending it the dialer's public key
1490            let (mut sink, _) = context.dial(socket).await.unwrap();
1491            if let Err(err) = send_frame(&mut sink, dialer.as_ref().to_vec(), max_frame_size).await
1492            {
1493                error!(?err, "failed to send public key to listener");
1494                return;
1495            }
1496
1497            // Process messages in order, waiting for their receive time
1498            while let Some((channel, message, receive_complete_at)) = outbox.recv().await {
1499                // Wait until the message should arrive at receiver
1500                context.sleep_until(receive_complete_at).await;
1501
1502                // Send the message
1503                let channel_bytes = channel.to_be_bytes();
1504                let mut data = Vec::with_capacity(channel_bytes.len() + message.len());
1505                data.extend_from_slice(&channel_bytes);
1506                data.extend_from_slice(message.as_ref());
1507                let _ = send_frame(&mut sink, data, max_frame_size).await;
1508
1509                // Bump received messages metric
1510                received_messages
1511                    .get_or_create(&metrics::Message::new(&dialer, &receiver, channel))
1512                    .inc();
1513            }
1514        });
1515
1516        Self {
1517            sampler,
1518            success_rate,
1519            inbox,
1520        }
1521    }
1522
1523    // Send a message over the link with receive timing.
1524    fn send(
1525        &mut self,
1526        channel: Channel,
1527        message: IoBuf,
1528        receive_complete_at: SystemTime,
1529    ) -> Result<(), Error> {
1530        self.inbox
1531            .send((channel, message, receive_complete_at))
1532            .map_err(|_| Error::NetworkClosed)?;
1533        Ok(())
1534    }
1535}
1536
1537#[cfg(test)]
1538mod tests {
1539    use super::*;
1540    use crate::{
1541        CheckedSender as _, LimitedSender as _, Manager as _, Provider, Receiver as _, Recipients,
1542        Sender as _, TrackedPeers,
1543    };
1544    use commonware_cryptography::{Signer as _, ed25519};
1545    use commonware_runtime::{Quota, Runner as _, Supervisor as _, deterministic};
1546    use commonware_utils::{NZUsize, ordered::Set, probability};
1547    use futures::FutureExt;
1548    use std::num::NonZeroU32;
1549
1550    const MAX_MESSAGE_SIZE: u32 = 1024 * 1024;
1551
1552    /// Default rate limit set high enough to not interfere with normal operation
1553    const TEST_QUOTA: Quota = Quota::per_second(NonZeroU32::MAX);
1554
1555    async fn send_when_ready(
1556        context: &deterministic::Context,
1557        sender: &mut Sender<ed25519::PublicKey, deterministic::Context>,
1558        recipients: Recipients<ed25519::PublicKey>,
1559        expected_recipients: usize,
1560        message: Vec<u8>,
1561        priority: bool,
1562    ) -> SystemTime {
1563        loop {
1564            let checked = sender.check(recipients.clone()).unwrap();
1565            if checked.recipients().len() == expected_recipients {
1566                checked.send(message, priority);
1567                return context.current();
1568            }
1569            context.sleep(Duration::from_millis(1)).await;
1570        }
1571    }
1572
1573    /// [`Network::new_with_peers`] seeds peers; controls can register channels and add a link once;
1574    /// a duplicate link between the same pair returns [`Error::LinkExists`].
1575    #[test]
1576    fn test_register_and_link() {
1577        let executor = deterministic::Runner::default();
1578        executor.start(|context| async move {
1579            let cfg = Config {
1580                max_size: MAX_MESSAGE_SIZE,
1581                max_peers_per_set: NZUsize!(2),
1582                disconnect_on_block: true,
1583                tracked_peer_sets: NZUsize!(3),
1584            };
1585            // Create two public keys
1586            let pk1 = ed25519::PrivateKey::from_seed(1).public_key();
1587            let pk2 = ed25519::PrivateKey::from_seed(2).public_key();
1588            let peers = [pk1.clone(), pk2.clone()];
1589
1590            let (network, oracle) =
1591                Network::new_with_peers(context.child("network"), cfg, peers).await;
1592            network.start();
1593
1594            let control = oracle.control(pk1.clone());
1595            control.register(0, TEST_QUOTA).await.unwrap();
1596            control.register(1, TEST_QUOTA).await.unwrap();
1597            let control = oracle.control(pk2.clone());
1598            control.register(0, TEST_QUOTA).await.unwrap();
1599            control.register(1, TEST_QUOTA).await.unwrap();
1600
1601            // Overwrite if registering again
1602            control.register(1, TEST_QUOTA).await.unwrap();
1603
1604            // Add link
1605            let link = ingress::Link {
1606                latency: Duration::from_millis(2),
1607                jitter: Duration::from_millis(1),
1608                success_rate: probability!(0.9),
1609            };
1610            oracle
1611                .add_link(pk1.clone(), pk2.clone(), link.clone())
1612                .await
1613                .unwrap();
1614
1615            // Expect error when adding link again
1616            assert!(matches!(
1617                oracle.add_link(pk1, pk2, link).await,
1618                Err(Error::LinkExists)
1619            ));
1620        });
1621    }
1622
1623    /// [`Config::max_size`] must leave enough frame capacity for internal overhead.
1624    #[test]
1625    #[should_panic(expected = "maximum frame size overflow")]
1626    fn test_max_size_overflow_panics() {
1627        let executor = deterministic::Runner::default();
1628        executor.start(|context| async move {
1629            let cfg = Config {
1630                max_size: u32::MAX,
1631                max_peers_per_set: NZUsize!(1),
1632                disconnect_on_block: true,
1633                tracked_peer_sets: NZUsize!(1),
1634            };
1635            let _ = Network::<deterministic::Context, ed25519::PublicKey>::new(
1636                context.child("network"),
1637                cfg,
1638            );
1639        });
1640    }
1641
1642    /// [`Config::max_size`] limits the payload without counting the internal channel identifier.
1643    #[test]
1644    fn test_max_size_applies_to_payload() {
1645        const MAX_SIZE: usize = 64;
1646
1647        let executor = deterministic::Runner::default();
1648        executor.start(|context| async move {
1649            let cfg = Config {
1650                max_size: MAX_SIZE as u32,
1651                max_peers_per_set: NZUsize!(2),
1652                disconnect_on_block: true,
1653                tracked_peer_sets: NZUsize!(1),
1654            };
1655            let (network, oracle) = Network::new(context.child("network"), cfg);
1656            let network_handle = network.start();
1657
1658            let sender_pk = ed25519::PrivateKey::from_seed(1).public_key();
1659            let recipient_pk = ed25519::PrivateKey::from_seed(2).public_key();
1660
1661            let mut manager = oracle.manager();
1662            manager.track(
1663                0,
1664                Set::try_from([sender_pk.clone(), recipient_pk.clone()]).unwrap(),
1665            );
1666
1667            let (mut sender, _) = oracle
1668                .control(sender_pk.clone())
1669                .register(0, TEST_QUOTA)
1670                .await
1671                .unwrap();
1672            let (_, mut receiver) = oracle
1673                .control(recipient_pk.clone())
1674                .register(0, TEST_QUOTA)
1675                .await
1676                .unwrap();
1677
1678            oracle
1679                .add_link(
1680                    sender_pk.clone(),
1681                    recipient_pk.clone(),
1682                    ingress::Link {
1683                        latency: Duration::ZERO,
1684                        jitter: Duration::ZERO,
1685                        success_rate: probability!(1.0),
1686                    },
1687                )
1688                .await
1689                .unwrap();
1690
1691            let message = vec![42; MAX_SIZE];
1692            send_when_ready(
1693                &context,
1694                &mut sender,
1695                Recipients::One(recipient_pk),
1696                1,
1697                message.clone(),
1698                false,
1699            )
1700            .await;
1701
1702            let (origin, received) = context
1703                .timeout(Duration::from_secs(1), async move { receiver.recv().await })
1704                .await
1705                .expect("maximum-sized payload was not delivered")
1706                .unwrap();
1707            assert_eq!(origin, sender_pk);
1708            assert_eq!(received, message.as_slice());
1709
1710            drop(oracle);
1711            drop(sender);
1712            network_handle.abort();
1713        });
1714    }
1715
1716    /// [`Network::new_with_split_peers`] registers id `0` with separate primary and secondary sets,
1717    /// exposes the same split from [`Manager::peer_set`], and emits a matching [`PeerSetUpdate`] on subscribe.
1718    #[test]
1719    fn test_new_with_split_peers_seeds_initial_update() {
1720        let executor = deterministic::Runner::default();
1721        executor.start(|context| async move {
1722            let cfg = Config {
1723                max_size: MAX_MESSAGE_SIZE,
1724                max_peers_per_set: NZUsize!(2),
1725                disconnect_on_block: true,
1726                tracked_peer_sets: NZUsize!(3),
1727            };
1728            let primary = ed25519::PrivateKey::from_seed(11).public_key();
1729            let secondary = ed25519::PrivateKey::from_seed(12).public_key();
1730
1731            let (network, oracle) = Network::new_with_split_peers(
1732                context.child("network"),
1733                cfg,
1734                [primary.clone()],
1735                [secondary.clone()],
1736            )
1737            .await;
1738            network.start();
1739
1740            let mut manager = oracle.manager();
1741            let peer_set = manager.peer_set(0).await.unwrap();
1742            assert_eq!(peer_set.primary, Set::try_from([primary.clone()]).unwrap());
1743            assert_eq!(
1744                peer_set.secondary,
1745                Set::try_from([secondary.clone()]).unwrap()
1746            );
1747
1748            let mut updates = manager.subscribe().await;
1749            let update = updates.recv().await.unwrap();
1750            assert_eq!(update.index, 0);
1751            assert_eq!(
1752                update.latest.primary,
1753                Set::try_from([primary.clone()]).unwrap()
1754            );
1755            assert_eq!(
1756                update.latest.secondary,
1757                Set::try_from([secondary.clone()]).unwrap()
1758            );
1759            assert_eq!(update.all.primary, Set::try_from([primary]).unwrap());
1760            assert_eq!(update.all.secondary, Set::try_from([secondary]).unwrap());
1761        });
1762    }
1763
1764    #[test]
1765    fn test_max_peers_per_set_allows_larger_union_across_sets() {
1766        let executor = deterministic::Runner::default();
1767        executor.start(|context| async move {
1768            let cfg = Config {
1769                max_size: MAX_MESSAGE_SIZE,
1770                max_peers_per_set: NZUsize!(2),
1771                disconnect_on_block: true,
1772                tracked_peer_sets: NZUsize!(2),
1773            };
1774            let (mut network, _oracle) = Network::new(context.child("network"), cfg);
1775            let peer_1 = ed25519::PrivateKey::from_seed(1).public_key();
1776            let peer_2 = ed25519::PrivateKey::from_seed(2).public_key();
1777            let peer_3 = ed25519::PrivateKey::from_seed(3).public_key();
1778
1779            // Each set contains two identities. Their combined union may be larger than either
1780            // individual set.
1781            assert!(
1782                network
1783                    .register_tracked_peer_set(
1784                        0,
1785                        TrackedPeers::new(
1786                            Set::try_from([peer_1]).unwrap(),
1787                            Set::try_from([peer_2.clone()]).unwrap(),
1788                        ),
1789                    )
1790                    .await
1791            );
1792            assert!(
1793                network
1794                    .register_tracked_peer_set(
1795                        1,
1796                        TrackedPeers::new(
1797                            Set::try_from([peer_2]).unwrap(),
1798                            Set::try_from([peer_3]).unwrap(),
1799                        ),
1800                    )
1801                    .await
1802            );
1803            assert_eq!(network.peer_ref_counts.len(), 3);
1804        });
1805    }
1806
1807    #[test]
1808    #[should_panic(expected = "peer set too large: 3 > 2")]
1809    fn test_max_peers_per_set_rejects_primary_secondary_union() {
1810        let executor = deterministic::Runner::default();
1811        executor.start(|context| async move {
1812            let cfg = Config {
1813                max_size: MAX_MESSAGE_SIZE,
1814                max_peers_per_set: NZUsize!(2),
1815                disconnect_on_block: true,
1816                tracked_peer_sets: NZUsize!(1),
1817            };
1818            let (mut network, _oracle) = Network::new(context.child("network"), cfg);
1819            let peer_1 = ed25519::PrivateKey::from_seed(1).public_key();
1820            let peer_2 = ed25519::PrivateKey::from_seed(2).public_key();
1821            let peer_3 = ed25519::PrivateKey::from_seed(3).public_key();
1822
1823            network
1824                .register_tracked_peer_set(
1825                    0,
1826                    TrackedPeers::new(
1827                        Set::try_from([peer_1, peer_2.clone()]).unwrap(),
1828                        Set::try_from([peer_2, peer_3]).unwrap(),
1829                    ),
1830                )
1831                .await;
1832        });
1833    }
1834
1835    #[test]
1836    fn test_peer_set_size_deduplicates_roles_and_sets() {
1837        let executor = deterministic::Runner::default();
1838        executor.start(|context| async move {
1839            let cfg = Config {
1840                max_size: MAX_MESSAGE_SIZE,
1841                max_peers_per_set: NZUsize!(2),
1842                disconnect_on_block: true,
1843                tracked_peer_sets: NZUsize!(2),
1844            };
1845            let (mut network, _oracle) = Network::new(context.child("network"), cfg);
1846            let peer_1 = ed25519::PrivateKey::from_seed(1).public_key();
1847            let peer_2 = ed25519::PrivateKey::from_seed(2).public_key();
1848
1849            // Within a set, a primary identity is not also counted as secondary. Across retained
1850            // sets, each identity may still hold one reference in each role.
1851            assert!(
1852                network
1853                    .register_tracked_peer_set(
1854                        0,
1855                        TrackedPeers::new(
1856                            Set::try_from([peer_1.clone()]).unwrap(),
1857                            Set::try_from([peer_1.clone(), peer_2.clone()]).unwrap(),
1858                        ),
1859                    )
1860                    .await
1861            );
1862            assert!(
1863                network
1864                    .register_tracked_peer_set(
1865                        1,
1866                        TrackedPeers::new(
1867                            Set::try_from([peer_2.clone()]).unwrap(),
1868                            Set::try_from([peer_1.clone()]).unwrap(),
1869                        ),
1870                    )
1871                    .await
1872            );
1873
1874            assert_eq!(network.peer_ref_counts.len(), 2);
1875            let peer_1_counts = network.peer_ref_counts.get(&peer_1).unwrap();
1876            assert_eq!(peer_1_counts.primary, 1);
1877            assert_eq!(peer_1_counts.secondary, 1);
1878            let peer_2_counts = network.peer_ref_counts.get(&peer_2).unwrap();
1879            assert_eq!(peer_2_counts.primary, 1);
1880            assert_eq!(peer_2_counts.secondary, 1);
1881        });
1882    }
1883
1884    /// Split sender/receiver routes each half to a different neighbor: primary out goes only to `peer_a`,
1885    /// secondary out only to `peer_b`, and inbound mail is demuxed by sender id.
1886    #[test]
1887    fn test_split_channel_single() {
1888        let executor = deterministic::Runner::default();
1889        executor.start(|context| async move {
1890            let cfg = Config {
1891                max_size: MAX_MESSAGE_SIZE,
1892                max_peers_per_set: NZUsize!(3),
1893                disconnect_on_block: true,
1894                tracked_peer_sets: NZUsize!(3),
1895            };
1896            let (network, oracle) = Network::new(context.child("network"), cfg);
1897            network.start();
1898
1899            // Create a "twin" node that will be split, plus two normal peers
1900            let twin = ed25519::PrivateKey::from_seed(20).public_key();
1901            let peer_a = ed25519::PrivateKey::from_seed(21).public_key();
1902            let peer_b = ed25519::PrivateKey::from_seed(22).public_key();
1903
1904            // Register all peers
1905            let mut manager = oracle.manager();
1906            manager.track(
1907                0,
1908                Set::try_from([twin.clone(), peer_a.clone(), peer_b.clone()]).unwrap(),
1909            );
1910
1911            // Register normal peers
1912            let (mut peer_a_sender, mut peer_a_recv) = oracle
1913                .control(peer_a.clone())
1914                .register(0, TEST_QUOTA)
1915                .await
1916                .unwrap();
1917            let (mut peer_b_sender, mut peer_b_recv) = oracle
1918                .control(peer_b.clone())
1919                .register(0, TEST_QUOTA)
1920                .await
1921                .unwrap();
1922
1923            // Register and split the twin's channel:
1924            // - Primary sends only to peer_a
1925            // - Secondary sends only to peer_b
1926            // - Messages from peer_a go to primary receiver
1927            // - Messages from peer_b go to secondary receiver
1928            let (twin_sender, twin_receiver) = oracle
1929                .control(twin.clone())
1930                .register(0, TEST_QUOTA)
1931                .await
1932                .unwrap();
1933            let peer_a_for_router = peer_a.clone();
1934            let peer_b_for_router = peer_b.clone();
1935            let (mut twin_primary_sender, mut twin_secondary_sender) =
1936                twin_sender.split_with(move |origin, _, _| match origin {
1937                    SplitOrigin::Primary => Some(Recipients::One(peer_a_for_router.clone())),
1938                    SplitOrigin::Secondary => Some(Recipients::One(peer_b_for_router.clone())),
1939                });
1940            let peer_a_for_recv = peer_a.clone();
1941            let peer_b_for_recv = peer_b.clone();
1942            let (mut twin_primary_recv, mut twin_secondary_recv) =
1943                twin_receiver.split_with(context.child("split_receiver"), move |(sender, _)| {
1944                    if sender == &peer_a_for_recv {
1945                        SplitTarget::Primary
1946                    } else if sender == &peer_b_for_recv {
1947                        SplitTarget::Secondary
1948                    } else {
1949                        panic!("unexpected sender");
1950                    }
1951                });
1952
1953            // Establish bidirectional links
1954            let link = ingress::Link {
1955                latency: Duration::from_millis(0),
1956                jitter: Duration::from_millis(0),
1957                success_rate: probability!(1.0),
1958            };
1959            oracle
1960                .add_link(peer_a.clone(), twin.clone(), link.clone())
1961                .await
1962                .unwrap();
1963            oracle
1964                .add_link(twin.clone(), peer_a.clone(), link.clone())
1965                .await
1966                .unwrap();
1967            oracle
1968                .add_link(peer_b.clone(), twin.clone(), link.clone())
1969                .await
1970                .unwrap();
1971            oracle
1972                .add_link(twin.clone(), peer_b.clone(), link.clone())
1973                .await
1974                .unwrap();
1975
1976            // Send messages in both directions
1977            peer_a_sender.send(Recipients::One(twin.clone()), b"from_a", false);
1978            peer_b_sender.send(Recipients::One(twin.clone()), b"from_b", false);
1979            twin_primary_sender.send(Recipients::All, b"primary_out", false);
1980            twin_secondary_sender.send(Recipients::All, b"secondary_out", false);
1981
1982            // Verify routing: peer_a messages go to primary, peer_b to secondary
1983            let (sender, payload) = twin_primary_recv.recv().await.unwrap();
1984            assert_eq!(sender, peer_a);
1985            assert_eq!(payload, b"from_a");
1986            let (sender, payload) = twin_secondary_recv.recv().await.unwrap();
1987            assert_eq!(sender, peer_b);
1988            assert_eq!(payload, b"from_b");
1989
1990            // Verify routing: primary sends to peer_a, secondary to peer_b
1991            let (sender, payload) = peer_a_recv.recv().await.unwrap();
1992            assert_eq!(sender, twin);
1993            assert_eq!(payload, b"primary_out");
1994            let (sender, payload) = peer_b_recv.recv().await.unwrap();
1995            assert_eq!(sender, twin);
1996            assert_eq!(payload, b"secondary_out");
1997        });
1998    }
1999
2000    /// When both split halves use [`SplitTarget::Both`], a single inbound message is delivered to primary and secondary receivers.
2001    #[test]
2002    fn test_split_channel_both() {
2003        let executor = deterministic::Runner::default();
2004        executor.start(|context| async move {
2005            let cfg = Config {
2006                max_size: MAX_MESSAGE_SIZE,
2007                max_peers_per_set: NZUsize!(2),
2008                disconnect_on_block: true,
2009                tracked_peer_sets: NZUsize!(3),
2010            };
2011            let (network, oracle) = Network::new(context.child("network"), cfg);
2012            network.start();
2013
2014            // Create a "twin" node that will be split, plus a third peer
2015            let twin = ed25519::PrivateKey::from_seed(30).public_key();
2016            let peer_c = ed25519::PrivateKey::from_seed(31).public_key();
2017
2018            // Register all peers
2019            let mut manager = oracle.manager();
2020            manager.track(0, Set::try_from([twin.clone(), peer_c.clone()]).unwrap());
2021
2022            // Register normal peer
2023            let (mut peer_c_sender, _peer_c_recv) = oracle
2024                .control(peer_c.clone())
2025                .register(0, TEST_QUOTA)
2026                .await
2027                .unwrap();
2028
2029            // Register and split the twin's channel with a router that sends to Both
2030            let (twin_sender, twin_receiver) = oracle
2031                .control(twin.clone())
2032                .register(0, TEST_QUOTA)
2033                .await
2034                .unwrap();
2035            let (_twin_primary_sender, _twin_secondary_sender) =
2036                twin_sender.split_with(|_origin, recipients, _| Some(recipients.clone()));
2037            let (mut twin_primary_recv, mut twin_secondary_recv) = twin_receiver
2038                .split_with(context.child("split_receiver_both"), |_| SplitTarget::Both);
2039
2040            // Establish bidirectional links
2041            let link = ingress::Link {
2042                latency: Duration::from_millis(0),
2043                jitter: Duration::from_millis(0),
2044                success_rate: probability!(1.0),
2045            };
2046            oracle
2047                .add_link(peer_c.clone(), twin.clone(), link.clone())
2048                .await
2049                .unwrap();
2050            oracle
2051                .add_link(twin.clone(), peer_c.clone(), link)
2052                .await
2053                .unwrap();
2054
2055            // Send a message from peer_c to twin
2056            peer_c_sender.send(Recipients::One(twin.clone()), b"to_both", false);
2057
2058            // Verify both receivers get the message
2059            let (sender, payload) = twin_primary_recv.recv().await.unwrap();
2060            assert_eq!(sender, peer_c);
2061            assert_eq!(payload, b"to_both");
2062            let (sender, payload) = twin_secondary_recv.recv().await.unwrap();
2063            assert_eq!(sender, peer_c);
2064            assert_eq!(payload, b"to_both");
2065        });
2066    }
2067
2068    /// [`SplitTarget::None`] and a send router returning `None` drop traffic: inbound is not
2069    /// delivered to either half, and outbound sends report no recipients after the split forwarder
2070    /// drops them.
2071    #[test]
2072    fn test_split_channel_none() {
2073        let executor = deterministic::Runner::default();
2074        executor.start(|context| async move {
2075            let cfg = Config {
2076                max_size: MAX_MESSAGE_SIZE,
2077                max_peers_per_set: NZUsize!(2),
2078                disconnect_on_block: true,
2079                tracked_peer_sets: NZUsize!(3),
2080            };
2081            let (network, oracle) = Network::new(context.child("network"), cfg);
2082            network.start();
2083
2084            // Create a "twin" node that will be split, plus a third peer
2085            let twin = ed25519::PrivateKey::from_seed(30).public_key();
2086            let peer_c = ed25519::PrivateKey::from_seed(31).public_key();
2087
2088            // Register all peers
2089            let mut manager = oracle.manager();
2090            manager.track(0, Set::try_from([twin.clone(), peer_c.clone()]).unwrap());
2091
2092            // Register normal peer
2093            let (mut peer_c_sender, _peer_c_recv) = oracle
2094                .control(peer_c.clone())
2095                .register(0, TEST_QUOTA)
2096                .await
2097                .unwrap();
2098
2099            // Register and split the twin's channel with a router that sends to Both
2100            let (twin_sender, twin_receiver) = oracle
2101                .control(twin.clone())
2102                .register(0, TEST_QUOTA)
2103                .await
2104                .unwrap();
2105            let (mut twin_primary_sender, mut twin_secondary_sender) =
2106                twin_sender.split_with(|_origin, _, _| None);
2107            let (mut twin_primary_recv, mut twin_secondary_recv) = twin_receiver
2108                .split_with(context.child("split_receiver_both"), |_| SplitTarget::None);
2109
2110            // Establish bidirectional links
2111            let link = ingress::Link {
2112                latency: Duration::from_millis(0),
2113                jitter: Duration::from_millis(0),
2114                success_rate: probability!(1.0),
2115            };
2116            oracle
2117                .add_link(peer_c.clone(), twin.clone(), link.clone())
2118                .await
2119                .unwrap();
2120            oracle
2121                .add_link(twin.clone(), peer_c.clone(), link)
2122                .await
2123                .unwrap();
2124
2125            // Send a message from peer_c to twin
2126            let sent = peer_c_sender.send(Recipients::One(twin.clone()), b"to_both", false);
2127            assert_eq!(sent.len(), 1);
2128            assert_eq!(sent[0], twin);
2129
2130            // Verify both receivers get the message
2131            context.sleep(Duration::from_millis(100)).await;
2132            assert!(twin_primary_recv.recv().now_or_never().is_none());
2133            assert!(twin_secondary_recv.recv().now_or_never().is_none());
2134
2135            // Send a message from twin to peer_c
2136            let sent = twin_primary_sender.send(Recipients::One(peer_c.clone()), b"to_both", false);
2137            assert!(sent.is_empty());
2138
2139            // Send a message from twin to peer_c
2140            let sent =
2141                twin_secondary_sender.send(Recipients::One(peer_c.clone()), b"to_both", false);
2142            assert!(sent.is_empty());
2143        });
2144    }
2145
2146    /// [`Manager::track`] indices may arrive out of order: older indices are ignored; subscribers see updates in commit order
2147    /// and [`PeerSetUpdate::all`] accumulates primaries across applied sets.
2148    #[test]
2149    fn test_unordered_peer_sets() {
2150        let executor = deterministic::Runner::default();
2151        executor.start(|context| async move {
2152            let cfg = Config {
2153                max_size: MAX_MESSAGE_SIZE,
2154                max_peers_per_set: NZUsize!(2),
2155                disconnect_on_block: true,
2156                tracked_peer_sets: NZUsize!(3),
2157            };
2158            let (network, oracle) = Network::new(context.child("network"), cfg);
2159            network.start();
2160
2161            // Create two public keys
2162            let pk1 = ed25519::PrivateKey::from_seed(1).public_key();
2163            let pk2 = ed25519::PrivateKey::from_seed(2).public_key();
2164
2165            // Subscribe to peer sets
2166            let mut manager = oracle.manager();
2167            let mut subscription = manager.subscribe().await;
2168
2169            // Register initial peer set
2170            manager.track(10, Set::try_from([pk1.clone(), pk2.clone()]).unwrap());
2171            let update = subscription.recv().await.unwrap();
2172            assert_eq!(update.index, 10);
2173            assert_eq!(update.latest.primary.len(), 2);
2174            assert!(update.latest.secondary.is_empty());
2175            assert_eq!(update.all.primary.len(), 2);
2176            assert!(update.all.secondary.is_empty());
2177
2178            // Register old peer sets (ignored)
2179            let pk3 = ed25519::PrivateKey::from_seed(3).public_key();
2180            manager.track(9, Set::try_from([pk3.clone()]).unwrap());
2181
2182            // Add new peer set
2183            let pk4 = ed25519::PrivateKey::from_seed(4).public_key();
2184            manager.track(11, Set::try_from([pk4.clone()]).unwrap());
2185            let update = subscription.recv().await.unwrap();
2186            assert_eq!(update.index, 11);
2187            assert_eq!(update.latest.primary, Set::try_from([pk4.clone()]).unwrap());
2188            assert!(update.latest.secondary.is_empty());
2189            assert_eq!(update.all.primary, Set::try_from([pk1, pk2, pk4]).unwrap());
2190            assert!(update.all.secondary.is_empty());
2191        });
2192    }
2193
2194    /// [`PeerSetUpdate::all`] uses primary-wins across *tracked* indices: a peer who is primary in one
2195    /// peer set and secondary in another is listed only under `all.primary` (not in `all.secondary`).
2196    #[test]
2197    fn test_peer_set_update_all_cross_index_primary_wins() {
2198        let executor = deterministic::Runner::default();
2199        executor.start(|context| async move {
2200            let cfg = Config {
2201                max_size: MAX_MESSAGE_SIZE,
2202                max_peers_per_set: NZUsize!(3),
2203                disconnect_on_block: true,
2204                tracked_peer_sets: NZUsize!(3),
2205            };
2206            let (network, oracle) = Network::new(context.child("network"), cfg);
2207            network.start();
2208
2209            let pk_a = ed25519::PrivateKey::from_seed(21).public_key();
2210            let pk_b = ed25519::PrivateKey::from_seed(22).public_key();
2211            // Appears as primary in set 10 and (redundantly) as secondary in set 11.
2212            let pk_overlap = ed25519::PrivateKey::from_seed(23).public_key();
2213            // Secondary-only in set 11; should still appear under aggregate secondary.
2214            let pk_sec = ed25519::PrivateKey::from_seed(24).public_key();
2215
2216            let mut manager = oracle.manager();
2217            let mut subscription = manager.subscribe().await;
2218
2219            manager.track(
2220                10,
2221                TrackedPeers::new(
2222                    Set::try_from([pk_a.clone(), pk_overlap.clone()]).unwrap(),
2223                    Set::default(),
2224                ),
2225            );
2226            let _ = subscription.recv().await.unwrap();
2227
2228            manager.track(
2229                11,
2230                TrackedPeers::new(
2231                    Set::try_from([pk_b.clone()]).unwrap(),
2232                    Set::try_from([pk_overlap.clone(), pk_sec.clone()]).unwrap(),
2233                ),
2234            );
2235            let update = subscription.recv().await.unwrap();
2236            assert_eq!(update.index, 11);
2237
2238            assert_eq!(
2239                update.latest.primary,
2240                Set::try_from([pk_b.clone()]).unwrap()
2241            );
2242            // At index 11 alone, pk_overlap is secondary-only (primary at 11 is pk_b).
2243            assert!(update.latest.secondary.position(&pk_overlap).is_some());
2244            assert!(update.latest.secondary.position(&pk_sec).is_some());
2245
2246            // Across tracked sets: pk_overlap is primary in set 10 -> aggregate lists them only under primary.
2247            assert!(update.all.primary.position(&pk_a).is_some());
2248            assert!(update.all.primary.position(&pk_b).is_some());
2249            assert!(update.all.primary.position(&pk_overlap).is_some());
2250            assert!(
2251                update.all.secondary.position(&pk_overlap).is_none(),
2252                "aggregate secondary must omit peers who have any primary membership"
2253            );
2254            assert!(update.all.secondary.position(&pk_sec).is_some());
2255        });
2256    }
2257
2258    /// [`Network::get_next_socket`] hands out the current address then advances port, wrapping IPv4 and port at boundaries.
2259    #[test]
2260    fn test_get_next_socket() {
2261        let cfg = Config {
2262            max_size: MAX_MESSAGE_SIZE,
2263            max_peers_per_set: NZUsize!(1),
2264            disconnect_on_block: true,
2265            tracked_peer_sets: NZUsize!(1),
2266        };
2267        let runner = deterministic::Runner::default();
2268
2269        runner.start(|context| async move {
2270            type PublicKey = ed25519::PublicKey;
2271            let (mut network, _) =
2272                Network::<deterministic::Context, PublicKey>::new(context.child("network"), cfg);
2273
2274            // Test that the next socket address is incremented correctly
2275            let mut original = network.next_addr;
2276            let next = network.get_next_socket();
2277            assert_eq!(next, original);
2278            let next = network.get_next_socket();
2279            original.set_port(1);
2280            assert_eq!(next, original);
2281
2282            // Test that the port number overflows correctly
2283            let max_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(255, 0, 255, 255)), 65535);
2284            network.next_addr = max_addr;
2285            let next = network.get_next_socket();
2286            assert_eq!(next, max_addr);
2287            let next = network.get_next_socket();
2288            assert_eq!(
2289                next,
2290                SocketAddr::new(IpAddr::V4(Ipv4Addr::new(255, 1, 0, 0)), 0)
2291            );
2292        });
2293    }
2294
2295    /// Many sequential sends to one recipient arrive in order when symmetric per-link bandwidth limits apply.
2296    #[test]
2297    fn test_fifo_burst_same_recipient() {
2298        let cfg = Config {
2299            max_size: MAX_MESSAGE_SIZE,
2300            max_peers_per_set: NZUsize!(2),
2301            disconnect_on_block: true,
2302            tracked_peer_sets: NZUsize!(3),
2303        };
2304        let runner = deterministic::Runner::default();
2305
2306        runner.start(|context| async move {
2307            let (network, oracle) = Network::new(context.child("network"), cfg);
2308            let network_handle = network.start();
2309
2310            let sender_pk = ed25519::PrivateKey::from_seed(10).public_key();
2311            let recipient_pk = ed25519::PrivateKey::from_seed(11).public_key();
2312
2313            let mut manager = oracle.manager();
2314            manager.track(
2315                0,
2316                Set::try_from([sender_pk.clone(), recipient_pk.clone()]).unwrap(),
2317            );
2318            let (mut sender, _sender_recv) = oracle
2319                .control(sender_pk.clone())
2320                .register(0, TEST_QUOTA)
2321                .await
2322                .unwrap();
2323            let (_sender2, mut receiver) = oracle
2324                .control(recipient_pk.clone())
2325                .register(0, TEST_QUOTA)
2326                .await
2327                .unwrap();
2328
2329            oracle
2330                .limit_bandwidth(sender_pk.clone(), Some(5_000), None)
2331                .await
2332                .unwrap();
2333            oracle
2334                .limit_bandwidth(recipient_pk.clone(), None, Some(5_000))
2335                .await
2336                .unwrap();
2337
2338            oracle
2339                .add_link(
2340                    sender_pk.clone(),
2341                    recipient_pk.clone(),
2342                    ingress::Link {
2343                        latency: Duration::from_millis(0),
2344                        jitter: Duration::from_millis(0),
2345                        success_rate: probability!(1.0),
2346                    },
2347                )
2348                .await
2349                .unwrap();
2350
2351            const COUNT: usize = 50;
2352            let mut expected = Vec::with_capacity(COUNT);
2353            for i in 0..COUNT {
2354                let msg = vec![i as u8; 64];
2355                sender
2356                    .check(Recipients::One(recipient_pk.clone()))
2357                    .unwrap()
2358                    .send(msg.clone(), false);
2359                expected.push(msg);
2360            }
2361
2362            for expected_msg in expected {
2363                let (_pk, bytes) = receiver.recv().await.unwrap();
2364                assert_eq!(bytes, expected_msg.as_slice());
2365            }
2366
2367            drop(oracle);
2368            drop(sender);
2369            network_handle.abort();
2370        });
2371    }
2372
2373    /// [`Recipients::All`] to two links shares the sender cap: both deliveries are delayed in line with the shared bandwidth model,
2374    /// not delivered back-to-back.
2375    #[test]
2376    fn test_broadcast_respects_transmit_latency() {
2377        let cfg = Config {
2378            max_size: MAX_MESSAGE_SIZE,
2379            max_peers_per_set: NZUsize!(3),
2380            disconnect_on_block: true,
2381            tracked_peer_sets: NZUsize!(3),
2382        };
2383        let runner = deterministic::Runner::default();
2384
2385        runner.start(|context| async move {
2386            let (network, oracle) = Network::new(context.child("network"), cfg);
2387            let network_handle = network.start();
2388
2389            let sender_pk = ed25519::PrivateKey::from_seed(42).public_key();
2390            let recipient_a = ed25519::PrivateKey::from_seed(43).public_key();
2391            let recipient_b = ed25519::PrivateKey::from_seed(44).public_key();
2392
2393            let mut manager = oracle.manager();
2394            manager.track(
2395                0,
2396                Set::try_from([sender_pk.clone(), recipient_a.clone(), recipient_b.clone()])
2397                    .unwrap(),
2398            );
2399            let (mut sender, _recv_sender) = oracle
2400                .control(sender_pk.clone())
2401                .register(0, TEST_QUOTA)
2402                .await
2403                .unwrap();
2404            let (_sender2, mut recv_a) = oracle
2405                .control(recipient_a.clone())
2406                .register(0, TEST_QUOTA)
2407                .await
2408                .unwrap();
2409            let (_sender3, mut recv_b) = oracle
2410                .control(recipient_b.clone())
2411                .register(0, TEST_QUOTA)
2412                .await
2413                .unwrap();
2414
2415            oracle
2416                .limit_bandwidth(sender_pk.clone(), Some(1_000), None)
2417                .await
2418                .unwrap();
2419            oracle
2420                .limit_bandwidth(recipient_a.clone(), None, Some(1_000))
2421                .await
2422                .unwrap();
2423            oracle
2424                .limit_bandwidth(recipient_b.clone(), None, Some(1_000))
2425                .await
2426                .unwrap();
2427
2428            let link = ingress::Link {
2429                latency: Duration::from_millis(0),
2430                jitter: Duration::from_millis(0),
2431                success_rate: probability!(1.0),
2432            };
2433            oracle
2434                .add_link(sender_pk.clone(), recipient_a.clone(), link.clone())
2435                .await
2436                .unwrap();
2437            oracle
2438                .add_link(sender_pk.clone(), recipient_b.clone(), link)
2439                .await
2440                .unwrap();
2441
2442            let big_msg = vec![7u8; 10_000];
2443            let start = send_when_ready(
2444                &context,
2445                &mut sender,
2446                Recipients::All,
2447                2,
2448                big_msg.clone(),
2449                false,
2450            )
2451            .await;
2452
2453            let (_pk, received_a) = recv_a.recv().await.unwrap();
2454            assert_eq!(received_a, big_msg.as_slice());
2455            let elapsed_a = context.current().duration_since(start).unwrap();
2456            assert!(elapsed_a >= Duration::from_secs(20));
2457
2458            let (_pk, received_b) = recv_b.recv().await.unwrap();
2459            assert_eq!(received_b, big_msg.as_slice());
2460            let elapsed_b = context.current().duration_since(start).unwrap();
2461            assert!(elapsed_b >= Duration::from_secs(20));
2462
2463            // Because bandwidth is shared, the two messages should take about the same time
2464            assert!(elapsed_a.abs_diff(elapsed_b) <= Duration::from_secs(1));
2465
2466            drop(oracle);
2467            drop(sender);
2468            network_handle.abort();
2469        });
2470    }
2471
2472    /// A peer listed in both primary and secondary appears only in [`PeerSetUpdate::latest`] primary; aggregate secondary omits
2473    /// primary keys. [`Recipients::All`] from another peer lists the overlap peer once and still reaches secondary-only peers.
2474    #[test]
2475    fn test_overlapping_primary_secondary_no_duplicate_recipients() {
2476        let executor = deterministic::Runner::default();
2477        executor.start(|context| async move {
2478            let cfg = Config {
2479                max_size: MAX_MESSAGE_SIZE,
2480                max_peers_per_set: NZUsize!(3),
2481                disconnect_on_block: true,
2482                tracked_peer_sets: NZUsize!(3),
2483            };
2484            let (network, oracle) = Network::new(context.child("network"), cfg);
2485            network.start();
2486
2487            let pk1 = ed25519::PrivateKey::from_seed(1).public_key();
2488            let pk2 = ed25519::PrivateKey::from_seed(2).public_key();
2489            let pk3 = ed25519::PrivateKey::from_seed(3).public_key();
2490
2491            let mut manager = oracle.manager();
2492            manager.track(
2493                0,
2494                TrackedPeers::new(
2495                    Set::try_from([pk1.clone(), pk2.clone()]).unwrap(),
2496                    Set::try_from([pk2.clone(), pk3.clone()]).unwrap(),
2497                ),
2498            );
2499
2500            let mut updates = manager.subscribe().await;
2501            let update = updates.recv().await.unwrap();
2502            assert_eq!(update.index, 0);
2503            assert!(update.latest.primary.position(&pk2).is_some());
2504            assert!(
2505                update.latest.secondary.position(&pk2).is_none(),
2506                "overlap peer must not appear in latest.secondary"
2507            );
2508            assert!(update.latest.secondary.position(&pk3).is_some());
2509            assert!(update.all.primary.position(&pk2).is_some());
2510            assert!(
2511                update.all.secondary.position(&pk2).is_none(),
2512                "aggregate secondary must not list peers who are primary"
2513            );
2514            assert!(update.all.secondary.position(&pk3).is_some());
2515
2516            let link = ingress::Link {
2517                latency: Duration::from_millis(1),
2518                jitter: Duration::ZERO,
2519                success_rate: probability!(1.0),
2520            };
2521            for (a, b) in [(&pk1, &pk2), (&pk1, &pk3), (&pk2, &pk3)] {
2522                oracle
2523                    .add_link(a.clone(), b.clone(), link.clone())
2524                    .await
2525                    .unwrap();
2526            }
2527
2528            let (mut sender1, _) = oracle
2529                .control(pk1.clone())
2530                .register(0, TEST_QUOTA)
2531                .await
2532                .unwrap();
2533            let (_, mut recv2) = oracle
2534                .control(pk2.clone())
2535                .register(0, TEST_QUOTA)
2536                .await
2537                .unwrap();
2538            let (_, mut recv3) = oracle
2539                .control(pk3.clone())
2540                .register(0, TEST_QUOTA)
2541                .await
2542                .unwrap();
2543
2544            let msg = vec![42u8; 10];
2545            let checked = sender1.check(Recipients::All).unwrap();
2546            let sent_to = crate::CheckedSender::recipients(&checked);
2547            checked.send(msg.clone(), true);
2548
2549            let pk2_count = sent_to.iter().filter(|pk| *pk == &pk2).count();
2550            assert_eq!(pk2_count, 1, "pk2 received duplicate sends");
2551            assert!(sent_to.iter().any(|pk| pk == &pk3));
2552
2553            context.sleep(Duration::from_millis(10)).await;
2554            let (from2, data2) = recv2.recv().await.unwrap();
2555            assert_eq!(from2, pk1);
2556            assert_eq!(data2, msg.as_slice());
2557            let (from3, data3) = recv3.recv().await.unwrap();
2558            assert_eq!(from3, pk1);
2559            assert_eq!(data3, msg.as_slice());
2560            assert!(recv2.recv().now_or_never().is_none());
2561        });
2562    }
2563
2564    /// A peer can be demoted from primary to secondary across tracked peer set indices.
2565    /// After the old primary-containing set is evicted, the peer is purely secondary.
2566    #[test]
2567    fn test_demotion_from_primary_to_secondary() {
2568        let executor = deterministic::Runner::default();
2569        executor.start(|context| async move {
2570            let cfg = Config {
2571                max_size: 1024,
2572                max_peers_per_set: NZUsize!(2),
2573                disconnect_on_block: true,
2574                tracked_peer_sets: NZUsize!(2),
2575            };
2576            let (network, oracle) = Network::new(context.child("network"), cfg);
2577            network.start();
2578
2579            let pk_x = ed25519::PrivateKey::from_seed(1).public_key();
2580            let pk_y = ed25519::PrivateKey::from_seed(2).public_key();
2581
2582            let mut manager = oracle.manager();
2583            let mut sub = manager.subscribe().await;
2584
2585            // Index 0: X is primary, Y is secondary.
2586            manager.track(
2587                0,
2588                TrackedPeers::new(
2589                    Set::try_from([pk_x.clone()]).unwrap(),
2590                    Set::try_from([pk_y.clone()]).unwrap(),
2591                ),
2592            );
2593
2594            let update = sub.recv().await.unwrap();
2595            assert!(update.all.primary.position(&pk_x).is_some());
2596            assert!(update.all.secondary.position(&pk_y).is_some());
2597
2598            // Index 1: X is demoted to secondary, Y is promoted to primary.
2599            manager.track(
2600                1,
2601                TrackedPeers::new(
2602                    Set::try_from([pk_y.clone()]).unwrap(),
2603                    Set::try_from([pk_x.clone()]).unwrap(),
2604                ),
2605            );
2606
2607            // Both indices retained: both peers are primary somewhere -> aggregate primary.
2608            let update = sub.recv().await.unwrap();
2609            assert!(update.all.primary.position(&pk_x).is_some());
2610            assert!(update.all.primary.position(&pk_y).is_some());
2611            assert!(update.all.secondary.is_empty());
2612
2613            // Index 2: same as index 1. Evicts index 0.
2614            manager.track(
2615                2,
2616                TrackedPeers::new(
2617                    Set::try_from([pk_y.clone()]).unwrap(),
2618                    Set::try_from([pk_x.clone()]).unwrap(),
2619                ),
2620            );
2621
2622            // Index 0 evicted. X is now purely secondary.
2623            let update = sub.recv().await.unwrap();
2624            assert!(update.all.primary.position(&pk_y).is_some());
2625            assert!(update.all.secondary.position(&pk_x).is_some());
2626            assert!(update.all.primary.position(&pk_x).is_none());
2627        });
2628    }
2629
2630    /// After advancing tracked peer sets, secondaries from an older snapshot remain addressable until evicted from history:
2631    /// a new primary can still reach them, while a newer-only primary does not receive messages intended for that tracked secondary view.
2632    #[test]
2633    fn test_secondary_sets_remain_until_eviction() {
2634        let executor = deterministic::Runner::default();
2635        executor.start(|context| async move {
2636            let cfg = Config {
2637                max_size: MAX_MESSAGE_SIZE,
2638                max_peers_per_set: NZUsize!(2),
2639                disconnect_on_block: true,
2640                tracked_peer_sets: NZUsize!(2),
2641            };
2642            let (network, oracle) = Network::new(context.child("network"), cfg);
2643            network.start();
2644
2645            let primary_0 = ed25519::PrivateKey::from_seed(1).public_key();
2646            let primary_1 = ed25519::PrivateKey::from_seed(2).public_key();
2647            let primary_2 = ed25519::PrivateKey::from_seed(3).public_key();
2648            let secondary_0 = ed25519::PrivateKey::from_seed(4).public_key();
2649            let secondary_1 = ed25519::PrivateKey::from_seed(5).public_key();
2650
2651            let mut manager = oracle.manager();
2652            manager.track(
2653                0,
2654                TrackedPeers::new(
2655                    Set::try_from([primary_0.clone()]).unwrap(),
2656                    Set::try_from([secondary_0.clone()]).unwrap(),
2657                ),
2658            );
2659            manager.track(
2660                1,
2661                TrackedPeers::new(
2662                    Set::try_from([primary_1.clone()]).unwrap(),
2663                    Set::try_from([secondary_1.clone()]).unwrap(),
2664                ),
2665            );
2666
2667            let link = ingress::Link {
2668                latency: Duration::from_millis(1),
2669                jitter: Duration::ZERO,
2670                success_rate: probability!(1.0),
2671            };
2672            oracle
2673                .add_link(primary_1.clone(), secondary_0.clone(), link.clone())
2674                .await
2675                .unwrap();
2676            oracle
2677                .add_link(primary_1.clone(), secondary_1.clone(), link.clone())
2678                .await
2679                .unwrap();
2680
2681            let (mut sender_1, _) = oracle
2682                .control(primary_1.clone())
2683                .register(0, TEST_QUOTA)
2684                .await
2685                .unwrap();
2686            let (_, mut receiver_0) = oracle
2687                .control(secondary_0.clone())
2688                .register(0, TEST_QUOTA)
2689                .await
2690                .unwrap();
2691            let (_, mut receiver_1) = oracle
2692                .control(secondary_1.clone())
2693                .register(0, TEST_QUOTA)
2694                .await
2695                .unwrap();
2696
2697            let msg_1 = vec![1u8; 8];
2698            sender_1
2699                .check(Recipients::Some(vec![
2700                    secondary_0.clone(),
2701                    secondary_1.clone(),
2702                ]))
2703                .unwrap()
2704                .send(msg_1.clone(), true);
2705            assert_eq!(receiver_0.recv().await.unwrap().1, msg_1.as_slice());
2706            assert_eq!(receiver_1.recv().await.unwrap().1, msg_1.as_slice());
2707
2708            crate::Manager::track(
2709                &mut manager,
2710                2,
2711                TrackedPeers::primary([primary_2.clone()].try_into().unwrap()),
2712            );
2713            oracle
2714                .add_link(primary_2.clone(), secondary_0.clone(), link.clone())
2715                .await
2716                .unwrap();
2717            oracle
2718                .add_link(primary_2.clone(), secondary_1.clone(), link)
2719                .await
2720                .unwrap();
2721
2722            let (mut sender_2, _) = oracle
2723                .control(primary_2)
2724                .register(0, TEST_QUOTA)
2725                .await
2726                .unwrap();
2727
2728            let msg_2 = vec![2u8; 8];
2729            sender_2
2730                .check(Recipients::Some(vec![
2731                    secondary_0.clone(),
2732                    secondary_1.clone(),
2733                ]))
2734                .unwrap()
2735                .send(msg_2.clone(), true);
2736            assert!(receiver_0.recv().now_or_never().is_none());
2737            assert_eq!(receiver_1.recv().await.unwrap().1, msg_2.as_slice());
2738        });
2739    }
2740}