1use crate::PeerId;
21use crate::quantum_crypto::ant_quic_integration::{
22 MlDsaPublicKey, MlDsaSecretKey, MlDsaSignature, ml_dsa_sign, ml_dsa_verify,
23};
24use anyhow::{Result, anyhow};
25use serde::{Deserialize, Serialize};
26use sha2::{Digest, Sha256};
27use std::collections::HashMap;
28use std::fmt::Debug;
29use std::net::{Ipv4Addr, Ipv6Addr};
30use std::time::{Duration, SystemTime, UNIX_EPOCH};
31
32use std::sync::Arc;
33
34pub trait NodeIpAddress: Debug + Clone + Send + Sync + 'static {
40 fn octets_vec(&self) -> Vec<u8>;
42}
43
44impl NodeIpAddress for Ipv6Addr {
45 fn octets_vec(&self) -> Vec<u8> {
46 self.octets().to_vec()
47 }
48}
49
50impl NodeIpAddress for Ipv4Addr {
51 fn octets_vec(&self) -> Vec<u8> {
52 self.octets().to_vec()
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct GenericIpNodeID<A: NodeIpAddress> {
66 pub node_id: Vec<u8>,
68 pub ip_addr: A,
70 pub public_key: Vec<u8>,
72 pub signature: Vec<u8>,
74 pub timestamp_secs: u64,
76 pub salt: Vec<u8>,
78}
79
80impl<A: NodeIpAddress> GenericIpNodeID<A> {
81 const SIGNATURE_LENGTH: usize = 3309;
83
84 pub fn generate(ip_addr: A, secret: &MlDsaSecretKey, public: &MlDsaPublicKey) -> Result<Self> {
86 let mut rng = rand::thread_rng();
87 let mut salt = vec![0u8; 16];
88 rand::RngCore::fill_bytes(&mut rng, &mut salt);
89
90 let timestamp = SystemTime::now();
91 let timestamp_secs = timestamp.duration_since(UNIX_EPOCH)?.as_secs();
92 let public_key = public.as_bytes().to_vec();
93 let ip_octets = ip_addr.octets_vec();
94
95 let node_id = Self::compute_node_id(&ip_octets, &public_key, &salt, timestamp_secs);
97
98 let message_to_sign = Self::build_message(&ip_octets, &public_key, &salt, timestamp_secs);
100 let sig = ml_dsa_sign(secret, &message_to_sign)
101 .map_err(|e| anyhow!("ML-DSA sign failed: {:?}", e))?;
102 let signature = sig.0.to_vec();
103
104 Ok(Self {
105 node_id,
106 ip_addr,
107 public_key,
108 signature,
109 timestamp_secs,
110 salt,
111 })
112 }
113
114 pub fn verify(&self) -> Result<bool> {
116 let ip_octets = self.ip_addr.octets_vec();
117
118 let expected_node_id = Self::compute_node_id(
120 &ip_octets,
121 &self.public_key,
122 &self.salt,
123 self.timestamp_secs,
124 );
125
126 if expected_node_id != self.node_id {
127 return Ok(false);
128 }
129
130 let public_key = MlDsaPublicKey::from_bytes(&self.public_key)
132 .map_err(|e| anyhow!("Invalid ML-DSA public key: {:?}", e))?;
133
134 if self.signature.len() != Self::SIGNATURE_LENGTH {
135 return Ok(false);
136 }
137
138 let mut sig_bytes = [0u8; 3309];
139 sig_bytes.copy_from_slice(&self.signature);
140 let signature = MlDsaSignature(Box::new(sig_bytes));
141
142 let message_to_verify = Self::build_message(
143 &ip_octets,
144 &self.public_key,
145 &self.salt,
146 self.timestamp_secs,
147 );
148
149 let ok = ml_dsa_verify(&public_key, &message_to_verify, &signature)
150 .map_err(|e| anyhow!("ML-DSA verify error: {:?}", e))?;
151 Ok(ok)
152 }
153
154 pub fn age_secs(&self) -> u64 {
156 let now = SystemTime::now()
157 .duration_since(UNIX_EPOCH)
158 .map(|d| d.as_secs())
159 .unwrap_or(0);
160 now.saturating_sub(self.timestamp_secs)
161 }
162
163 pub fn is_expired(&self, max_age: Duration) -> bool {
165 self.age_secs() > max_age.as_secs()
166 }
167
168 #[inline]
171 fn compute_node_id(
172 ip_octets: &[u8],
173 public_key: &[u8],
174 salt: &[u8],
175 timestamp_secs: u64,
176 ) -> Vec<u8> {
177 let mut hasher = Sha256::new();
178 hasher.update(ip_octets);
179 hasher.update(public_key);
180 hasher.update(salt);
181 hasher.update(timestamp_secs.to_le_bytes());
182 hasher.finalize().to_vec()
183 }
184
185 #[inline]
186 fn build_message(
187 ip_octets: &[u8],
188 public_key: &[u8],
189 salt: &[u8],
190 timestamp_secs: u64,
191 ) -> Vec<u8> {
192 let mut message = Vec::with_capacity(ip_octets.len() + public_key.len() + salt.len() + 8);
193 message.extend_from_slice(ip_octets);
194 message.extend_from_slice(public_key);
195 message.extend_from_slice(salt);
196 message.extend_from_slice(×tamp_secs.to_le_bytes());
197 message
198 }
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct IPv6NodeID {
208 pub node_id: Vec<u8>,
210 pub ipv6_addr: Ipv6Addr,
212 pub public_key: Vec<u8>,
214 pub signature: Vec<u8>,
216 pub timestamp_secs: u64,
218 pub salt: Vec<u8>,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct IPDiversityConfig {
225 pub max_nodes_per_64: usize,
228 pub max_nodes_per_48: usize,
230 pub max_nodes_per_32: usize,
232
233 pub max_nodes_per_ipv4_32: usize,
236 pub max_nodes_per_ipv4_24: usize,
238 pub max_nodes_per_ipv4_16: usize,
240
241 pub max_per_ip_cap: usize,
244 pub max_network_fraction: f64,
246
247 pub max_nodes_per_asn: usize,
250 pub enable_geolocation_check: bool,
252 pub min_geographic_diversity: usize,
254}
255
256#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
258pub struct IPAnalysis {
259 pub subnet_64: Ipv6Addr,
261 pub subnet_48: Ipv6Addr,
263 pub subnet_32: Ipv6Addr,
265 pub asn: Option<u32>,
267 pub country: Option<String>,
269 pub is_hosting_provider: bool,
271 pub is_vpn_provider: bool,
273 pub reputation_score: f64,
275}
276
277#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
279pub struct IPv4Analysis {
280 pub ip_addr: Ipv4Addr,
282 pub subnet_24: Ipv4Addr,
284 pub subnet_16: Ipv4Addr,
286 pub subnet_8: Ipv4Addr,
288 pub asn: Option<u32>,
290 pub country: Option<String>,
292 pub is_hosting_provider: bool,
294 pub is_vpn_provider: bool,
296 pub reputation_score: f64,
298}
299
300#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
302pub enum UnifiedIPAnalysis {
303 IPv4(IPv4Analysis),
305 IPv6(IPAnalysis),
307}
308
309#[derive(Debug, Clone)]
311pub struct NodeReputation {
312 pub peer_id: PeerId,
314 pub response_rate: f64,
316 pub response_time: Duration,
318 pub consistency_score: f64,
320 pub uptime_estimate: Duration,
322 pub routing_accuracy: f64,
324 pub last_seen: SystemTime,
326 pub interaction_count: u64,
328}
329
330impl Default for IPDiversityConfig {
331 fn default() -> Self {
332 Self {
333 max_nodes_per_64: 1,
335 max_nodes_per_48: 3,
336 max_nodes_per_32: 10,
337 max_nodes_per_ipv4_32: 1, max_nodes_per_ipv4_24: 3, max_nodes_per_ipv4_16: 10, max_per_ip_cap: 50, max_network_fraction: 0.005, max_nodes_per_asn: 20,
346 enable_geolocation_check: true,
347 min_geographic_diversity: 3,
348 }
349 }
350}
351
352impl IPDiversityConfig {
353 #[must_use]
364 pub fn testnet() -> Self {
365 Self {
366 max_nodes_per_64: 100, max_nodes_per_48: 500, max_nodes_per_32: 1000, max_nodes_per_ipv4_32: 100, max_nodes_per_ipv4_24: 500, max_nodes_per_ipv4_16: 1000, max_per_ip_cap: 100, max_network_fraction: 0.1, max_nodes_per_asn: 5000, enable_geolocation_check: false, min_geographic_diversity: 1, }
382 }
383
384 #[must_use]
389 pub fn permissive() -> Self {
390 Self {
391 max_nodes_per_64: usize::MAX,
393 max_nodes_per_48: usize::MAX,
394 max_nodes_per_32: usize::MAX,
395 max_nodes_per_ipv4_32: usize::MAX,
397 max_nodes_per_ipv4_24: usize::MAX,
398 max_nodes_per_ipv4_16: usize::MAX,
399 max_per_ip_cap: usize::MAX,
401 max_network_fraction: 1.0, max_nodes_per_asn: usize::MAX,
404 enable_geolocation_check: false,
405 min_geographic_diversity: 0,
406 }
407 }
408
409 #[must_use]
411 pub fn is_relaxed(&self) -> bool {
412 self.max_nodes_per_asn > 100 || !self.enable_geolocation_check
413 }
414}
415
416impl IPv6NodeID {
417 pub fn generate(
421 ipv6_addr: Ipv6Addr,
422 secret: &MlDsaSecretKey,
423 public: &MlDsaPublicKey,
424 ) -> Result<Self> {
425 let generic = GenericIpNodeID::generate(ipv6_addr, secret, public)?;
426 Ok(Self::from_generic(generic))
427 }
428
429 pub fn verify(&self) -> Result<bool> {
431 self.to_generic().verify()
432 }
433
434 pub fn extract_subnet_64(&self) -> Ipv6Addr {
436 let octets = self.ipv6_addr.octets();
437 let mut subnet = [0u8; 16];
438 subnet[..8].copy_from_slice(&octets[..8]);
439 Ipv6Addr::from(subnet)
440 }
441
442 pub fn extract_subnet_48(&self) -> Ipv6Addr {
444 let octets = self.ipv6_addr.octets();
445 let mut subnet = [0u8; 16];
446 subnet[..6].copy_from_slice(&octets[..6]);
447 Ipv6Addr::from(subnet)
448 }
449
450 pub fn extract_subnet_32(&self) -> Ipv6Addr {
452 let octets = self.ipv6_addr.octets();
453 let mut subnet = [0u8; 16];
454 subnet[..4].copy_from_slice(&octets[..4]);
455 Ipv6Addr::from(subnet)
456 }
457
458 fn from_generic(g: GenericIpNodeID<Ipv6Addr>) -> Self {
461 Self {
462 node_id: g.node_id,
463 ipv6_addr: g.ip_addr,
464 public_key: g.public_key,
465 signature: g.signature,
466 timestamp_secs: g.timestamp_secs,
467 salt: g.salt,
468 }
469 }
470
471 fn to_generic(&self) -> GenericIpNodeID<Ipv6Addr> {
472 GenericIpNodeID {
473 node_id: self.node_id.clone(),
474 ip_addr: self.ipv6_addr,
475 public_key: self.public_key.clone(),
476 signature: self.signature.clone(),
477 timestamp_secs: self.timestamp_secs,
478 salt: self.salt.clone(),
479 }
480 }
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
486pub struct IPv4NodeID {
487 pub node_id: Vec<u8>,
489 pub ipv4_addr: Ipv4Addr,
491 pub public_key: Vec<u8>,
493 pub signature: Vec<u8>,
495 pub timestamp_secs: u64,
497 pub salt: Vec<u8>,
499}
500
501impl IPv4NodeID {
502 pub fn generate(
506 ipv4_addr: Ipv4Addr,
507 secret: &MlDsaSecretKey,
508 public: &MlDsaPublicKey,
509 ) -> Result<Self> {
510 let generic = GenericIpNodeID::generate(ipv4_addr, secret, public)?;
511 Ok(Self::from_generic(generic))
512 }
513
514 pub fn verify(&self) -> Result<bool> {
516 self.to_generic().verify()
517 }
518
519 pub fn extract_subnet_24(&self) -> Ipv4Addr {
521 let octets = self.ipv4_addr.octets();
522 Ipv4Addr::new(octets[0], octets[1], octets[2], 0)
523 }
524
525 pub fn extract_subnet_16(&self) -> Ipv4Addr {
527 let octets = self.ipv4_addr.octets();
528 Ipv4Addr::new(octets[0], octets[1], 0, 0)
529 }
530
531 pub fn extract_subnet_8(&self) -> Ipv4Addr {
533 let octets = self.ipv4_addr.octets();
534 Ipv4Addr::new(octets[0], 0, 0, 0)
535 }
536
537 pub fn age_secs(&self) -> u64 {
539 self.to_generic().age_secs()
540 }
541
542 pub fn is_expired(&self, max_age: Duration) -> bool {
544 self.to_generic().is_expired(max_age)
545 }
546
547 fn from_generic(g: GenericIpNodeID<Ipv4Addr>) -> Self {
550 Self {
551 node_id: g.node_id,
552 ipv4_addr: g.ip_addr,
553 public_key: g.public_key,
554 signature: g.signature,
555 timestamp_secs: g.timestamp_secs,
556 salt: g.salt,
557 }
558 }
559
560 fn to_generic(&self) -> GenericIpNodeID<Ipv4Addr> {
561 GenericIpNodeID {
562 node_id: self.node_id.clone(),
563 ip_addr: self.ipv4_addr,
564 public_key: self.public_key.clone(),
565 signature: self.signature.clone(),
566 timestamp_secs: self.timestamp_secs,
567 salt: self.salt.clone(),
568 }
569 }
570}
571
572#[derive(Debug)]
574pub struct IPDiversityEnforcer {
575 config: IPDiversityConfig,
576 subnet_64_counts: HashMap<Ipv6Addr, usize>,
578 subnet_48_counts: HashMap<Ipv6Addr, usize>,
579 subnet_32_counts: HashMap<Ipv6Addr, usize>,
580 ipv4_32_counts: HashMap<Ipv4Addr, usize>, ipv4_24_counts: HashMap<Ipv4Addr, usize>, ipv4_16_counts: HashMap<Ipv4Addr, usize>, asn_counts: HashMap<u32, usize>,
586 country_counts: HashMap<String, usize>,
587 geo_provider: Option<Arc<dyn GeoProvider + Send + Sync>>,
588 network_size: usize,
590}
591
592impl IPDiversityEnforcer {
593 pub fn new(config: IPDiversityConfig) -> Self {
595 Self {
596 config,
597 subnet_64_counts: HashMap::new(),
599 subnet_48_counts: HashMap::new(),
600 subnet_32_counts: HashMap::new(),
601 ipv4_32_counts: HashMap::new(),
603 ipv4_24_counts: HashMap::new(),
604 ipv4_16_counts: HashMap::new(),
605 asn_counts: HashMap::new(),
607 country_counts: HashMap::new(),
608 geo_provider: None,
609 network_size: 0,
610 }
611 }
612
613 pub fn with_geo_provider(
615 config: IPDiversityConfig,
616 provider: Arc<dyn GeoProvider + Send + Sync>,
617 ) -> Self {
618 let mut s = Self::new(config);
619 s.geo_provider = Some(provider);
620 s
621 }
622
623 pub fn analyze_ip(&self, ipv6_addr: Ipv6Addr) -> Result<IPAnalysis> {
625 let subnet_64 = Self::extract_subnet_prefix(ipv6_addr, 64);
626 let subnet_48 = Self::extract_subnet_prefix(ipv6_addr, 48);
627 let subnet_32 = Self::extract_subnet_prefix(ipv6_addr, 32);
628
629 let (asn, country, is_hosting_provider, is_vpn_provider) =
631 if let Some(p) = &self.geo_provider {
632 let info = p.lookup(ipv6_addr);
633 (
634 info.asn,
635 info.country,
636 info.is_hosting_provider,
637 info.is_vpn_provider,
638 )
639 } else {
640 (None, None, false, false)
641 };
642
643 let reputation_score = 0.5;
645
646 Ok(IPAnalysis {
647 subnet_64,
648 subnet_48,
649 subnet_32,
650 asn,
651 country,
652 is_hosting_provider,
653 is_vpn_provider,
654 reputation_score,
655 })
656 }
657
658 pub fn can_accept_node(&self, ip_analysis: &IPAnalysis) -> bool {
660 let (limit_64, limit_48, limit_32, limit_asn) =
662 if ip_analysis.is_hosting_provider || ip_analysis.is_vpn_provider {
663 (
665 std::cmp::max(1, self.config.max_nodes_per_64 / 2),
666 std::cmp::max(1, self.config.max_nodes_per_48 / 2),
667 std::cmp::max(1, self.config.max_nodes_per_32 / 2),
668 std::cmp::max(1, self.config.max_nodes_per_asn / 2),
669 )
670 } else {
671 (
673 self.config.max_nodes_per_64,
674 self.config.max_nodes_per_48,
675 self.config.max_nodes_per_32,
676 self.config.max_nodes_per_asn,
677 )
678 };
679
680 if let Some(&count) = self.subnet_64_counts.get(&ip_analysis.subnet_64)
682 && count >= limit_64
683 {
684 return false;
685 }
686
687 if let Some(&count) = self.subnet_48_counts.get(&ip_analysis.subnet_48)
689 && count >= limit_48
690 {
691 return false;
692 }
693
694 if let Some(&count) = self.subnet_32_counts.get(&ip_analysis.subnet_32)
696 && count >= limit_32
697 {
698 return false;
699 }
700
701 if let Some(asn) = ip_analysis.asn
703 && let Some(&count) = self.asn_counts.get(&asn)
704 && count >= limit_asn
705 {
706 return false;
707 }
708
709 true
710 }
711
712 pub fn add_node(&mut self, ip_analysis: &IPAnalysis) -> Result<()> {
714 if !self.can_accept_node(ip_analysis) {
715 return Err(anyhow!("IP diversity limits exceeded"));
716 }
717
718 *self
720 .subnet_64_counts
721 .entry(ip_analysis.subnet_64)
722 .or_insert(0) += 1;
723 *self
724 .subnet_48_counts
725 .entry(ip_analysis.subnet_48)
726 .or_insert(0) += 1;
727 *self
728 .subnet_32_counts
729 .entry(ip_analysis.subnet_32)
730 .or_insert(0) += 1;
731
732 if let Some(asn) = ip_analysis.asn {
733 *self.asn_counts.entry(asn).or_insert(0) += 1;
734 }
735
736 if let Some(ref country) = ip_analysis.country {
737 *self.country_counts.entry(country.clone()).or_insert(0) += 1;
738 }
739
740 Ok(())
741 }
742
743 pub fn remove_node(&mut self, ip_analysis: &IPAnalysis) {
745 if let Some(count) = self.subnet_64_counts.get_mut(&ip_analysis.subnet_64) {
746 *count = count.saturating_sub(1);
747 if *count == 0 {
748 self.subnet_64_counts.remove(&ip_analysis.subnet_64);
749 }
750 }
751
752 if let Some(count) = self.subnet_48_counts.get_mut(&ip_analysis.subnet_48) {
753 *count = count.saturating_sub(1);
754 if *count == 0 {
755 self.subnet_48_counts.remove(&ip_analysis.subnet_48);
756 }
757 }
758
759 if let Some(count) = self.subnet_32_counts.get_mut(&ip_analysis.subnet_32) {
760 *count = count.saturating_sub(1);
761 if *count == 0 {
762 self.subnet_32_counts.remove(&ip_analysis.subnet_32);
763 }
764 }
765
766 if let Some(asn) = ip_analysis.asn
767 && let Some(count) = self.asn_counts.get_mut(&asn)
768 {
769 *count = count.saturating_sub(1);
770 if *count == 0 {
771 self.asn_counts.remove(&asn);
772 }
773 }
774
775 if let Some(ref country) = ip_analysis.country
776 && let Some(count) = self.country_counts.get_mut(country)
777 {
778 *count = count.saturating_sub(1);
779 if *count == 0 {
780 self.country_counts.remove(country);
781 }
782 }
783 }
784
785 pub fn extract_subnet_prefix(addr: Ipv6Addr, prefix_len: u8) -> Ipv6Addr {
787 let octets = addr.octets();
788 let mut subnet = [0u8; 16];
789
790 let bytes_to_copy = (prefix_len / 8) as usize;
791 let remaining_bits = prefix_len % 8;
792
793 if bytes_to_copy < 16 {
795 subnet[..bytes_to_copy].copy_from_slice(&octets[..bytes_to_copy]);
796 } else {
797 subnet.copy_from_slice(&octets);
798 }
799
800 if remaining_bits > 0 && bytes_to_copy < 16 {
802 let mask = 0xFF << (8 - remaining_bits);
803 subnet[bytes_to_copy] = octets[bytes_to_copy] & mask;
804 }
805
806 Ipv6Addr::from(subnet)
807 }
808
809 pub fn get_diversity_stats(&self) -> DiversityStats {
811 DiversityStats {
812 total_64_subnets: self.subnet_64_counts.len(),
813 total_48_subnets: self.subnet_48_counts.len(),
814 total_32_subnets: self.subnet_32_counts.len(),
815 total_asns: self.asn_counts.len(),
816 total_countries: self.country_counts.len(),
817 max_nodes_per_64: self.subnet_64_counts.values().max().copied().unwrap_or(0),
818 max_nodes_per_48: self.subnet_48_counts.values().max().copied().unwrap_or(0),
819 max_nodes_per_32: self.subnet_32_counts.values().max().copied().unwrap_or(0),
820 total_ipv4_32: self.ipv4_32_counts.len(),
822 total_ipv4_24_subnets: self.ipv4_24_counts.len(),
823 total_ipv4_16_subnets: self.ipv4_16_counts.len(),
824 max_nodes_per_ipv4_32: self.ipv4_32_counts.values().max().copied().unwrap_or(0),
825 max_nodes_per_ipv4_24: self.ipv4_24_counts.values().max().copied().unwrap_or(0),
826 max_nodes_per_ipv4_16: self.ipv4_16_counts.values().max().copied().unwrap_or(0),
827 }
828 }
829
830 pub fn set_network_size(&mut self, size: usize) {
834 self.network_size = size;
835 }
836
837 pub fn get_network_size(&self) -> usize {
839 self.network_size
840 }
841
842 pub fn get_per_ip_limit(&self) -> usize {
845 let fraction_limit =
846 (self.network_size as f64 * self.config.max_network_fraction).floor() as usize;
847 std::cmp::min(self.config.max_per_ip_cap, std::cmp::max(1, fraction_limit))
848 }
849
850 fn extract_ipv4_subnet_24(addr: Ipv4Addr) -> Ipv4Addr {
852 let octets = addr.octets();
853 Ipv4Addr::new(octets[0], octets[1], octets[2], 0)
854 }
855
856 fn extract_ipv4_subnet_16(addr: Ipv4Addr) -> Ipv4Addr {
858 let octets = addr.octets();
859 Ipv4Addr::new(octets[0], octets[1], 0, 0)
860 }
861
862 fn extract_ipv4_subnet_8(addr: Ipv4Addr) -> Ipv4Addr {
864 let octets = addr.octets();
865 Ipv4Addr::new(octets[0], 0, 0, 0)
866 }
867
868 pub fn analyze_ipv4(&self, ipv4_addr: Ipv4Addr) -> Result<IPv4Analysis> {
870 let subnet_24 = Self::extract_ipv4_subnet_24(ipv4_addr);
871 let subnet_16 = Self::extract_ipv4_subnet_16(ipv4_addr);
872 let subnet_8 = Self::extract_ipv4_subnet_8(ipv4_addr);
873
874 let asn = None;
877 let country = None;
878 let is_hosting_provider = false;
879 let is_vpn_provider = false;
880 let reputation_score = 0.5;
881
882 Ok(IPv4Analysis {
883 ip_addr: ipv4_addr,
884 subnet_24,
885 subnet_16,
886 subnet_8,
887 asn,
888 country,
889 is_hosting_provider,
890 is_vpn_provider,
891 reputation_score,
892 })
893 }
894
895 pub fn analyze_unified(&self, addr: std::net::IpAddr) -> Result<UnifiedIPAnalysis> {
897 match addr {
898 std::net::IpAddr::V4(ipv4) => {
899 let analysis = self.analyze_ipv4(ipv4)?;
900 Ok(UnifiedIPAnalysis::IPv4(analysis))
901 }
902 std::net::IpAddr::V6(ipv6) => {
903 let analysis = self.analyze_ip(ipv6)?;
904 Ok(UnifiedIPAnalysis::IPv6(analysis))
905 }
906 }
907 }
908
909 pub fn can_accept_unified(&self, analysis: &UnifiedIPAnalysis) -> bool {
911 match analysis {
912 UnifiedIPAnalysis::IPv4(ipv4_analysis) => self.can_accept_ipv4(ipv4_analysis),
913 UnifiedIPAnalysis::IPv6(ipv6_analysis) => self.can_accept_node(ipv6_analysis),
914 }
915 }
916
917 fn can_accept_ipv4(&self, analysis: &IPv4Analysis) -> bool {
919 let per_ip_limit = self.get_per_ip_limit();
921
922 let limit_32 = per_ip_limit;
924 let limit_24 = std::cmp::min(self.config.max_nodes_per_ipv4_24, per_ip_limit * 3);
925 let limit_16 = std::cmp::min(self.config.max_nodes_per_ipv4_16, per_ip_limit * 10);
926
927 let (limit_32, limit_24, limit_16) =
929 if analysis.is_hosting_provider || analysis.is_vpn_provider {
930 (
931 std::cmp::max(1, limit_32 / 2),
932 std::cmp::max(1, limit_24 / 2),
933 std::cmp::max(1, limit_16 / 2),
934 )
935 } else {
936 (limit_32, limit_24, limit_16)
937 };
938
939 if let Some(&count) = self.ipv4_32_counts.get(&analysis.ip_addr)
941 && count >= limit_32
942 {
943 return false;
944 }
945
946 if let Some(&count) = self.ipv4_24_counts.get(&analysis.subnet_24)
948 && count >= limit_24
949 {
950 return false;
951 }
952
953 if let Some(&count) = self.ipv4_16_counts.get(&analysis.subnet_16)
955 && count >= limit_16
956 {
957 return false;
958 }
959
960 if let Some(asn) = analysis.asn
962 && let Some(&count) = self.asn_counts.get(&asn)
963 && count >= self.config.max_nodes_per_asn
964 {
965 return false;
966 }
967
968 true
969 }
970
971 pub fn add_unified(&mut self, analysis: &UnifiedIPAnalysis) -> Result<()> {
973 match analysis {
974 UnifiedIPAnalysis::IPv4(ipv4_analysis) => self.add_ipv4(ipv4_analysis),
975 UnifiedIPAnalysis::IPv6(ipv6_analysis) => self.add_node(ipv6_analysis),
976 }
977 }
978
979 fn add_ipv4(&mut self, analysis: &IPv4Analysis) -> Result<()> {
981 if !self.can_accept_ipv4(analysis) {
982 return Err(anyhow!("IPv4 diversity limits exceeded"));
983 }
984
985 *self.ipv4_32_counts.entry(analysis.ip_addr).or_insert(0) += 1;
987 *self.ipv4_24_counts.entry(analysis.subnet_24).or_insert(0) += 1;
988 *self.ipv4_16_counts.entry(analysis.subnet_16).or_insert(0) += 1;
989
990 if let Some(asn) = analysis.asn {
991 *self.asn_counts.entry(asn).or_insert(0) += 1;
992 }
993
994 if let Some(ref country) = analysis.country {
995 *self.country_counts.entry(country.clone()).or_insert(0) += 1;
996 }
997
998 Ok(())
999 }
1000
1001 pub fn remove_unified(&mut self, analysis: &UnifiedIPAnalysis) {
1003 match analysis {
1004 UnifiedIPAnalysis::IPv4(ipv4_analysis) => self.remove_ipv4(ipv4_analysis),
1005 UnifiedIPAnalysis::IPv6(ipv6_analysis) => self.remove_node(ipv6_analysis),
1006 }
1007 }
1008
1009 fn remove_ipv4(&mut self, analysis: &IPv4Analysis) {
1011 if let Some(count) = self.ipv4_32_counts.get_mut(&analysis.ip_addr) {
1012 *count = count.saturating_sub(1);
1013 if *count == 0 {
1014 self.ipv4_32_counts.remove(&analysis.ip_addr);
1015 }
1016 }
1017
1018 if let Some(count) = self.ipv4_24_counts.get_mut(&analysis.subnet_24) {
1019 *count = count.saturating_sub(1);
1020 if *count == 0 {
1021 self.ipv4_24_counts.remove(&analysis.subnet_24);
1022 }
1023 }
1024
1025 if let Some(count) = self.ipv4_16_counts.get_mut(&analysis.subnet_16) {
1026 *count = count.saturating_sub(1);
1027 if *count == 0 {
1028 self.ipv4_16_counts.remove(&analysis.subnet_16);
1029 }
1030 }
1031
1032 if let Some(asn) = analysis.asn
1033 && let Some(count) = self.asn_counts.get_mut(&asn)
1034 {
1035 *count = count.saturating_sub(1);
1036 if *count == 0 {
1037 self.asn_counts.remove(&asn);
1038 }
1039 }
1040
1041 if let Some(ref country) = analysis.country
1042 && let Some(count) = self.country_counts.get_mut(country)
1043 {
1044 *count = count.saturating_sub(1);
1045 if *count == 0 {
1046 self.country_counts.remove(country);
1047 }
1048 }
1049 }
1050}
1051
1052#[cfg(test)]
1053impl IPDiversityEnforcer {
1054 pub fn config(&self) -> &IPDiversityConfig {
1055 &self.config
1056 }
1057}
1058
1059pub trait GeoProvider: std::fmt::Debug {
1061 fn lookup(&self, ip: Ipv6Addr) -> GeoInfo;
1062}
1063
1064#[derive(Debug, Clone)]
1066pub struct GeoInfo {
1067 pub asn: Option<u32>,
1068 pub country: Option<String>,
1069 pub is_hosting_provider: bool,
1070 pub is_vpn_provider: bool,
1071}
1072
1073#[derive(Debug)]
1075pub struct CachedGeoProvider<P: GeoProvider> {
1076 inner: P,
1077 cache: parking_lot::RwLock<HashMap<Ipv6Addr, GeoInfo>>,
1078}
1079
1080impl<P: GeoProvider> CachedGeoProvider<P> {
1081 pub fn new(inner: P) -> Self {
1082 Self {
1083 inner,
1084 cache: parking_lot::RwLock::new(HashMap::new()),
1085 }
1086 }
1087}
1088
1089impl<P: GeoProvider> GeoProvider for CachedGeoProvider<P> {
1090 fn lookup(&self, ip: Ipv6Addr) -> GeoInfo {
1091 if let Some(info) = self.cache.read().get(&ip).cloned() {
1092 return info;
1093 }
1094 let info = self.inner.lookup(ip);
1095 self.cache.write().insert(ip, info.clone());
1096 info
1097 }
1098}
1099
1100#[derive(Debug)]
1102pub struct StubGeoProvider;
1103impl GeoProvider for StubGeoProvider {
1104 fn lookup(&self, _ip: Ipv6Addr) -> GeoInfo {
1105 GeoInfo {
1106 asn: None,
1107 country: None,
1108 is_hosting_provider: false,
1109 is_vpn_provider: false,
1110 }
1111 }
1112}
1113
1114#[derive(Debug, Clone, Serialize, Deserialize)]
1116pub struct DiversityStats {
1117 pub total_64_subnets: usize,
1120 pub total_48_subnets: usize,
1122 pub total_32_subnets: usize,
1124 pub max_nodes_per_64: usize,
1126 pub max_nodes_per_48: usize,
1128 pub max_nodes_per_32: usize,
1130
1131 pub total_ipv4_32: usize,
1134 pub total_ipv4_24_subnets: usize,
1136 pub total_ipv4_16_subnets: usize,
1138 pub max_nodes_per_ipv4_32: usize,
1140 pub max_nodes_per_ipv4_24: usize,
1142 pub max_nodes_per_ipv4_16: usize,
1144
1145 pub total_asns: usize,
1148 pub total_countries: usize,
1150}
1151
1152#[derive(Debug)]
1154pub struct ReputationManager {
1155 reputations: HashMap<PeerId, NodeReputation>,
1156 reputation_decay: f64,
1157 min_reputation: f64,
1158}
1159
1160impl ReputationManager {
1161 pub fn new(reputation_decay: f64, min_reputation: f64) -> Self {
1163 Self {
1164 reputations: HashMap::new(),
1165 reputation_decay,
1166 min_reputation,
1167 }
1168 }
1169
1170 pub fn get_reputation(&self, peer_id: &PeerId) -> Option<&NodeReputation> {
1172 self.reputations.get(peer_id)
1173 }
1174
1175 pub fn update_reputation(&mut self, peer_id: &PeerId, success: bool, response_time: Duration) {
1177 let reputation =
1178 self.reputations
1179 .entry(peer_id.clone())
1180 .or_insert_with(|| NodeReputation {
1181 peer_id: peer_id.clone(),
1182 response_rate: 0.5,
1183 response_time: Duration::from_millis(500),
1184 consistency_score: 0.5,
1185 uptime_estimate: Duration::from_secs(0),
1186 routing_accuracy: 0.5,
1187 last_seen: SystemTime::now(),
1188 interaction_count: 0,
1189 });
1190
1191 let alpha = 0.3; if success {
1195 reputation.response_rate = reputation.response_rate * (1.0 - alpha) + alpha;
1196 } else {
1197 reputation.response_rate *= 1.0 - alpha;
1198 }
1199
1200 let response_time_ms = response_time.as_millis() as f64;
1202 let current_response_ms = reputation.response_time.as_millis() as f64;
1203 let new_response_ms = current_response_ms * (1.0 - alpha) + response_time_ms * alpha;
1204 reputation.response_time = Duration::from_millis(new_response_ms as u64);
1205
1206 reputation.last_seen = SystemTime::now();
1207 reputation.interaction_count += 1;
1208 }
1209
1210 pub fn apply_decay(&mut self) {
1212 let now = SystemTime::now();
1213
1214 self.reputations.retain(|_, reputation| {
1215 if let Ok(elapsed) = now.duration_since(reputation.last_seen) {
1216 let decay_factor = (-elapsed.as_secs_f64() / 3600.0 * self.reputation_decay).exp();
1218 reputation.response_rate *= decay_factor;
1219 reputation.consistency_score *= decay_factor;
1220 reputation.routing_accuracy *= decay_factor;
1221
1222 reputation.response_rate > self.min_reputation / 10.0
1224 } else {
1225 true
1226 }
1227 });
1228 }
1229}
1230
1231#[cfg(test)]
1234mod tests {
1235 use super::*;
1236 use crate::quantum_crypto::generate_ml_dsa_keypair;
1237
1238 fn create_test_keypair() -> (MlDsaPublicKey, MlDsaSecretKey) {
1239 generate_ml_dsa_keypair().expect("Failed to generate test keypair")
1240 }
1241
1242 fn create_test_ipv6() -> Ipv6Addr {
1243 Ipv6Addr::new(
1244 0x2001, 0xdb8, 0x85a3, 0x0000, 0x0000, 0x8a2e, 0x0370, 0x7334,
1245 )
1246 }
1247
1248 fn create_test_diversity_config() -> IPDiversityConfig {
1249 IPDiversityConfig {
1250 max_nodes_per_64: 1,
1252 max_nodes_per_48: 3,
1253 max_nodes_per_32: 10,
1254 max_nodes_per_ipv4_32: 1,
1256 max_nodes_per_ipv4_24: 3,
1257 max_nodes_per_ipv4_16: 10,
1258 max_per_ip_cap: 50,
1260 max_network_fraction: 0.005,
1261 max_nodes_per_asn: 20,
1263 enable_geolocation_check: true,
1264 min_geographic_diversity: 3,
1265 }
1266 }
1267
1268 #[test]
1269 fn test_ipv6_node_id_generation() -> Result<()> {
1270 let (public_key, secret_key) = create_test_keypair();
1271 let ipv6_addr = create_test_ipv6();
1272
1273 let node_id = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1274
1275 assert_eq!(node_id.ipv6_addr, ipv6_addr);
1276 assert_eq!(node_id.public_key.len(), 1952); assert_eq!(node_id.signature.len(), 3309); assert_eq!(node_id.node_id.len(), 32); assert_eq!(node_id.salt.len(), 16);
1280 assert!(node_id.timestamp_secs > 0);
1281
1282 Ok(())
1283 }
1284
1285 #[test]
1286 fn test_ipv6_node_id_verification() -> Result<()> {
1287 let (public_key, secret_key) = create_test_keypair();
1288 let ipv6_addr = create_test_ipv6();
1289
1290 let node_id = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1291 let is_valid = node_id.verify()?;
1292
1293 assert!(is_valid);
1294
1295 Ok(())
1296 }
1297
1298 #[test]
1299 fn test_ipv6_node_id_verification_fails_with_wrong_data() -> Result<()> {
1300 let (public_key, secret_key) = create_test_keypair();
1301 let ipv6_addr = create_test_ipv6();
1302
1303 let mut node_id = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1304
1305 node_id.node_id[0] ^= 0xFF;
1307 let is_valid = node_id.verify()?;
1308 assert!(!is_valid);
1309
1310 let mut node_id2 = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1312 node_id2.signature = vec![0u8; 32]; let is_valid2 = node_id2.verify()?;
1314 assert!(!is_valid2);
1315
1316 let mut node_id3 = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1318 node_id3.public_key = vec![0u8; 16]; let is_valid3 = node_id3.verify()?;
1320 assert!(!is_valid3);
1321
1322 Ok(())
1323 }
1324
1325 #[test]
1326 fn test_ipv6_subnet_extraction() -> Result<()> {
1327 let (public_key, secret_key) = create_test_keypair();
1328 let ipv6_addr = Ipv6Addr::new(
1329 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1330 );
1331
1332 let node_id = IPv6NodeID::generate(ipv6_addr, &secret_key, &public_key)?;
1333
1334 let subnet_64 = node_id.extract_subnet_64();
1336 let expected_64 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1234, 0, 0, 0, 0);
1337 assert_eq!(subnet_64, expected_64);
1338
1339 let subnet_48 = node_id.extract_subnet_48();
1341 let expected_48 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0, 0, 0, 0, 0);
1342 assert_eq!(subnet_48, expected_48);
1343
1344 let subnet_32 = node_id.extract_subnet_32();
1346 let expected_32 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
1347 assert_eq!(subnet_32, expected_32);
1348
1349 Ok(())
1350 }
1351
1352 fn create_test_ipv4() -> Ipv4Addr {
1355 Ipv4Addr::new(192, 168, 1, 100)
1356 }
1357
1358 #[test]
1359 fn test_ipv4_node_id_generation() -> Result<()> {
1360 let (public_key, secret_key) = create_test_keypair();
1361 let ipv4_addr = create_test_ipv4();
1362
1363 let node_id = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1364
1365 assert_eq!(node_id.ipv4_addr, ipv4_addr);
1366 assert_eq!(node_id.public_key.len(), 1952); assert_eq!(node_id.signature.len(), 3309); assert_eq!(node_id.node_id.len(), 32); assert_eq!(node_id.salt.len(), 16);
1370 assert!(node_id.timestamp_secs > 0);
1371
1372 Ok(())
1373 }
1374
1375 #[test]
1376 fn test_ipv4_node_id_verification() -> Result<()> {
1377 let (public_key, secret_key) = create_test_keypair();
1378 let ipv4_addr = create_test_ipv4();
1379
1380 let node_id = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1381 let is_valid = node_id.verify()?;
1382
1383 assert!(is_valid);
1384
1385 Ok(())
1386 }
1387
1388 #[test]
1389 fn test_ipv4_node_id_verification_fails_with_wrong_data() -> Result<()> {
1390 let (public_key, secret_key) = create_test_keypair();
1391 let ipv4_addr = create_test_ipv4();
1392
1393 let mut node_id = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1394
1395 node_id.node_id[0] ^= 0xFF;
1397 let is_valid = node_id.verify()?;
1398 assert!(!is_valid);
1399
1400 let mut node_id2 = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1402 node_id2.signature = vec![0u8; 32]; let is_valid2 = node_id2.verify()?;
1404 assert!(!is_valid2);
1405
1406 let mut node_id3 = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1408 node_id3.public_key = vec![0u8; 16]; let is_valid3 = node_id3.verify()?;
1410 assert!(!is_valid3);
1411
1412 Ok(())
1413 }
1414
1415 #[test]
1416 fn test_ipv4_subnet_extraction() -> Result<()> {
1417 let (public_key, secret_key) = create_test_keypair();
1418 let ipv4_addr = Ipv4Addr::new(192, 168, 42, 100);
1419
1420 let node_id = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1421
1422 let subnet_24 = node_id.extract_subnet_24();
1424 let expected_24 = Ipv4Addr::new(192, 168, 42, 0);
1425 assert_eq!(subnet_24, expected_24);
1426
1427 let subnet_16 = node_id.extract_subnet_16();
1429 let expected_16 = Ipv4Addr::new(192, 168, 0, 0);
1430 assert_eq!(subnet_16, expected_16);
1431
1432 let subnet_8 = node_id.extract_subnet_8();
1434 let expected_8 = Ipv4Addr::new(192, 0, 0, 0);
1435 assert_eq!(subnet_8, expected_8);
1436
1437 Ok(())
1438 }
1439
1440 #[test]
1441 fn test_ipv4_node_id_age() -> Result<()> {
1442 let (public_key, secret_key) = create_test_keypair();
1443 let ipv4_addr = create_test_ipv4();
1444
1445 let node_id = IPv4NodeID::generate(ipv4_addr, &secret_key, &public_key)?;
1446
1447 assert!(node_id.age_secs() < 5);
1449
1450 assert!(!node_id.is_expired(Duration::from_secs(3600)));
1452
1453 assert!(!node_id.is_expired(Duration::from_secs(0)));
1456
1457 Ok(())
1458 }
1459
1460 #[test]
1461 fn test_ipv4_different_addresses_different_node_ids() -> Result<()> {
1462 let (public_key, secret_key) = create_test_keypair();
1463 let addr1 = Ipv4Addr::new(192, 168, 1, 1);
1464 let addr2 = Ipv4Addr::new(192, 168, 1, 2);
1465
1466 let node_id1 = IPv4NodeID::generate(addr1, &secret_key, &public_key)?;
1467 let node_id2 = IPv4NodeID::generate(addr2, &secret_key, &public_key)?;
1468
1469 assert_ne!(node_id1.node_id, node_id2.node_id);
1471
1472 assert!(node_id1.verify()?);
1474 assert!(node_id2.verify()?);
1475
1476 Ok(())
1477 }
1478
1479 #[test]
1482 fn test_ip_diversity_config_default() {
1483 let config = IPDiversityConfig::default();
1484
1485 assert_eq!(config.max_nodes_per_64, 1);
1486 assert_eq!(config.max_nodes_per_48, 3);
1487 assert_eq!(config.max_nodes_per_32, 10);
1488 assert_eq!(config.max_nodes_per_asn, 20);
1489 assert!(config.enable_geolocation_check);
1490 assert_eq!(config.min_geographic_diversity, 3);
1491 }
1492
1493 #[test]
1494 fn test_ip_diversity_enforcer_creation() {
1495 let config = create_test_diversity_config();
1496 let enforcer = IPDiversityEnforcer::new(config.clone());
1497
1498 assert_eq!(enforcer.config.max_nodes_per_64, config.max_nodes_per_64);
1499 assert_eq!(enforcer.subnet_64_counts.len(), 0);
1500 assert_eq!(enforcer.subnet_48_counts.len(), 0);
1501 assert_eq!(enforcer.subnet_32_counts.len(), 0);
1502 }
1503
1504 #[test]
1505 fn test_ip_analysis() -> Result<()> {
1506 let config = create_test_diversity_config();
1507 let enforcer = IPDiversityEnforcer::new(config);
1508
1509 let ipv6_addr = create_test_ipv6();
1510 let analysis = enforcer.analyze_ip(ipv6_addr)?;
1511
1512 assert_eq!(
1513 analysis.subnet_64,
1514 IPDiversityEnforcer::extract_subnet_prefix(ipv6_addr, 64)
1515 );
1516 assert_eq!(
1517 analysis.subnet_48,
1518 IPDiversityEnforcer::extract_subnet_prefix(ipv6_addr, 48)
1519 );
1520 assert_eq!(
1521 analysis.subnet_32,
1522 IPDiversityEnforcer::extract_subnet_prefix(ipv6_addr, 32)
1523 );
1524 assert!(analysis.asn.is_none()); assert!(analysis.country.is_none()); assert!(!analysis.is_hosting_provider);
1527 assert!(!analysis.is_vpn_provider);
1528 assert_eq!(analysis.reputation_score, 0.5);
1529
1530 Ok(())
1531 }
1532
1533 #[test]
1534 fn test_can_accept_node_basic() -> Result<()> {
1535 let config = create_test_diversity_config();
1536 let enforcer = IPDiversityEnforcer::new(config);
1537
1538 let ipv6_addr = create_test_ipv6();
1539 let analysis = enforcer.analyze_ip(ipv6_addr)?;
1540
1541 assert!(enforcer.can_accept_node(&analysis));
1543
1544 Ok(())
1545 }
1546
1547 #[test]
1548 fn test_add_and_remove_node() -> Result<()> {
1549 let config = create_test_diversity_config();
1550 let mut enforcer = IPDiversityEnforcer::new(config);
1551
1552 let ipv6_addr = create_test_ipv6();
1553 let analysis = enforcer.analyze_ip(ipv6_addr)?;
1554
1555 enforcer.add_node(&analysis)?;
1557 assert_eq!(enforcer.subnet_64_counts.get(&analysis.subnet_64), Some(&1));
1558 assert_eq!(enforcer.subnet_48_counts.get(&analysis.subnet_48), Some(&1));
1559 assert_eq!(enforcer.subnet_32_counts.get(&analysis.subnet_32), Some(&1));
1560
1561 enforcer.remove_node(&analysis);
1563 assert_eq!(enforcer.subnet_64_counts.get(&analysis.subnet_64), None);
1564 assert_eq!(enforcer.subnet_48_counts.get(&analysis.subnet_48), None);
1565 assert_eq!(enforcer.subnet_32_counts.get(&analysis.subnet_32), None);
1566
1567 Ok(())
1568 }
1569
1570 #[test]
1571 fn test_diversity_limits_enforcement() -> Result<()> {
1572 let config = create_test_diversity_config();
1573 let mut enforcer = IPDiversityEnforcer::new(config);
1574
1575 let ipv6_addr1 = Ipv6Addr::new(
1576 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1577 );
1578 let ipv6_addr2 = Ipv6Addr::new(
1579 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7335,
1580 ); let analysis1 = enforcer.analyze_ip(ipv6_addr1)?;
1583 let analysis2 = enforcer.analyze_ip(ipv6_addr2)?;
1584
1585 assert!(enforcer.can_accept_node(&analysis1));
1587 enforcer.add_node(&analysis1)?;
1588
1589 assert!(!enforcer.can_accept_node(&analysis2));
1591
1592 let result = enforcer.add_node(&analysis2);
1594 assert!(result.is_err());
1595 assert!(
1596 result
1597 .unwrap_err()
1598 .to_string()
1599 .contains("IP diversity limits exceeded")
1600 );
1601
1602 Ok(())
1603 }
1604
1605 #[test]
1606 fn test_hosting_provider_stricter_limits() -> Result<()> {
1607 let config = IPDiversityConfig {
1608 max_nodes_per_64: 4, max_nodes_per_48: 8,
1610 ..create_test_diversity_config()
1611 };
1612 let mut enforcer = IPDiversityEnforcer::new(config);
1613
1614 let ipv6_addr = create_test_ipv6();
1615 let mut analysis = enforcer.analyze_ip(ipv6_addr)?;
1616 analysis.is_hosting_provider = true;
1617
1618 assert!(enforcer.can_accept_node(&analysis));
1620 enforcer.add_node(&analysis)?;
1621
1622 let ipv6_addr2 = Ipv6Addr::new(
1624 0x2001, 0xdb8, 0x85a3, 0x0000, 0x0000, 0x8a2e, 0x0370, 0x7335,
1625 );
1626 let mut analysis2 = enforcer.analyze_ip(ipv6_addr2)?;
1627 analysis2.is_hosting_provider = true;
1628 analysis2.subnet_64 = analysis.subnet_64; assert!(enforcer.can_accept_node(&analysis2));
1631 enforcer.add_node(&analysis2)?;
1632
1633 let ipv6_addr3 = Ipv6Addr::new(
1635 0x2001, 0xdb8, 0x85a3, 0x0000, 0x0000, 0x8a2e, 0x0370, 0x7336,
1636 );
1637 let mut analysis3 = enforcer.analyze_ip(ipv6_addr3)?;
1638 analysis3.is_hosting_provider = true;
1639 analysis3.subnet_64 = analysis.subnet_64; assert!(!enforcer.can_accept_node(&analysis3));
1642
1643 Ok(())
1644 }
1645
1646 #[test]
1647 fn test_diversity_stats() -> Result<()> {
1648 let config = create_test_diversity_config();
1649 let mut enforcer = IPDiversityEnforcer::new(config);
1650
1651 let addresses = [
1653 Ipv6Addr::new(
1654 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1655 ),
1656 Ipv6Addr::new(
1657 0x2001, 0xdb8, 0x85a4, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1658 ), Ipv6Addr::new(
1660 0x2002, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1661 ), ];
1663
1664 for addr in addresses {
1665 let analysis = enforcer.analyze_ip(addr)?;
1666 enforcer.add_node(&analysis)?;
1667 }
1668
1669 let stats = enforcer.get_diversity_stats();
1670 assert_eq!(stats.total_64_subnets, 3);
1671 assert_eq!(stats.total_48_subnets, 3);
1672 assert_eq!(stats.total_32_subnets, 2); assert_eq!(stats.max_nodes_per_64, 1);
1674 assert_eq!(stats.max_nodes_per_48, 1);
1675 assert_eq!(stats.max_nodes_per_32, 2); Ok(())
1678 }
1679
1680 #[test]
1681 fn test_extract_subnet_prefix() {
1682 let addr = Ipv6Addr::new(
1683 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x7334,
1684 );
1685
1686 let prefix_64 = IPDiversityEnforcer::extract_subnet_prefix(addr, 64);
1688 let expected_64 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1234, 0, 0, 0, 0);
1689 assert_eq!(prefix_64, expected_64);
1690
1691 let prefix_48 = IPDiversityEnforcer::extract_subnet_prefix(addr, 48);
1693 let expected_48 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0, 0, 0, 0, 0);
1694 assert_eq!(prefix_48, expected_48);
1695
1696 let prefix_32 = IPDiversityEnforcer::extract_subnet_prefix(addr, 32);
1698 let expected_32 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
1699 assert_eq!(prefix_32, expected_32);
1700
1701 let prefix_56 = IPDiversityEnforcer::extract_subnet_prefix(addr, 56);
1703 let expected_56 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1200, 0, 0, 0, 0);
1704 assert_eq!(prefix_56, expected_56);
1705
1706 let prefix_128 = IPDiversityEnforcer::extract_subnet_prefix(addr, 128);
1708 assert_eq!(prefix_128, addr);
1709 }
1710
1711 #[test]
1712 fn test_reputation_manager_creation() {
1713 let manager = ReputationManager::new(0.1, 0.1);
1714 assert_eq!(manager.reputation_decay, 0.1);
1715 assert_eq!(manager.min_reputation, 0.1);
1716 assert_eq!(manager.reputations.len(), 0);
1717 }
1718
1719 #[test]
1720 fn test_reputation_get_nonexistent() {
1721 let manager = ReputationManager::new(0.1, 0.1);
1722 let peer_id = "test_peer".to_string();
1723
1724 let reputation = manager.get_reputation(&peer_id);
1725 assert!(reputation.is_none());
1726 }
1727
1728 #[test]
1729 fn test_reputation_update_creates_entry() {
1730 let mut manager = ReputationManager::new(0.1, 0.1);
1731 let peer_id = "test_peer".to_string();
1732
1733 manager.update_reputation(&peer_id, true, Duration::from_millis(100));
1734
1735 let reputation = manager.get_reputation(&peer_id);
1736 assert!(reputation.is_some());
1737
1738 let rep = reputation.unwrap();
1739 assert_eq!(rep.peer_id, peer_id);
1740 assert!(rep.response_rate > 0.5); assert_eq!(rep.interaction_count, 1);
1742 }
1743
1744 #[test]
1745 fn test_reputation_update_success_improves_rate() {
1746 let mut manager = ReputationManager::new(0.1, 0.1);
1747 let peer_id = "test_peer".to_string();
1748
1749 for _ in 0..15 {
1751 manager.update_reputation(&peer_id, true, Duration::from_millis(100));
1752 }
1753
1754 let reputation = manager.get_reputation(&peer_id).unwrap();
1755 assert!(reputation.response_rate > 0.85); assert_eq!(reputation.interaction_count, 15);
1757 }
1758
1759 #[test]
1760 fn test_reputation_update_failure_decreases_rate() {
1761 let mut manager = ReputationManager::new(0.1, 0.1);
1762 let peer_id = "test_peer".to_string();
1763
1764 for _ in 0..15 {
1766 manager.update_reputation(&peer_id, false, Duration::from_millis(1000));
1767 }
1768
1769 let reputation = manager.get_reputation(&peer_id).unwrap();
1770 assert!(reputation.response_rate < 0.15); assert_eq!(reputation.interaction_count, 15);
1772 }
1773
1774 #[test]
1775 fn test_reputation_response_time_tracking() {
1776 let mut manager = ReputationManager::new(0.1, 0.1);
1777 let peer_id = "test_peer".to_string();
1778
1779 manager.update_reputation(&peer_id, true, Duration::from_millis(200));
1781
1782 let reputation = manager.get_reputation(&peer_id).unwrap();
1783 assert!(reputation.response_time.as_millis() > 200);
1785 assert!(reputation.response_time.as_millis() < 500);
1786 }
1787
1788 #[test]
1789 fn test_reputation_decay() {
1790 let mut manager = ReputationManager::new(1.0, 0.01); let peer_id = "test_peer".to_string();
1792
1793 manager.update_reputation(&peer_id, true, Duration::from_millis(100));
1795
1796 if let Some(reputation) = manager.reputations.get_mut(&peer_id) {
1798 reputation.last_seen = SystemTime::now() - Duration::from_secs(7200); }
1800
1801 let original_rate = manager.get_reputation(&peer_id).unwrap().response_rate;
1802
1803 manager.apply_decay();
1805
1806 let reputation = manager.get_reputation(&peer_id);
1807 if let Some(rep) = reputation {
1808 assert!(rep.response_rate < original_rate);
1810 } }
1812
1813 #[test]
1814 fn test_reputation_decay_removes_low_reputation() {
1815 let mut manager = ReputationManager::new(0.1, 0.5); let peer_id = "test_peer".to_string();
1817
1818 for _ in 0..10 {
1820 manager.update_reputation(&peer_id, false, Duration::from_millis(1000));
1821 }
1822
1823 if let Some(reputation) = manager.reputations.get_mut(&peer_id) {
1825 reputation.last_seen = SystemTime::now() - Duration::from_secs(3600); reputation.response_rate = 0.01; }
1828
1829 manager.apply_decay();
1831
1832 assert!(manager.get_reputation(&peer_id).is_none());
1834 }
1835
1836 #[test]
1837 fn test_security_types_keypair() {
1838 let (public_key, secret_key) =
1839 generate_ml_dsa_keypair().expect("Failed to generate keypair");
1840
1841 let public_key_bytes = public_key.as_bytes();
1842 assert_eq!(public_key_bytes.len(), 1952); let message = b"test message";
1845 let signature = ml_dsa_sign(&secret_key, message).expect("Failed to sign message");
1846 assert_eq!(signature.as_bytes().len(), 3309); assert!(ml_dsa_verify(&public_key, message, &signature).is_ok());
1850 }
1851
1852 #[test]
1853 fn test_node_reputation_structure() {
1854 let peer_id = "test_peer".to_string();
1855 let reputation = NodeReputation {
1856 peer_id: peer_id.clone(),
1857 response_rate: 0.85,
1858 response_time: Duration::from_millis(150),
1859 consistency_score: 0.9,
1860 uptime_estimate: Duration::from_secs(86400),
1861 routing_accuracy: 0.8,
1862 last_seen: SystemTime::now(),
1863 interaction_count: 42,
1864 };
1865
1866 assert_eq!(reputation.peer_id, peer_id);
1867 assert_eq!(reputation.response_rate, 0.85);
1868 assert_eq!(reputation.response_time, Duration::from_millis(150));
1869 assert_eq!(reputation.consistency_score, 0.9);
1870 assert_eq!(reputation.uptime_estimate, Duration::from_secs(86400));
1871 assert_eq!(reputation.routing_accuracy, 0.8);
1872 assert_eq!(reputation.interaction_count, 42);
1873 }
1874
1875 #[test]
1876 fn test_ip_analysis_structure() {
1877 let analysis = IPAnalysis {
1878 subnet_64: Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1234, 0, 0, 0, 0),
1879 subnet_48: Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0, 0, 0, 0, 0),
1880 subnet_32: Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0),
1881 asn: Some(64512),
1882 country: Some("US".to_string()),
1883 is_hosting_provider: true,
1884 is_vpn_provider: false,
1885 reputation_score: 0.75,
1886 };
1887
1888 assert_eq!(analysis.asn, Some(64512));
1889 assert_eq!(analysis.country, Some("US".to_string()));
1890 assert!(analysis.is_hosting_provider);
1891 assert!(!analysis.is_vpn_provider);
1892 assert_eq!(analysis.reputation_score, 0.75);
1893 }
1894
1895 #[test]
1896 fn test_diversity_stats_structure() {
1897 let stats = DiversityStats {
1898 total_64_subnets: 100,
1900 total_48_subnets: 50,
1901 total_32_subnets: 25,
1902 max_nodes_per_64: 1,
1903 max_nodes_per_48: 3,
1904 max_nodes_per_32: 10,
1905 total_ipv4_32: 80,
1907 total_ipv4_24_subnets: 40,
1908 total_ipv4_16_subnets: 20,
1909 max_nodes_per_ipv4_32: 1,
1910 max_nodes_per_ipv4_24: 3,
1911 max_nodes_per_ipv4_16: 10,
1912 total_asns: 15,
1914 total_countries: 8,
1915 };
1916
1917 assert_eq!(stats.total_64_subnets, 100);
1919 assert_eq!(stats.total_48_subnets, 50);
1920 assert_eq!(stats.total_32_subnets, 25);
1921 assert_eq!(stats.max_nodes_per_64, 1);
1922 assert_eq!(stats.max_nodes_per_48, 3);
1923 assert_eq!(stats.max_nodes_per_32, 10);
1924 assert_eq!(stats.total_ipv4_32, 80);
1926 assert_eq!(stats.total_ipv4_24_subnets, 40);
1927 assert_eq!(stats.total_ipv4_16_subnets, 20);
1928 assert_eq!(stats.max_nodes_per_ipv4_32, 1);
1929 assert_eq!(stats.max_nodes_per_ipv4_24, 3);
1930 assert_eq!(stats.max_nodes_per_ipv4_16, 10);
1931 assert_eq!(stats.total_asns, 15);
1933 assert_eq!(stats.total_countries, 8);
1934 }
1935
1936 #[test]
1937 fn test_multiple_same_subnet_nodes() -> Result<()> {
1938 let config = IPDiversityConfig {
1939 max_nodes_per_64: 3, max_nodes_per_48: 5,
1941 max_nodes_per_32: 10,
1942 ..create_test_diversity_config()
1943 };
1944 let mut enforcer = IPDiversityEnforcer::new(config);
1945
1946 let _base_addr = Ipv6Addr::new(
1947 0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 0x0000,
1948 );
1949
1950 for i in 1..=3 {
1952 let addr = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, i);
1953 let analysis = enforcer.analyze_ip(addr)?;
1954 assert!(enforcer.can_accept_node(&analysis));
1955 enforcer.add_node(&analysis)?;
1956 }
1957
1958 let addr4 = Ipv6Addr::new(0x2001, 0xdb8, 0x85a3, 0x1234, 0x5678, 0x8a2e, 0x0370, 4);
1960 let analysis4 = enforcer.analyze_ip(addr4)?;
1961 assert!(!enforcer.can_accept_node(&analysis4));
1962
1963 let stats = enforcer.get_diversity_stats();
1964 assert_eq!(stats.total_64_subnets, 1);
1965 assert_eq!(stats.max_nodes_per_64, 3);
1966
1967 Ok(())
1968 }
1969
1970 #[test]
1971 fn test_asn_and_country_tracking() -> Result<()> {
1972 let config = create_test_diversity_config();
1973 let mut enforcer = IPDiversityEnforcer::new(config);
1974
1975 let ipv6_addr = create_test_ipv6();
1977 let mut analysis = enforcer.analyze_ip(ipv6_addr)?;
1978 analysis.asn = Some(64512);
1979 analysis.country = Some("US".to_string());
1980
1981 enforcer.add_node(&analysis)?;
1982
1983 assert_eq!(enforcer.asn_counts.get(&64512), Some(&1));
1984 assert_eq!(enforcer.country_counts.get("US"), Some(&1));
1985
1986 enforcer.remove_node(&analysis);
1988 assert!(!enforcer.asn_counts.contains_key(&64512));
1989 assert!(!enforcer.country_counts.contains_key("US"));
1990
1991 Ok(())
1992 }
1993
1994 #[test]
1995 fn test_reputation_mixed_interactions() {
1996 let mut manager = ReputationManager::new(0.1, 0.1);
1997 let peer_id = "test_peer".to_string();
1998
1999 for i in 0..15 {
2001 let success = i % 3 != 0; manager.update_reputation(&peer_id, success, Duration::from_millis(100 + i * 10));
2003 }
2004
2005 let reputation = manager.get_reputation(&peer_id).unwrap();
2006 assert!(reputation.response_rate > 0.55);
2009 assert!(reputation.response_rate < 0.85);
2010 assert_eq!(reputation.interaction_count, 15);
2011 }
2012}