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: saorsalabs@gmail.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 coordinator;
35pub mod coordinator_extensions;
36pub mod dht_integration;
37pub mod eviction;
38pub mod gossip;
39pub mod hyperbolic;
40pub mod identity;
41pub mod learning;
42pub mod monitoring;
43pub mod multi_armed_bandit;
44pub mod performance;
45pub mod q_learning_cache;
46pub mod replication;
47pub mod retrieval;
48pub mod routing;
49pub mod security;
50pub mod som;
51pub mod storage;
52pub mod transport;
53pub mod trust;
54
55// Re-export commonly used types
56pub use churn::{ChurnConfig, ChurnHandler, NodeMonitor, NodeState, RecoveryManager};
57pub use client::{
58    AdaptiveP2PClient, Client, ClientConfig, ClientProfile, NetworkStats as ClientNetworkStats,
59};
60pub use coordinator::{NetworkConfig, NetworkCoordinator};
61pub use dht_integration::{AdaptiveDHT, KademliaRoutingStrategy};
62pub use eviction::{
63    AdaptiveStrategy, CacheState, EvictionStrategy, EvictionStrategyType, FIFOStrategy,
64    LFUStrategy, LRUStrategy,
65};
66pub use gossip::AdaptiveGossipSub;
67pub use hyperbolic::{HyperbolicRoutingStrategy, HyperbolicSpace};
68pub use identity::{NodeIdentity, ProofOfWork, SignedMessage, StoredIdentity};
69pub use learning::{ChurnPredictor, QLearnCacheManager, ThompsonSampling};
70pub use monitoring::{
71    Alert, AlertManager, DashboardData, MonitoringConfig, MonitoringSystem, NetworkHealth,
72};
73pub use multi_armed_bandit::{
74    MABConfig, MABRoutingStrategy, MultiArmedBandit, RouteDecision, RouteId,
75};
76pub use performance::{
77    BatchProcessor, ConcurrencyLimiter, ConnectionPool, OptimizedSerializer, PerformanceCache,
78    PerformanceConfig,
79};
80pub use q_learning_cache::{
81    AccessInfo, CacheAction, CacheStatistics, QLearnCacheManager as QLearningCacheManager,
82    QLearningConfig, StateVector,
83};
84pub use replication::{ReplicaInfo, ReplicationManager, ReplicationStrategy};
85pub use retrieval::{RetrievalManager, RetrievalStrategy};
86pub use routing::AdaptiveRouter;
87pub use security::{
88    BlacklistManager, EclipseDetector, RateLimiter, SecurityAuditor, SecurityConfig,
89    SecurityManager,
90};
91pub use som::{FeatureExtractor, GridSize, SOMRoutingStrategy, SelfOrganizingMap, SomConfig};
92pub use storage::{ChunkManager, ContentStore, ReplicationConfig, StorageConfig};
93pub use transport::{ConnectionInfo, Transport, TransportManager, TransportProtocol};
94pub use trust::{
95    EigenTrustEngine, MockTrustProvider, NodeStatistics, NodeStatisticsUpdate,
96    TrustBasedRoutingStrategy,
97};
98
99/// Result type for adaptive network operations
100pub type Result<T> = std::result::Result<T, AdaptiveNetworkError>;
101
102/// Core error type for the adaptive network
103#[derive(Debug, thiserror::Error)]
104pub enum AdaptiveNetworkError {
105    #[error("Routing error: {0}")]
106    Routing(String),
107
108    #[error("Trust calculation error: {0}")]
109    Trust(String),
110
111    #[error("Learning system error: {0}")]
112    Learning(String),
113
114    #[error("Gossip error: {0}")]
115    Gossip(String),
116
117    #[error("Network error: {0}")]
118    Network(#[from] std::io::Error),
119
120    #[error("IO error: {0}")]
121    Io(std::io::Error),
122
123    #[error("Serialization error: {0}")]
124    Serialization(#[from] bincode::Error),
125
126    #[error("Other error: {0}")]
127    Other(String),
128}
129
130impl From<anyhow::Error> for AdaptiveNetworkError {
131    fn from(e: anyhow::Error) -> Self {
132        AdaptiveNetworkError::Io(std::io::Error::new(
133            std::io::ErrorKind::Other,
134            e.to_string(),
135        ))
136    }
137}
138
139/// Content hash type used throughout the network
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
141pub struct ContentHash(pub [u8; 32]);
142
143impl ContentHash {
144    /// Create from bytes
145    pub fn from(data: &[u8]) -> Self {
146        let mut hash = [0u8; 32];
147        if data.len() >= 32 {
148            hash.copy_from_slice(&data[..32]);
149        } else {
150            let hashed = blake3::hash(data);
151            hash.copy_from_slice(hashed.as_bytes());
152        }
153        Self(hash)
154    }
155}
156
157/// Network message type
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct NetworkMessage {
160    /// Message ID
161    pub id: String,
162    /// Sender node ID
163    pub sender: NodeId,
164    /// Message content
165    pub content: Vec<u8>,
166    /// Message type
167    pub msg_type: ContentType,
168    /// Timestamp (Unix timestamp in seconds)
169    pub timestamp: u64,
170}
171
172/// Node ID type alias
173pub type NodeId = crate::peer_record::UserId;
174
175/// Node descriptor containing all information about a peer
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct NodeDescriptor {
178    pub id: NodeId,
179    pub public_key: ed25519_dalek::VerifyingKey,
180    pub addresses: Vec<String>,
181    pub hyperbolic: Option<HyperbolicCoordinate>,
182    pub som_position: Option<[f64; 4]>,
183    pub trust: f64,
184    pub capabilities: NodeCapabilities,
185}
186
187/// Hyperbolic coordinate in Poincaré disk model
188#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
189pub struct HyperbolicCoordinate {
190    pub r: f64,     // Radial coordinate [0, 1)
191    pub theta: f64, // Angular coordinate [0, 2π)
192}
193
194/// Node capabilities for resource discovery
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct NodeCapabilities {
197    pub storage: u64,   // GB available
198    pub compute: u64,   // Benchmark score
199    pub bandwidth: u64, // Mbps available
200}
201
202/// Core trait for adaptive P2P network nodes
203#[async_trait]
204pub trait AdaptiveNetworkNode: Send + Sync {
205    /// Join the network using bootstrap nodes
206    async fn join(&mut self, bootstrap: Vec<NodeDescriptor>) -> Result<()>;
207
208    /// Store data with adaptive replication
209    async fn store(&self, data: Vec<u8>) -> Result<ContentHash>;
210
211    /// Retrieve data using parallel strategies
212    async fn retrieve(&self, hash: &ContentHash) -> Result<Vec<u8>>;
213
214    /// Publish a message to a gossip topic
215    async fn publish(&self, topic: &str, message: Vec<u8>) -> Result<()>;
216
217    /// Subscribe to a gossip topic
218    async fn subscribe(
219        &self,
220        topic: &str,
221    ) -> Result<Box<dyn futures::Stream<Item = Vec<u8>> + Send>>;
222
223    /// Get current node information
224    async fn node_info(&self) -> Result<NodeDescriptor>;
225
226    /// Get network statistics
227    async fn network_stats(&self) -> Result<NetworkStats>;
228
229    /// Gracefully shutdown the node
230    async fn shutdown(self) -> Result<()>;
231}
232
233/// Network statistics for monitoring
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct NetworkStats {
236    pub connected_peers: usize,
237    pub routing_success_rate: f64,
238    pub average_trust_score: f64,
239    pub cache_hit_rate: f64,
240    pub churn_rate: f64,
241    pub total_storage: u64,
242    pub total_bandwidth: u64,
243}
244
245/// Routing strategy trait for different routing algorithms
246#[async_trait]
247pub trait RoutingStrategy: Send + Sync {
248    /// Find a path to the target node
249    async fn find_path(&self, target: &NodeId) -> Result<Vec<NodeId>>;
250
251    /// Calculate routing score for a neighbor towards a target
252    fn route_score(&self, neighbor: &NodeId, target: &NodeId) -> f64;
253
254    /// Update routing metrics based on success/failure
255    fn update_metrics(&mut self, path: &[NodeId], success: bool);
256
257    /// Find closest nodes to a content hash
258    async fn find_closest_nodes(
259        &self,
260        content_hash: &ContentHash,
261        _count: usize,
262    ) -> Result<Vec<NodeId>> {
263        // Default implementation uses node ID from content hash
264        let target = NodeId {
265            hash: content_hash.0,
266        };
267        self.find_path(&target).await
268    }
269}
270
271/// Trust provider trait for reputation queries
272pub trait TrustProvider: Send + Sync {
273    /// Get trust score for a node
274    fn get_trust(&self, node: &NodeId) -> f64;
275
276    /// Update trust based on interaction
277    fn update_trust(&self, from: &NodeId, to: &NodeId, success: bool);
278
279    /// Get global trust vector
280    fn get_global_trust(&self) -> std::collections::HashMap<NodeId, f64>;
281
282    /// Remove a node from the trust system
283    fn remove_node(&self, node: &NodeId);
284
285    /// Get trust score (alias for get_trust)
286    fn get_trust_score(&self, node: &NodeId) -> f64 {
287        self.get_trust(node)
288    }
289}
290
291/// Learning system trait for adaptive behavior
292#[async_trait]
293pub trait LearningSystem: Send + Sync {
294    /// Select optimal strategy based on context
295    async fn select_strategy(&self, context: &LearningContext) -> StrategyChoice;
296
297    /// Update learning model with outcome
298    async fn update(
299        &mut self,
300        context: &LearningContext,
301        choice: &StrategyChoice,
302        outcome: &Outcome,
303    );
304
305    /// Get current model performance metrics
306    async fn metrics(&self) -> LearningMetrics;
307}
308
309/// Context for learning decisions
310#[derive(Debug, Clone, Serialize, Deserialize)]
311pub struct LearningContext {
312    pub content_type: ContentType,
313    pub network_conditions: NetworkConditions,
314    pub historical_performance: Vec<f64>,
315}
316
317/// Content type classification
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
319pub enum ContentType {
320    DHTLookup,
321    DataRetrieval,
322    ComputeRequest,
323    RealtimeMessage,
324    DiscoveryProbe,
325}
326
327/// Current network conditions
328#[derive(Debug, Clone, Serialize, Deserialize)]
329pub struct NetworkConditions {
330    pub connected_peers: usize,
331    pub avg_latency_ms: f64,
332    pub churn_rate: f64,
333}
334
335/// Strategy choice made by learning system
336#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
337pub enum StrategyChoice {
338    Kademlia,
339    Hyperbolic,
340    TrustPath,
341    SOMRegion,
342}
343
344/// Outcome of a strategy choice
345#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct Outcome {
347    pub success: bool,
348    pub latency_ms: u64,
349    pub hops: usize,
350}
351
352/// Learning system performance metrics
353#[derive(Debug, Clone, Serialize, Deserialize)]
354pub struct LearningMetrics {
355    pub total_decisions: u64,
356    pub success_rate: f64,
357    pub avg_latency_ms: f64,
358    pub strategy_performance: std::collections::HashMap<StrategyChoice, f64>,
359}
360
361#[cfg(test)]
362mod timestamp_tests;
363
364#[cfg(test)]
365mod tests {
366    use super::*;
367
368    #[test]
369    fn test_content_hash_serialization() {
370        let hash = ContentHash([42u8; 32]);
371        let serialized = bincode::serialize(&hash).unwrap();
372        let deserialized: ContentHash = bincode::deserialize(&serialized).unwrap();
373        assert_eq!(hash, deserialized);
374    }
375
376    #[test]
377    fn test_hyperbolic_coordinate_bounds() {
378        let coord = HyperbolicCoordinate {
379            r: 0.5,
380            theta: std::f64::consts::PI,
381        };
382        assert!(coord.r >= 0.0 && coord.r < 1.0);
383        assert!(coord.theta >= 0.0 && coord.theta < 2.0 * std::f64::consts::PI);
384    }
385}