Skip to main content

saorsa_core/adaptive/
mod.rs

1// Copyright 2024 Saorsa Labs Limited
2//
3// This software is dual-licensed under:
4// - GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)
5// - Commercial License
6//
7// For AGPL-3.0 license, see LICENSE-AGPL-3.0
8// For commercial licensing, contact: david@saorsalabs.com
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under these licenses is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
14//! Adaptive P2P Network Implementation
15//!
16//! This module implements the adaptive P2P network architecture described in the
17//! network documentation, combining multiple distributed systems technologies:
18//! - Secure Kademlia (S/Kademlia) as the foundational DHT layer
19//! - Hyperbolic geometry routing for efficient greedy routing
20//! - Self-Organizing Maps (SOM) for content and capability clustering
21//! - EigenTrust++ for decentralized reputation management
22//! - Adaptive GossipSub for scalable message propagation
23//! - Machine learning systems for routing optimization, caching, and churn prediction
24
25#![allow(missing_docs)]
26
27use async_trait::async_trait;
28use serde::{Deserialize, Serialize};
29
30pub mod beta_distribution;
31pub mod churn;
32pub mod churn_prediction;
33pub mod client;
34pub mod component_builders;
35pub mod coordinator;
36pub mod coordinator_extensions;
37pub mod dht_integration;
38pub mod eviction;
39pub mod gossip;
40pub mod hyperbolic;
41pub mod hyperbolic_enhanced;
42pub mod hyperbolic_greedy;
43// Use crate-level PQC identity instead of local Ed25519 variant
44pub mod learning;
45pub mod monitoring;
46pub mod multi_armed_bandit;
47pub mod performance;
48pub mod q_learning_cache;
49pub mod replication;
50pub mod retrieval;
51pub mod routing;
52pub mod security;
53pub mod som;
54pub mod storage;
55pub mod transport;
56pub mod trust;
57
58// Re-export commonly used types
59pub use crate::identity::NodeIdentity;
60pub use churn::{ChurnConfig, ChurnHandler, NodeMonitor, NodeState, RecoveryManager};
61pub use client::{
62    AdaptiveP2PClient, Client, ClientConfig, ClientProfile, NetworkStats as ClientNetworkStats,
63};
64pub use coordinator::{NetworkConfig, NetworkCoordinator};
65pub use dht_integration::{AdaptiveDHT, KademliaRoutingStrategy};
66pub use eviction::{
67    AdaptiveStrategy, CacheState, EvictionStrategy, EvictionStrategyType, FIFOStrategy,
68    LFUStrategy, LRUStrategy,
69};
70pub use gossip::AdaptiveGossipSub;
71pub use hyperbolic::{HyperbolicRoutingStrategy, HyperbolicSpace};
72pub use hyperbolic_enhanced::{
73    EnhancedHyperbolicCoordinate, EnhancedHyperbolicRoutingStrategy, EnhancedHyperbolicSpace,
74};
75pub use hyperbolic_greedy::{
76    Embedding, EmbeddingConfig, HyperbolicGreedyRouter, embed_snapshot, greedy_next,
77};
78pub use learning::{ChurnPredictor, QLearnCacheManager, ThompsonSampling};
79pub use monitoring::{
80    Alert, AlertManager, DashboardData, MonitoringConfig, MonitoringSystem, NetworkHealth,
81};
82pub use multi_armed_bandit::{
83    MABConfig, MABRoutingStrategy, MultiArmedBandit, RouteDecision, RouteId,
84};
85pub use performance::{
86    BatchProcessor, ConcurrencyLimiter, ConnectionPool, OptimizedSerializer, PerformanceCache,
87    PerformanceConfig,
88};
89pub use q_learning_cache::{
90    AccessInfo, CacheAction, CacheStatistics, QLearnCacheManager as QLearningCacheManager,
91    QLearningConfig, StateVector,
92};
93pub use replication::{ReplicaInfo, ReplicationManager, ReplicationStrategy};
94pub use retrieval::{RetrievalManager, RetrievalStrategy};
95pub use routing::AdaptiveRouter;
96pub use security::{
97    BlacklistManager, EclipseDetector, RateLimiter, SecurityAuditor, SecurityConfig,
98    SecurityManager,
99};
100pub use som::{FeatureExtractor, GridSize, SOMRoutingStrategy, SelfOrganizingMap, SomConfig};
101pub use storage::{ChunkManager, ContentStore, ReplicationConfig, StorageConfig};
102pub use transport::{ConnectionInfo, Transport, TransportManager, TransportProtocol};
103pub use trust::{
104    EigenTrustEngine, MockTrustProvider, NodeStatistics, NodeStatisticsUpdate,
105    TrustBasedRoutingStrategy, TrustRoutingConfig,
106};
107
108/// Result type for adaptive network operations
109pub type Result<T> = std::result::Result<T, AdaptiveNetworkError>;
110
111/// Core error type for the adaptive network
112#[derive(Debug, thiserror::Error)]
113pub enum AdaptiveNetworkError {
114    #[error("Routing error: {0}")]
115    Routing(String),
116
117    #[error("Trust calculation error: {0}")]
118    Trust(String),
119
120    #[error("Learning system error: {0}")]
121    Learning(String),
122
123    #[error("Gossip error: {0}")]
124    Gossip(String),
125
126    #[error("Network error: {0}")]
127    Network(#[from] std::io::Error),
128
129    #[error("Serialization error: {0}")]
130    Serialization(#[from] postcard::Error),
131
132    #[error("Other error: {0}")]
133    Other(String),
134}
135
136impl From<anyhow::Error> for AdaptiveNetworkError {
137    fn from(e: anyhow::Error) -> Self {
138        AdaptiveNetworkError::Network(std::io::Error::other(e.to_string()))
139    }
140}
141
142impl From<crate::error::P2PError> for AdaptiveNetworkError {
143    fn from(e: crate::error::P2PError) -> Self {
144        AdaptiveNetworkError::Network(std::io::Error::other(e.to_string()))
145    }
146}
147
148/// Content hash type used throughout the network
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
150pub struct ContentHash(pub [u8; 32]);
151
152impl ContentHash {
153    /// Create from bytes
154    pub fn from(data: &[u8]) -> Self {
155        let mut hash = [0u8; 32];
156        if data.len() >= 32 {
157            hash.copy_from_slice(&data[..32]);
158        } else {
159            let hashed = blake3::hash(data);
160            hash.copy_from_slice(hashed.as_bytes());
161        }
162        Self(hash)
163    }
164}
165
166/// Network message type
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct NetworkMessage {
169    /// Message ID
170    pub id: String,
171    /// Sender node ID
172    pub sender: NodeId,
173    /// Message content
174    pub content: Vec<u8>,
175    /// Message type
176    pub msg_type: ContentType,
177    /// Timestamp (Unix timestamp in seconds)
178    pub timestamp: u64,
179}
180
181/// Node ID type alias
182pub type NodeId = crate::peer_record::UserId;
183
184/// Node descriptor containing all information about a peer
185#[derive(Debug, Clone)]
186pub struct NodeDescriptor {
187    pub id: NodeId,
188    // PQC-only: ML-DSA public key
189    pub public_key: crate::quantum_crypto::ant_quic_integration::MlDsaPublicKey,
190    pub addresses: Vec<String>,
191    pub hyperbolic: Option<HyperbolicCoordinate>,
192    pub som_position: Option<[f64; 4]>,
193    pub trust: f64,
194    pub capabilities: NodeCapabilities,
195}
196
197/// Hyperbolic coordinate in Poincaré disk model
198#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
199pub struct HyperbolicCoordinate {
200    pub r: f64,     // Radial coordinate [0, 1)
201    pub theta: f64, // Angular coordinate [0, 2π)
202}
203
204/// Node capabilities for resource discovery
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct NodeCapabilities {
207    pub storage: u64,   // GB available
208    pub compute: u64,   // Benchmark score
209    pub bandwidth: u64, // Mbps available
210}
211
212/// Core trait for adaptive P2P network nodes
213#[async_trait]
214pub trait AdaptiveNetworkNode: Send + Sync {
215    /// Join the network using bootstrap nodes
216    async fn join(&mut self, bootstrap: Vec<NodeDescriptor>) -> Result<()>;
217
218    /// Store data with adaptive replication
219    async fn store(&self, data: Vec<u8>) -> Result<ContentHash>;
220
221    /// Retrieve data using parallel strategies
222    async fn retrieve(&self, hash: &ContentHash) -> Result<Vec<u8>>;
223
224    /// Publish a message to a gossip topic
225    async fn publish(&self, topic: &str, message: Vec<u8>) -> Result<()>;
226
227    /// Subscribe to a gossip topic
228    async fn subscribe(
229        &self,
230        topic: &str,
231    ) -> Result<Box<dyn futures::Stream<Item = Vec<u8>> + Send>>;
232
233    /// Get current node information
234    async fn node_info(&self) -> Result<NodeDescriptor>;
235
236    /// Get network statistics
237    async fn network_stats(&self) -> Result<NetworkStats>;
238
239    /// Gracefully shutdown the node
240    async fn shutdown(self) -> Result<()>;
241}
242
243/// Network statistics for monitoring
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct NetworkStats {
246    pub connected_peers: usize,
247    pub routing_success_rate: f64,
248    pub average_trust_score: f64,
249    pub cache_hit_rate: f64,
250    pub churn_rate: f64,
251    pub total_storage: u64,
252    pub total_bandwidth: u64,
253}
254
255/// Routing strategy trait for different routing algorithms
256#[async_trait]
257pub trait RoutingStrategy: Send + Sync {
258    /// Find a path to the target node
259    async fn find_path(&self, target: &NodeId) -> Result<Vec<NodeId>>;
260
261    /// Calculate routing score for a neighbor towards a target
262    fn route_score(&self, neighbor: &NodeId, target: &NodeId) -> f64;
263
264    /// Update routing metrics based on success/failure
265    fn update_metrics(&mut self, path: &[NodeId], success: bool);
266
267    /// Find closest nodes to a content hash
268    async fn find_closest_nodes(
269        &self,
270        content_hash: &ContentHash,
271        _count: usize,
272    ) -> Result<Vec<NodeId>> {
273        // Default implementation uses node ID from content hash
274        let target = NodeId {
275            hash: content_hash.0,
276        };
277        self.find_path(&target).await
278    }
279}
280
281/// Trust provider trait for reputation queries
282///
283/// Provides a unified interface for trust scoring and management.
284/// Implementations should maintain a global trust vector that can be
285/// queried for individual nodes or in aggregate.
286pub trait TrustProvider: Send + Sync {
287    /// Get trust score for a node (0.0 = untrusted, 1.0 = fully trusted)
288    fn get_trust(&self, node: &NodeId) -> f64;
289
290    /// Update trust based on interaction outcome
291    fn update_trust(&self, from: &NodeId, to: &NodeId, success: bool);
292
293    /// Get global trust vector for all known nodes
294    fn get_global_trust(&self) -> std::collections::HashMap<NodeId, f64>;
295
296    /// Remove a node from the trust system
297    fn remove_node(&self, node: &NodeId);
298
299    // Note: get_trust_score was removed as redundant alias for get_trust
300}
301
302/// Learning system trait for adaptive behavior
303#[async_trait]
304pub trait LearningSystem: Send + Sync {
305    /// Select optimal strategy based on context
306    async fn select_strategy(&self, context: &LearningContext) -> StrategyChoice;
307
308    /// Update learning model with outcome
309    async fn update(
310        &mut self,
311        context: &LearningContext,
312        choice: &StrategyChoice,
313        outcome: &Outcome,
314    );
315
316    /// Get current model performance metrics
317    async fn metrics(&self) -> LearningMetrics;
318}
319
320/// Context for learning decisions
321#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct LearningContext {
323    pub content_type: ContentType,
324    pub network_conditions: NetworkConditions,
325    pub historical_performance: Vec<f64>,
326}
327
328/// Content type classification
329#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
330pub enum ContentType {
331    DHTLookup,
332    DataRetrieval,
333    ComputeRequest,
334    RealtimeMessage,
335    DiscoveryProbe,
336}
337
338/// Current network conditions
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct NetworkConditions {
341    pub connected_peers: usize,
342    pub avg_latency_ms: f64,
343    pub churn_rate: f64,
344}
345
346/// Strategy choice made by learning system
347#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
348pub enum StrategyChoice {
349    Kademlia,
350    Hyperbolic,
351    TrustPath,
352    SOMRegion,
353}
354
355/// Outcome of a strategy choice
356#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct Outcome {
358    pub success: bool,
359    pub latency_ms: u64,
360    pub hops: usize,
361}
362
363/// Learning system performance metrics
364#[derive(Debug, Clone, Serialize, Deserialize)]
365pub struct LearningMetrics {
366    pub total_decisions: u64,
367    pub success_rate: f64,
368    pub avg_latency_ms: f64,
369    pub strategy_performance: std::collections::HashMap<StrategyChoice, f64>,
370}
371
372#[cfg(test)]
373mod timestamp_tests;
374
375#[cfg(test)]
376mod coordinator_extensions_tests;
377
378#[cfg(test)]
379mod tests {
380    use super::*;
381
382    #[test]
383    fn test_content_hash_serialization() {
384        let hash = ContentHash([42u8; 32]);
385        let serialized = postcard::to_stdvec(&hash).unwrap();
386        let deserialized: ContentHash = postcard::from_bytes(&serialized).unwrap();
387        assert_eq!(hash, deserialized);
388    }
389
390    #[test]
391    fn test_hyperbolic_coordinate_bounds() {
392        let coord = HyperbolicCoordinate {
393            r: 0.5,
394            theta: std::f64::consts::PI,
395        };
396        assert!(coord.r >= 0.0 && coord.r < 1.0);
397        assert!(coord.theta >= 0.0 && coord.theta < 2.0 * std::f64::consts::PI);
398    }
399}