|
1 | 1 | use std::{ |
2 | | - collections::{HashMap, HashSet}, |
| 2 | + collections::{hash_map::Entry, HashMap, HashSet}, |
3 | 3 | sync::Arc, |
4 | 4 | time::Duration, |
5 | 5 | }; |
@@ -429,6 +429,8 @@ pub struct PeerContactBook { |
429 | 429 | /// Contact information for other peers in the network indexed by their |
430 | 430 | /// peer ID. |
431 | 431 | peer_contacts: HashMap<PeerId, Arc<PeerContactInfo>>, |
| 432 | + /// Reverse map when we |
| 433 | + validator_peer_ids: HashMap<Address, HashSet<PeerId>>, |
432 | 434 | /// Only return secure websocket addresses. |
433 | 435 | /// With this flag non secure websocket addresses will be stored (to still have a valid signature of the peer contact) |
434 | 436 | /// but won't be returned when calling `get_addresses` |
@@ -458,24 +460,42 @@ impl PeerContactBook { |
458 | 460 | only_secure_addresses, |
459 | 461 | allow_loopback_addresses, |
460 | 462 | memory_transport, |
| 463 | + validator_peer_ids: HashMap::new(), |
461 | 464 | } |
462 | 465 | } |
463 | 466 |
|
| 467 | + /// Obtain a list of peer ids associated to the given validator address |
| 468 | + pub fn get_validator_peer_ids(&self, validator_address: &Address) -> Vec<PeerId> { |
| 469 | + let Some(peer_ids) = self.validator_peer_ids.get(validator_address) else { |
| 470 | + return vec![]; |
| 471 | + }; |
| 472 | + |
| 473 | + peer_ids.iter().cloned().collect() |
| 474 | + } |
| 475 | + |
464 | 476 | /// Insert a peer contact or update an existing one |
465 | 477 | pub fn insert(&mut self, contact: SignedPeerContact) { |
466 | 478 | // Don't insert our own contact into our peer contacts |
467 | 479 | if contact.peer_id() == self.own_peer_id { |
468 | 480 | return; |
469 | 481 | } |
470 | 482 |
|
| 483 | + let peer_id = contact.peer_id(); |
| 484 | + |
471 | 485 | log::debug!(peer_id = %contact.peer_id(), addresses = ?contact.inner.addresses, "Adding peer contact"); |
472 | 486 | let current_ts = SystemTime::now() |
473 | 487 | .duration_since(SystemTime::UNIX_EPOCH) |
474 | 488 | .unwrap() |
475 | 489 | .as_secs(); |
476 | 490 |
|
| 491 | + if let Some(validator) = &contact.inner.validator_info { |
| 492 | + self.validator_peer_ids |
| 493 | + .entry(validator.validator_address.clone()) |
| 494 | + .or_insert(HashSet::new()) |
| 495 | + .insert(peer_id); |
| 496 | + } |
| 497 | + |
477 | 498 | let info = PeerContactInfo::from(contact); |
478 | | - let peer_id = info.peer_id; |
479 | 499 |
|
480 | 500 | match self.peer_contacts.entry(peer_id) { |
481 | 501 | std::collections::hash_map::Entry::Occupied(mut entry) => { |
@@ -539,6 +559,13 @@ impl PeerContactBook { |
539 | 559 | .peer_contacts |
540 | 560 | .insert(info.peer_id, Arc::clone(&info)) |
541 | 561 | .is_none(); |
| 562 | + if let Some(validator_info) = &info.contact.inner.validator_info { |
| 563 | + self.validator_peer_ids |
| 564 | + .entry(validator_info.validator_address.clone()) |
| 565 | + .or_insert(HashSet::new()) |
| 566 | + .insert(info.peer_id); |
| 567 | + } |
| 568 | + |
542 | 569 | if is_new { |
543 | 570 | log::trace!( |
544 | 571 | peer_id = %info.peer_id, |
@@ -701,16 +728,33 @@ impl PeerContactBook { |
701 | 728 | unix_time, |
702 | 729 | ) { |
703 | 730 | debug!(%peer_id, "Removing peer contact because of old age"); |
704 | | - Some(peer_id) |
| 731 | + Some(( |
| 732 | + peer_id.clone(), |
| 733 | + peer_contact.contact.inner.validator_info.clone(), |
| 734 | + )) |
705 | 735 | } else { |
706 | 736 | None |
707 | 737 | } |
708 | 738 | }) |
709 | | - .cloned() |
710 | | - .collect::<Vec<PeerId>>(); |
| 739 | + .collect::<Vec<(PeerId, Option<ValidatorInfo>)>>(); |
711 | 740 |
|
712 | | - for peer_id in delete_peers { |
| 741 | + for (peer_id, validator_info) in delete_peers { |
713 | 742 | self.peer_contacts.remove(&peer_id); |
| 743 | + if let Some(validator_info) = validator_info { |
| 744 | + match self |
| 745 | + .validator_peer_ids |
| 746 | + .entry(validator_info.validator_address.clone()) |
| 747 | + { |
| 748 | + Entry::Occupied(mut entry) => { |
| 749 | + entry.get_mut().remove(&peer_id); |
| 750 | + |
| 751 | + if entry.get_mut().is_empty() { |
| 752 | + entry.remove(); |
| 753 | + } |
| 754 | + } |
| 755 | + Entry::Vacant(_) => {} |
| 756 | + } |
| 757 | + } |
714 | 758 | } |
715 | 759 | } |
716 | 760 | } |
|
0 commit comments