1use tor_basic_utils::{n_key_list, n_key_set};
5use tor_llcrypto::pk::ed25519::Ed25519Identity;
6use tor_llcrypto::pk::rsa::RsaIdentity;
7
8use crate::{HasRelayIds, RelayIdRef};
9
10n_key_list! {
11 #[derive(Clone, Debug)]
23 pub struct[H:HasRelayIds] ListByRelayIds[H] for H
24 {
25 (Option) rsa: RsaIdentity { rsa_identity() },
26 (Option) ed25519: Ed25519Identity { ed_identity() },
27 }
28}
29
30n_key_set! {
31 #[derive(Clone, Debug)]
44 pub struct[H:HasRelayIds] ByRelayIds[H] for H
45 {
46 (Option) rsa: RsaIdentity { rsa_identity() },
47 (Option) ed25519: Ed25519Identity { ed_identity() },
48 }
49}
50
51impl<H: HasRelayIds> ByRelayIds<H> {
52 pub fn by_id<'a, T>(&self, key: T) -> Option<&H>
54 where
55 T: Into<RelayIdRef<'a>>,
56 {
57 match key.into() {
58 RelayIdRef::Ed25519(ed) => self.by_ed25519(ed),
59 RelayIdRef::Rsa(rsa) => self.by_rsa(rsa),
60 }
61 }
62
63 pub fn remove_by_id<'a, T>(&mut self, key: T) -> Option<H>
65 where
66 T: Into<RelayIdRef<'a>>,
67 {
68 match key.into() {
69 RelayIdRef::Ed25519(ed) => self.remove_by_ed25519(ed),
70 RelayIdRef::Rsa(rsa) => self.remove_by_rsa(rsa),
71 }
72 }
73
74 pub fn modify_by_id<'a, T, F>(&mut self, key: T, func: F) -> Vec<H>
78 where
79 T: Into<RelayIdRef<'a>>,
80 F: FnOnce(&mut H),
81 {
82 match key.into() {
83 RelayIdRef::Ed25519(ed) => self.modify_by_ed25519(ed, func),
84 RelayIdRef::Rsa(rsa) => self.modify_by_rsa(rsa, func),
85 }
86 }
87
88 pub fn by_all_ids<T>(&self, key: &T) -> Option<&H>
93 where
94 T: HasRelayIds,
95 {
96 let any_id = key.identities().next()?;
97 self.by_id(any_id)
98 .filter(|val| val.has_all_relay_ids_from(key))
99 }
100
101 pub fn modify_by_all_ids<T, F>(&mut self, key: &T, func: F) -> Vec<H>
106 where
107 T: HasRelayIds,
108 F: FnOnce(&mut H),
109 {
110 let any_id = match key.identities().next() {
111 Some(id) => id,
112 None => return Vec::new(),
113 };
114 self.modify_by_id(any_id, |val| {
115 if val.has_all_relay_ids_from(key) {
116 func(val);
117 }
118 })
119 }
120
121 pub fn remove_exact<T>(&mut self, key: &T) -> Option<H>
124 where
125 T: HasRelayIds,
126 {
127 let any_id = key.identities().next()?;
128 if self
129 .by_id(any_id)
130 .filter(|ent| ent.same_relay_ids(key))
131 .is_some()
132 {
133 self.remove_by_id(any_id)
134 } else {
135 None
136 }
137 }
138
139 pub fn remove_by_all_ids<T>(&mut self, key: &T) -> Option<H>
143 where
144 T: HasRelayIds,
145 {
146 let any_id = key.identities().next()?;
147 if self
148 .by_id(any_id)
149 .filter(|ent| ent.has_all_relay_ids_from(key))
150 .is_some()
151 {
152 self.remove_by_id(any_id)
153 } else {
154 None
155 }
156 }
157
158 pub fn all_overlapping<T>(&self, key: &T) -> Vec<&H>
163 where
164 T: HasRelayIds,
165 {
166 use by_address::ByAddress;
167 use std::collections::HashSet;
168
169 let mut items: HashSet<ByAddress<&H>> = HashSet::new();
170
171 for ident in key.identities() {
172 if let Some(found) = self.by_id(ident) {
173 items.insert(ByAddress(found));
174 }
175 }
176
177 items.into_iter().map(|by_addr| by_addr.0).collect()
178 }
179}
180
181impl<H: HasRelayIds> ListByRelayIds<H> {
182 pub fn by_id<'a, T>(&self, key: T) -> ListByRelayIdsIter<H>
184 where
185 T: Into<RelayIdRef<'a>>,
186 {
187 match key.into() {
188 RelayIdRef::Ed25519(ed) => self.by_ed25519(ed),
189 RelayIdRef::Rsa(rsa) => self.by_rsa(rsa),
190 }
191 }
192
193 pub fn by_all_ids<'a>(&'a self, key: &'a impl HasRelayIds) -> impl Iterator<Item = &'a H> + 'a {
197 key.identities()
198 .next()
199 .map_or_else(Default::default, |id| self.by_id(id))
200 .filter(|val| val.has_all_relay_ids_from(key))
201 }
202
203 pub fn all_overlapping<T>(&self, key: &T) -> Vec<&H>
208 where
209 T: HasRelayIds,
210 {
211 use by_address::ByAddress;
212 use std::collections::HashSet;
213
214 let mut items: HashSet<ByAddress<&H>> = HashSet::new();
215
216 for ident in key.identities() {
217 for found in self.by_id(ident) {
218 items.insert(ByAddress(found));
219 }
220 }
221
222 items.into_iter().map(|by_addr| by_addr.0).collect()
223 }
224
225 pub fn all_subset<T>(&self, key: &T) -> Vec<&H>
231 where
232 T: HasRelayIds,
233 {
234 use by_address::ByAddress;
235 use std::collections::HashSet;
236
237 let mut items: HashSet<ByAddress<&H>> = HashSet::new();
238
239 for ident in key.identities() {
240 for found in self.by_id(ident) {
241 if key.has_all_relay_ids_from(found) {
243 items.insert(ByAddress(found));
244 }
245 }
246 }
247
248 items.into_iter().map(|by_addr| by_addr.0).collect()
249 }
250
251 pub fn remove_by_id<'a, T>(&mut self, key: T, filter: impl FnMut(&H) -> bool) -> Vec<H>
253 where
254 T: Into<RelayIdRef<'a>>,
255 {
256 match key.into() {
257 RelayIdRef::Ed25519(ed) => self.remove_by_ed25519(ed, filter),
258 RelayIdRef::Rsa(rsa) => self.remove_by_rsa(rsa, filter),
259 }
260 }
261
262 pub fn remove_exact<T>(&mut self, key: &T) -> Vec<H>
265 where
266 T: HasRelayIds,
267 {
268 let Some(id) = key.identities().next() else {
269 return Vec::new();
270 };
271
272 self.remove_by_id(id, |val| val.same_relay_ids(key))
273 }
274
275 pub fn remove_by_all_ids<T>(&mut self, key: &T) -> Vec<H>
279 where
280 T: HasRelayIds,
281 {
282 let Some(id) = key.identities().next() else {
283 return Vec::new();
284 };
285
286 self.remove_by_id(id, |val| val.has_all_relay_ids_from(key))
287 }
288}
289
290pub use tor_basic_utils::n_key_list::Error as ListByRelayIdsError;
291pub use tor_basic_utils::n_key_set::Error as ByRelayIdsError;
292
293#[cfg(test)]
294mod test {
295 #![allow(clippy::bool_assert_comparison)]
297 #![allow(clippy::clone_on_copy)]
298 #![allow(clippy::dbg_macro)]
299 #![allow(clippy::mixed_attributes_style)]
300 #![allow(clippy::print_stderr)]
301 #![allow(clippy::print_stdout)]
302 #![allow(clippy::single_char_pattern)]
303 #![allow(clippy::unwrap_used)]
304 #![allow(clippy::unchecked_time_subtraction)]
305 #![allow(clippy::useless_vec)]
306 #![allow(clippy::needless_pass_by_value)]
307 #![allow(clippy::string_slice)] use super::*;
311 use crate::{RelayIds, RelayIdsBuilder};
312
313 fn sort<T: std::cmp::Ord>(i: impl Iterator<Item = T>) -> Vec<T> {
314 let mut v: Vec<_> = i.collect();
315 v.sort();
316 v
317 }
318
319 #[test]
320 fn lookup() {
321 let rsa1: RsaIdentity = (*b"12345678901234567890").into();
322 let rsa2: RsaIdentity = (*b"abcefghijklmnopqrstu").into();
323 let rsa3: RsaIdentity = (*b"abcefghijklmnopQRSTU").into();
324 let ed1: Ed25519Identity = (*b"12345678901234567890123456789012").into();
325 let ed2: Ed25519Identity = (*b"abcefghijklmnopqrstuvwxyzABCDEFG").into();
326 let ed3: Ed25519Identity = (*b"abcefghijklmnopqrstuvwxyz1234567").into();
327
328 let keys1 = RelayIdsBuilder::default()
329 .rsa_identity(rsa1)
330 .ed_identity(ed1)
331 .build()
332 .unwrap();
333
334 let keys2 = RelayIdsBuilder::default()
335 .rsa_identity(rsa2)
336 .ed_identity(ed2)
337 .build()
338 .unwrap();
339
340 let mut set = ByRelayIds::new();
344 set.insert(keys1.clone());
345 set.insert(keys2.clone());
346
347 let mut list = ListByRelayIds::new();
348 list.insert(keys1.clone());
349 list.insert(keys2.clone());
350
351 assert_eq!(set.by_id(&rsa1), Some(&keys1));
353 assert_eq!(set.by_id(&ed1), Some(&keys1));
354 assert_eq!(set.by_id(&rsa2), Some(&keys2));
355 assert_eq!(set.by_id(&ed2), Some(&keys2));
356 assert_eq!(set.by_id(&rsa3), None);
357 assert_eq!(set.by_id(&ed3), None);
358 assert_eq!(sort(list.by_id(&rsa1)), [&keys1]);
359 assert_eq!(sort(list.by_id(&ed1)), [&keys1]);
360 assert_eq!(sort(list.by_id(&rsa2)), [&keys2]);
361 assert_eq!(sort(list.by_id(&ed2)), [&keys2]);
362 assert_eq!(list.by_id(&rsa3).len(), 0);
363 assert_eq!(list.by_id(&ed3).len(), 0);
364
365 assert_eq!(set.by_all_ids(&keys1), Some(&keys1));
367 assert_eq!(set.by_all_ids(&keys2), Some(&keys2));
368 assert_eq!(set.by_all_ids(&RelayIds::empty()), None);
369 assert_eq!(sort(list.by_all_ids(&keys1)), [&keys1]);
370 assert_eq!(sort(list.by_all_ids(&keys2)), [&keys2]);
371 assert!(sort(list.by_all_ids(&RelayIds::empty())).is_empty());
372 {
373 let search = RelayIdsBuilder::default()
374 .rsa_identity(rsa1)
375 .build()
376 .unwrap();
377 assert_eq!(set.by_all_ids(&search), Some(&keys1));
378 assert_eq!(sort(list.by_all_ids(&search)), [&keys1]);
379 }
380 {
381 let search = RelayIdsBuilder::default()
382 .rsa_identity(rsa1)
383 .ed_identity(ed2)
384 .build()
385 .unwrap();
386 assert_eq!(set.by_all_ids(&search), None);
387 assert!(sort(list.by_all_ids(&search)).is_empty());
388 }
389
390 assert_eq!(set.all_overlapping(&keys1), vec![&keys1]);
392 assert_eq!(set.all_overlapping(&keys2), vec![&keys2]);
393 assert_eq!(list.all_overlapping(&keys1), vec![&keys1]);
394 assert_eq!(list.all_overlapping(&keys2), vec![&keys2]);
395 {
396 let search = RelayIdsBuilder::default()
397 .rsa_identity(rsa1)
398 .ed_identity(ed2)
399 .build()
400 .unwrap();
401 let answer = set.all_overlapping(&search);
402 assert_eq!(answer.len(), 2);
403 assert!(answer.contains(&&keys1));
404 assert!(answer.contains(&&keys2));
405 let answer = list.all_overlapping(&search);
406 assert_eq!(answer.len(), 2);
407 assert!(answer.contains(&&keys1));
408 assert!(answer.contains(&&keys2));
409 }
410 {
411 let search = RelayIdsBuilder::default()
412 .rsa_identity(rsa2)
413 .build()
414 .unwrap();
415 assert_eq!(set.all_overlapping(&search), vec![&keys2]);
416 assert_eq!(list.all_overlapping(&search), vec![&keys2]);
417 }
418 {
419 let search = RelayIdsBuilder::default()
420 .rsa_identity(rsa3)
421 .build()
422 .unwrap();
423 assert!(set.all_overlapping(&search).is_empty());
424 assert!(list.all_overlapping(&search).is_empty());
425 }
426 }
427
428 #[test]
429 fn remove_exact() {
430 let rsa1: RsaIdentity = (*b"12345678901234567890").into();
431 let rsa2: RsaIdentity = (*b"abcefghijklmnopqrstu").into();
432 let ed1: Ed25519Identity = (*b"12345678901234567890123456789012").into();
433 let ed2: Ed25519Identity = (*b"abcefghijklmnopqrstuvwxyzABCDEFG").into();
434
435 let keys1 = RelayIdsBuilder::default()
436 .rsa_identity(rsa1)
437 .ed_identity(ed1)
438 .build()
439 .unwrap();
440
441 let keys2 = RelayIdsBuilder::default()
442 .rsa_identity(rsa2)
443 .ed_identity(ed2)
444 .build()
445 .unwrap();
446
447 let mut set = ByRelayIds::new();
451 set.insert(keys1.clone());
452 set.insert(keys2.clone());
453 assert_eq!(set.len(), 2);
454
455 let mut list = ListByRelayIds::new();
456 list.insert(keys1.clone());
457 list.insert(keys2.clone());
458 assert_eq!(list.len(), 2);
459
460 assert_eq!(set.remove_exact(&keys1), Some(keys1.clone()));
461 assert_eq!(set.len(), 1);
462 assert_eq!(list.remove_exact(&keys1), vec![keys1.clone()]);
463 assert_eq!(list.len(), 1);
464
465 {
466 let search = RelayIdsBuilder::default().ed_identity(ed2).build().unwrap();
467
468 assert_eq!(set.remove_exact(&search), None);
470 assert_eq!(set.len(), 1);
471 assert_eq!(list.remove_exact(&search), vec![]);
472 assert_eq!(list.len(), 1);
473
474 let no_match = RelayIdsBuilder::default()
477 .ed_identity(ed2)
478 .rsa_identity(rsa1)
479 .build()
480 .unwrap();
481 assert_eq!(set.remove_by_all_ids(&no_match), None);
482 assert_eq!(set.len(), 1);
483 assert_eq!(list.remove_by_all_ids(&no_match), vec![]);
484 assert_eq!(list.len(), 1);
485
486 assert_eq!(set.remove_by_all_ids(&search), Some(keys2.clone()));
489 assert!(set.is_empty());
490 assert_eq!(list.remove_by_all_ids(&search), vec![keys2.clone()]);
491 assert!(list.is_empty());
492 }
493 }
494
495 #[test]
496 fn all_subset() {
497 let rsa1: RsaIdentity = (*b"12345678901234567890").into();
498 let rsa2: RsaIdentity = (*b"abcefghijklmnopqrstu").into();
499 let ed1: Ed25519Identity = (*b"12345678901234567890123456789012").into();
500
501 let keys1 = RelayIdsBuilder::default()
503 .rsa_identity(rsa1)
504 .ed_identity(ed1)
505 .build()
506 .unwrap();
507
508 let keys2 = RelayIdsBuilder::default()
510 .rsa_identity(rsa2)
511 .build()
512 .unwrap();
513
514 let mut list = ListByRelayIds::new();
515 list.insert(keys1.clone());
516 list.insert(keys2.clone());
517
518 assert_eq!(list.all_subset(&keys1), vec![&keys1]);
519 assert_eq!(list.all_subset(&keys2), vec![&keys2]);
520
521 {
522 let search = RelayIdsBuilder::default()
523 .rsa_identity(rsa1)
524 .build()
525 .unwrap();
526 assert!(list.all_subset(&search).is_empty());
527 }
528
529 {
530 let search = RelayIdsBuilder::default().ed_identity(ed1).build().unwrap();
531 assert!(list.all_subset(&search).is_empty());
532 }
533
534 {
535 let search = RelayIdsBuilder::default()
536 .rsa_identity(rsa2)
537 .build()
538 .unwrap();
539 assert_eq!(list.all_subset(&search), vec![&keys2]);
540 }
541
542 {
543 let search = RelayIdsBuilder::default()
544 .ed_identity(ed1)
545 .rsa_identity(rsa2)
546 .build()
547 .unwrap();
548 assert_eq!(list.all_subset(&search), vec![&keys2]);
549 }
550 }
551
552 #[test]
553 fn list_by_relay_ids() {
554 #[derive(Clone, Debug)]
555 struct ErsatzChannel<T> {
556 val: T,
557 ids: RelayIds,
558 }
559
560 impl<T> ErsatzChannel<T> {
561 fn new(val: T, ids: RelayIds) -> Self {
562 Self { val, ids }
563 }
564 }
565
566 impl<T> HasRelayIds for ErsatzChannel<T> {
567 fn identity(&self, key_type: crate::RelayIdType) -> Option<RelayIdRef<'_>> {
568 self.ids.identity(key_type)
569 }
570 }
571
572 fn ids(
574 rsa: impl Into<Option<RsaIdentity>>,
575 ed: impl Into<Option<Ed25519Identity>>,
576 ) -> RelayIds {
577 let mut ids = RelayIdsBuilder::default();
578 if let Some(rsa) = rsa.into() {
579 ids.rsa_identity(rsa);
580 }
581 if let Some(ed) = ed.into() {
582 ids.ed_identity(ed);
583 }
584 ids.build().unwrap()
585 }
586
587 let rsa_a: RsaIdentity = (*b"12345678901234567890").into();
589 let ed_a: Ed25519Identity = (*b"12345678901234567890123456789012").into();
590
591 let ed_b: Ed25519Identity = (*b"abcefghijklmnopqrstuvwxyzABCDEFG").into();
593 let rsa_b: RsaIdentity = (*b"abcefghijklmnopqrstu").into();
594
595 let channel_a_all = ErsatzChannel::new("channel-a-all", ids(rsa_a, ed_a));
597
598 let channel_a_rsa_only_1 = ErsatzChannel::new("channel-a-rsa-only-1", ids(rsa_a, None));
600
601 let channel_a_rsa_only_2 = ErsatzChannel::new("channel-a-rsa-only-2", ids(rsa_a, None));
604
605 let channel_a_ed_only = ErsatzChannel::new("channel-a-ed-only", ids(None, ed_a));
607
608 let channel_b_all = ErsatzChannel::new("channel-b-all", ids(rsa_b, ed_b));
610
611 let channel_invalid = ErsatzChannel::new("channel-invalid", ids(rsa_a, ed_b));
614
615 let mut list = ListByRelayIds::new();
616 list.insert(channel_a_all.clone());
617 list.insert(channel_a_rsa_only_1.clone());
618 list.insert(channel_a_rsa_only_2.clone());
619 list.insert(channel_a_ed_only.clone());
620 list.insert(channel_b_all.clone());
621 list.insert(channel_invalid.clone());
622
623 assert_eq!(
625 sort(list.by_id(&rsa_a).map(|x| x.val)),
626 [
627 "channel-a-all",
628 "channel-a-rsa-only-1",
629 "channel-a-rsa-only-2",
630 "channel-invalid",
631 ],
632 );
633
634 assert_eq!(
636 sort(list.by_id(&ed_a).map(|x| x.val)),
637 ["channel-a-all", "channel-a-ed-only"],
638 );
639
640 assert_eq!(sort(list.by_id(&rsa_b).map(|x| x.val)), ["channel-b-all"]);
642
643 assert_eq!(
645 sort(list.by_id(&ed_b).map(|x| x.val)),
646 ["channel-b-all", "channel-invalid"],
647 );
648
649 assert_eq!(
651 sort(list.by_all_ids(&ids(rsa_a, ed_a)).map(|x| x.val)),
652 ["channel-a-all"],
653 );
654
655 assert_eq!(
657 sort(list.by_all_ids(&ids(rsa_b, ed_b)).map(|x| x.val)),
658 ["channel-b-all"],
659 );
660
661 assert_eq!(
663 sort(
664 list.all_overlapping(&ids(rsa_a, ed_a))
665 .into_iter()
666 .map(|x| x.val)
667 ),
668 [
669 "channel-a-all",
670 "channel-a-ed-only",
671 "channel-a-rsa-only-1",
672 "channel-a-rsa-only-2",
673 "channel-invalid",
674 ],
675 );
676
677 assert_eq!(
679 sort(
680 list.all_subset(&ids(rsa_a, ed_a))
681 .into_iter()
682 .map(|x| x.val)
683 ),
684 [
685 "channel-a-all",
686 "channel-a-ed-only",
687 "channel-a-rsa-only-1",
688 "channel-a-rsa-only-2",
689 ],
690 );
691
692 assert_eq!(list.by_all_ids(&ids(None, None)).count(), 0);
694 assert!(list.all_overlapping(&ids(None, None)).is_empty());
695 assert!(list.all_subset(&ids(None, None)).is_empty());
696 assert_eq!(
697 sort(
698 list.all_overlapping(&ids(rsa_a, None))
699 .into_iter()
700 .map(|x| x.val)
701 ),
702 sort(list.by_id(&rsa_a).map(|x| x.val)),
703 );
704 assert_eq!(
705 sort(
706 list.all_overlapping(&ids(None, ed_b))
707 .into_iter()
708 .map(|x| x.val)
709 ),
710 sort(list.by_id(&ed_b).map(|x| x.val)),
711 );
712 assert_eq!(
713 sort(list.by_id(&rsa_a).map(|x| x.val)),
714 sort(list.by_rsa(&rsa_a).map(|x| x.val)),
715 );
716 assert_eq!(
717 sort(list.by_id(&ed_a).map(|x| x.val)),
718 sort(list.by_ed25519(&ed_a).map(|x| x.val)),
719 );
720
721 {
723 let mut list = list.clone();
724 assert_eq!(
725 sort(
726 list.remove_exact(&ids(rsa_a, ed_a))
727 .into_iter()
728 .map(|x| x.val)
729 ),
730 ["channel-a-all"],
731 );
732 assert_eq!(list.by_all_ids(&ids(rsa_a, ed_a)).count(), 0);
733 }
734
735 {
737 let mut list = list.clone();
738 assert_eq!(
739 sort(
740 list.remove_exact(&ids(rsa_a, None))
741 .into_iter()
742 .map(|x| x.val)
743 ),
744 ["channel-a-rsa-only-1", "channel-a-rsa-only-2"],
745 );
746 assert_eq!(
747 sort(list.by_all_ids(&ids(rsa_a, None)).map(|x| x.val)),
748 ["channel-a-all", "channel-invalid"],
749 );
750 }
751
752 {
754 let mut list = list.clone();
755 assert_eq!(
756 sort(
757 list.remove_by_all_ids(&ids(rsa_a, None))
758 .into_iter()
759 .map(|x| x.val)
760 ),
761 [
762 "channel-a-all",
763 "channel-a-rsa-only-1",
764 "channel-a-rsa-only-2",
765 "channel-invalid",
766 ],
767 );
768 assert_eq!(list.by_all_ids(&ids(rsa_a, None)).count(), 0);
769 }
770 }
771}