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::other(e.to_string()))
133    }
134}
135
136/// Content hash type used throughout the network
137#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
138pub struct ContentHash(pub [u8; 32]);
139
140impl ContentHash {
141    /// Create from bytes
142    pub fn from(data: &[u8]) -> Self {
143        let mut hash = [0u8; 32];
144        if data.len() >= 32 {
145            hash.copy_from_slice(&data[..32]);
146        } else {
147            let hashed = blake3::hash(data);
148            hash.copy_from_slice(hashed.as_bytes());
149        }
150        Self(hash)
151    }
152}
153
154/// Network message type
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct NetworkMessage {
157    /// Message ID
158    pub id: String,
159    /// Sender node ID
160    pub sender: NodeId,
161    /// Message content
162    pub content: Vec<u8>,
163    /// Message type
164    pub msg_type: ContentType,
165    /// Timestamp (Unix timestamp in seconds)
166    pub timestamp: u64,
167}
168
169/// Node ID type alias
170pub type NodeId = crate::peer_record::UserId;
171
172/// Node descriptor containing all information about a peer
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct NodeDescriptor {
175    pub id: NodeId,
176    pub public_key: ed25519_dalek::VerifyingKey,
177    pub addresses: Vec<String>,
178    pub hyperbolic: Option<HyperbolicCoordinate>,
179    pub som_position: Option<[f64; 4]>,
180    pub trust: f64,
181    pub capabilities: NodeCapabilities,
182}
183
184/// Hyperbolic coordinate in Poincaré disk model
185#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
186pub struct HyperbolicCoordinate {
187    pub r: f64,     // Radial coordinate [0, 1)
188    pub theta: f64, // Angular coordinate [0, 2π)
189}
190
191/// Node capabilities for resource discovery
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct NodeCapabilities {
194    pub storage: u64,   // GB available
195    pub compute: u64,   // Benchmark score
196    pub bandwidth: u64, // Mbps available
197}
198
199/// Core trait for adaptive P2P network nodes
200#[async_trait]
201pub trait AdaptiveNetworkNode: Send + Sync {
202    /// Join the network using bootstrap nodes
203    async fn join(&mut self, bootstrap: Vec<NodeDescriptor>) -> Result<()>;
204
205    /// Store data with adaptive replication
206    async fn store(&self, data: Vec<u8>) -> Result<ContentHash>;
207
208    /// Retrieve data using parallel strategies
209    async fn retrieve(&self, hash: &ContentHash) -> Result<Vec<u8>>;
210
211    /// Publish a message to a gossip topic
212    async fn publish(&self, topic: &str, message: Vec<u8>) -> Result<()>;
213
214    /// Subscribe to a gossip topic
215    async fn subscribe(
216        &self,
217        topic: &str,
218    ) -> Result<Box<dyn futures::Stream<Item = Vec<u8>> + Send>>;
219
220    /// Get current node information
221    async fn node_info(&self) -> Result<NodeDescriptor>;
222
223    /// Get network statistics
224    async fn network_stats(&self) -> Result<NetworkStats>;
225
226    /// Gracefully shutdown the node
227    async fn shutdown(self) -> Result<()>;
228}
229
230/// Network statistics for monitoring
231#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct NetworkStats {
233    pub connected_peers: usize,
234    pub routing_success_rate: f64,
235    pub average_trust_score: f64,
236    pub cache_hit_rate: f64,
237    pub churn_rate: f64,
238    pub total_storage: u64,
239    pub total_bandwidth: u64,
240}
241
242/// Routing strategy trait for different routing algorithms
243#[async_trait]
244pub trait RoutingStrategy: Send + Sync {
245    /// Find a path to the target node
246    async fn find_path(&self, target: &NodeId) -> Result<Vec<NodeId>>;
247
248    /// Calculate routing score for a neighbor towards a target
249    fn route_score(&self, neighbor: &NodeId, target: &NodeId) -> f64;
250
251    /// Update routing metrics based on success/failure
252    fn update_metrics(&mut self, path: &[NodeId], success: bool);
253
254    /// Find closest nodes to a content hash
255    async fn find_closest_nodes(
256        &self,
257        content_hash: &ContentHash,
258        _count: usize,
259    ) -> Result<Vec<NodeId>> {
260        // Default implementation uses node ID from content hash
261        let target = NodeId {
262            hash: content_hash.0,
263        };
264        self.find_path(&target).await
265    }
266}
267
268/// Trust provider trait for reputation queries
269pub trait TrustProvider: Send + Sync {
270    /// Get trust score for a node
271    fn get_trust(&self, node: &NodeId) -> f64;
272
273    /// Update trust based on interaction
274    fn update_trust(&self, from: &NodeId, to: &NodeId, success: bool);
275
276    /// Get global trust vector
277    fn get_global_trust(&self) -> std::collections::HashMap<NodeId, f64>;
278
279    /// Remove a node from the trust system
280    fn remove_node(&self, node: &NodeId);
281
282    /// Get trust score (alias for get_trust)
283    fn get_trust_score(&self, node: &NodeId) -> f64 {
284        self.get_trust(node)
285    }
286}
287
288/// Learning system trait for adaptive behavior
289#[async_trait]
290pub trait LearningSystem: Send + Sync {
291    /// Select optimal strategy based on context
292    async fn select_strategy(&self, context: &LearningContext) -> StrategyChoice;
293
294    /// Update learning model with outcome
295    async fn update(
296        &mut self,
297        context: &LearningContext,
298        choice: &StrategyChoice,
299        outcome: &Outcome,
300    );
301
302    /// Get current model performance metrics
303    async fn metrics(&self) -> LearningMetrics;
304}
305
306/// Context for learning decisions
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct LearningContext {
309    pub content_type: ContentType,
310    pub network_conditions: NetworkConditions,
311    pub historical_performance: Vec<f64>,
312}
313
314/// Content type classification
315#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
316pub enum ContentType {
317    DHTLookup,
318    DataRetrieval,
319    ComputeRequest,
320    RealtimeMessage,
321    DiscoveryProbe,
322}
323
324/// Current network conditions
325#[derive(Debug, Clone, Serialize, Deserialize)]
326pub struct NetworkConditions {
327    pub connected_peers: usize,
328    pub avg_latency_ms: f64,
329    pub churn_rate: f64,
330}
331
332/// Strategy choice made by learning system
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
334pub enum StrategyChoice {
335    Kademlia,
336    Hyperbolic,
337    TrustPath,
338    SOMRegion,
339}
340
341/// Outcome of a strategy choice
342#[derive(Debug, Clone, Serialize, Deserialize)]
343pub struct Outcome {
344    pub success: bool,
345    pub latency_ms: u64,
346    pub hops: usize,
347}
348
349/// Learning system performance metrics
350#[derive(Debug, Clone, Serialize, Deserialize)]
351pub struct LearningMetrics {
352    pub total_decisions: u64,
353    pub success_rate: f64,
354    pub avg_latency_ms: f64,
355    pub strategy_performance: std::collections::HashMap<StrategyChoice, f64>,
356}
357
358#[cfg(test)]
359mod timestamp_tests;
360
361#[cfg(test)]
362mod tests {
363    use super::*;
364
365    #[test]
366    fn test_content_hash_serialization() {
367        let hash = ContentHash([42u8; 32]);
368        let serialized = bincode::serialize(&hash).unwrap();
369        let deserialized: ContentHash = bincode::deserialize(&serialized).unwrap();
370        assert_eq!(hash, deserialized);
371    }
372
373    #[test]
374    fn test_hyperbolic_coordinate_bounds() {
375        let coord = HyperbolicCoordinate {
376            r: 0.5,
377            theta: std::f64::consts::PI,
378        };
379        assert!(coord.r >= 0.0 && coord.r < 1.0);
380        assert!(coord.theta >= 0.0 && coord.theta < 2.0 * std::f64::consts::PI);
381    }
382}