1use 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
51type PeerSetsAtIndex<P> = PeerSetsAtIndexBase<Set<P>, Set<P>>;
53
54type Task<P> = (Channel, P, Recipients<P>, IoBuf);
56
57const MAX_PAYLOAD_OVERHEAD: u32 = Channel::SIZE as u32;
59
60pub 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#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75#[must_use]
76pub enum SplitTarget {
77 None,
78 Primary,
79 Secondary,
80 Both,
81}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85#[must_use]
86pub enum SplitOrigin {
87 Primary,
88 Secondary,
89}
90
91pub 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
106pub 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#[derive(Clone, Copy, Default)]
119struct PeerRefCounts {
120 primary: usize,
121 secondary: usize,
122}
123
124pub struct Config {
126 pub max_size: u32,
132
133 pub max_peers_per_set: NonZeroUsize,
138
139 pub disconnect_on_block: bool,
143
144 pub tracked_peer_sets: NonZeroUsize,
149}
150
151pub struct Network<E: RNetwork + Spawner + Rng + Clock + Metrics, P: PublicKey> {
153 context: ContextCell<E>,
154
155 max_size: u32,
157
158 max_frame_size: u32,
160
161 max_peers_per_set: usize,
163
164 disconnect_on_block: bool,
168
169 next_addr: SocketAddr,
172
173 ingress: mpsc::UnboundedReceiver<ingress::Message<P, E>>,
175
176 ingress_sender: mpsc::UnboundedSender<ingress::Message<P, E>>,
178
179 links: HashMap<(P, P), Link>,
181
182 peers: BTreeMap<P, Peer<P>>,
184
185 peer_sets: BTreeMap<u64, PeerSetsAtIndex<P>>,
187
188 peer_ref_counts: BTreeMap<P, PeerRefCounts>,
190
191 tracked_peer_sets: NonZeroUsize,
193
194 blocks: BTreeSet<(P, P)>,
196
197 transmitter: transmitter::State<P>,
199
200 subscribers: Vec<mpsc::UnboundedSender<PeerSetUpdate<P>>>,
202
203 peer_subscribers: Vec<(P, ring::Sender<Vec<P>>)>,
205
206 blocked_subscribers: Vec<(P, ring::Sender<Set<P>>)>,
208
209 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 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 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 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 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 async fn register_tracked_peer_set(&mut self, id: u64, peers: TrackedPeers<P>) -> bool {
301 if self.peer_sets.contains_key(&id) {
303 warn!(id, "peer set already exists");
304 return false;
305 }
306
307 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 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 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 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 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 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 fn get_next_socket(&mut self) -> SocketAddr {
415 let result = self.next_addr;
416
417 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 async fn handle_ingress(&mut self, message: ingress::Message<P, E>) {
440 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 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 self.broadcast_peer_list();
477 }
478 ingress::Message::Register {
479 channel,
480 public_key,
481 quota,
482 result,
483 } => {
484 let _ = self.ensure_peer_exists(&public_key).await;
486
487 let clock = self
489 .context
490 .child("rate_limiter")
491 .with_attribute("channel", channel)
492 .with_attribute("peer", &public_key);
493
494 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 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 let (sender, receiver) = mpsc::unbounded_channel();
524
525 if let Some(update) = self.latest_update() {
527 sender.send_lossy(update);
528 }
529 self.subscribers.push(sender);
530
531 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 let _ = self.ensure_peer_exists(&public_key).await;
545
546 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 let _ = result.send(());
555 }
556 ingress::Message::AddLink {
557 sender,
558 receiver,
559 sampler,
560 success_rate,
561 result,
562 } => {
563 let _ = self.ensure_peer_exists(&sender).await;
565 let (receiver_socket, _) = self.ensure_peer_exists(&receiver).await;
566
567 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 async fn ensure_peer_exists(&mut self, public_key: &P) -> (SocketAddr, bool) {
623 if !self.peers.contains_key(public_key) {
624 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 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 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 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 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 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 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 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 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 fn process_completions(&mut self, completions: Vec<Completion<P>>) {
752 for completion in completions {
753 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 let key = (completion.origin.clone(), completion.recipient.clone());
765 let Some(link) = self.links.get_mut(&key) else {
766 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 fn handle_task(&mut self, task: Task<P>) {
785 let (channel, origin, recipients, message) = task;
786
787 if !self.is_connectable(&origin) {
789 warn!(
790 ?origin,
791 reason = "not primary or secondary",
792 "dropping message"
793 );
794 return;
795 }
796
797 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 let now = self.context.current();
806 for recipient in recipients {
807 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 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 let Some(link) = self.links.get_mut(&o_r) else {
835 trace!(?origin, ?recipient, reason = "no link", "dropping message");
836 continue;
837 };
838
839 self.sent_messages
845 .get_or_create(&metrics::Message::new(&origin, &recipient, channel))
846 .inc();
847
848 let latency = Duration::from_millis(link.sampler.sample(self.context.as_mut()) as u64);
850
851 let should_deliver = link.success_rate.sample(self.context.as_mut());
853
854 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 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
957pub 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
1010pub 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 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
1071pub 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 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
1153pub 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 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
1200pub 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 let message = message.into().coalesce();
1225
1226 let Some(recipients) = (self.forwarder)(self.replica, &self.recipients, &message) else {
1228 return Unreliable::Rejected;
1229 };
1230
1231 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#[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 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 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 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
1318struct Peer<P: PublicKey> {
1322 socket: SocketAddr,
1324
1325 control: mpsc::UnboundedSender<ChannelRegistration<P>>,
1327}
1328
1329impl<P: PublicKey> Peer<P> {
1330 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 let (control_sender, mut control_receiver): (
1342 mpsc::UnboundedSender<ChannelRegistration<P>>,
1343 _,
1344 ) = mpsc::unbounded_channel();
1345
1346 let (inbox_sender, mut inbox_receiver) = mpsc::unbounded_channel();
1349
1350 context.child("router").spawn(|context| async move {
1352 let mut mailboxes = HashMap::new();
1354
1355 select_loop! {
1357 context,
1358 on_stopped => {},
1359 Some((channel, guard, result_tx)) = control_receiver.recv() else break => {
1361 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 Some((channel, message)) = inbox_receiver.recv() else break => {
1371 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 let (ready_tx, ready_rx) = oneshot::channel();
1393 context.child("listener").spawn(move |context| async move {
1394 let mut listener = context.bind(socket).await.unwrap();
1396 let _ = ready_tx.send(());
1397
1398 while let Ok((_, _, mut stream)) = listener.accept().await {
1400 context.child("receiver").spawn({
1402 let inbox_sender = inbox_sender.clone();
1403 move |_| async move {
1404 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 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 let _ = ready_rx.await;
1438
1439 Self {
1441 socket,
1442 control: control_sender,
1443 }
1444 }
1445
1446 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
1463struct Link {
1466 sampler: Normal<f64>,
1467 success_rate: Probability,
1468 inbox: mpsc::UnboundedSender<(Channel, IoBuf, SystemTime)>,
1470}
1471
1472impl 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 let (inbox, mut outbox) = mpsc::unbounded_channel::<(Channel, IoBuf, SystemTime)>();
1488 context.child("link").spawn(move |context| async move {
1489 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 while let Some((channel, message, receive_complete_at)) = outbox.recv().await {
1499 context.sleep_until(receive_complete_at).await;
1501
1502 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 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 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 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 #[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 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 control.register(1, TEST_QUOTA).await.unwrap();
1603
1604 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 assert!(matches!(
1617 oracle.add_link(pk1, pk2, link).await,
1618 Err(Error::LinkExists)
1619 ));
1620 });
1621 }
1622
1623 #[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 #[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 #[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 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 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 #[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 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 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 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 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 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 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 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 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 #[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 let twin = ed25519::PrivateKey::from_seed(30).public_key();
2016 let peer_c = ed25519::PrivateKey::from_seed(31).public_key();
2017
2018 let mut manager = oracle.manager();
2020 manager.track(0, Set::try_from([twin.clone(), peer_c.clone()]).unwrap());
2021
2022 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 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 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 peer_c_sender.send(Recipients::One(twin.clone()), b"to_both", false);
2057
2058 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 #[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 let twin = ed25519::PrivateKey::from_seed(30).public_key();
2086 let peer_c = ed25519::PrivateKey::from_seed(31).public_key();
2087
2088 let mut manager = oracle.manager();
2090 manager.track(0, Set::try_from([twin.clone(), peer_c.clone()]).unwrap());
2091
2092 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 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 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 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 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 let sent = twin_primary_sender.send(Recipients::One(peer_c.clone()), b"to_both", false);
2137 assert!(sent.is_empty());
2138
2139 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 #[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 let pk1 = ed25519::PrivateKey::from_seed(1).public_key();
2163 let pk2 = ed25519::PrivateKey::from_seed(2).public_key();
2164
2165 let mut manager = oracle.manager();
2167 let mut subscription = manager.subscribe().await;
2168
2169 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 let pk3 = ed25519::PrivateKey::from_seed(3).public_key();
2180 manager.track(9, Set::try_from([pk3.clone()]).unwrap());
2181
2182 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 #[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 let pk_overlap = ed25519::PrivateKey::from_seed(23).public_key();
2213 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 assert!(update.latest.secondary.position(&pk_overlap).is_some());
2244 assert!(update.latest.secondary.position(&pk_sec).is_some());
2245
2246 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 #[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 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 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 #[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 #[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 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 #[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 #[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 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 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 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 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 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 #[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}