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