//! Network Evolution and Economic Sustainability //! //! Provides mechanisms for the network to adapt, optimize, and sustain itself //! through intelligent resource allocation and contribution incentives. use wasm_bindgen::prelude::*; use serde::{Serialize, Deserialize}; use rustc_hash::FxHashMap; // 30-50% faster than std HashMap use std::collections::VecDeque; /// Network topology adaptation for self-organization #[wasm_bindgen] #[derive(Clone, Serialize, Deserialize)] pub struct NetworkTopology { /// Current network structure fingerprint topology_hash: String, /// Node connectivity graph (adjacency scores) - FxHashMap for faster lookups connectivity: FxHashMap>, /// Cluster assignments for efficient routing - FxHashMap for O(1) lookups clusters: FxHashMap, /// Adaptation learning rate learning_rate: f32, /// Optimization generation generation: u64, /// Max connections per node (bounded to prevent memory growth) max_connections_per_node: usize, } #[wasm_bindgen] impl NetworkTopology { #[wasm_bindgen(constructor)] pub fn new() -> NetworkTopology { NetworkTopology { topology_hash: String::new(), connectivity: FxHashMap::default(), clusters: FxHashMap::default(), learning_rate: 0.1, generation: 0, max_connections_per_node: 100, // Bounded connectivity } } /// Register a node in the topology #[wasm_bindgen(js_name = registerNode)] pub fn register_node(&mut self, node_id: &str, capabilities: &[f32]) { // Assign to cluster based on capability similarity let cluster_id = self.determine_cluster(capabilities); self.clusters.insert(node_id.to_string(), cluster_id); self.connectivity.insert(node_id.to_string(), Vec::new()); self.generation += 1; } /// Update connection strength between nodes #[wasm_bindgen(js_name = updateConnection)] pub fn update_connection(&mut self, from: &str, to: &str, success_rate: f32) { if let Some(connections) = self.connectivity.get_mut(from) { if let Some(conn) = connections.iter_mut().find(|(id, _)| id == to) { // Exponential moving average conn.1 = conn.1 * (1.0 - self.learning_rate) + success_rate * self.learning_rate; } else { // Bounded connections: evict lowest score if at limit if connections.len() >= self.max_connections_per_node { if let Some(min_idx) = connections.iter() .enumerate() .min_by(|(_, a), (_, b)| a.1.partial_cmp(&b.1).unwrap()) .map(|(i, _)| i) { connections.swap_remove(min_idx); } } connections.push((to.to_string(), success_rate)); } } } /// Get optimal peers for a node #[wasm_bindgen(js_name = getOptimalPeers)] pub fn get_optimal_peers(&self, node_id: &str, count: usize) -> Vec { let mut peers = Vec::new(); if let Some(connections) = self.connectivity.get(node_id) { let mut sorted: Vec<_> = connections.iter().collect(); sorted.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal)); for (peer_id, _score) in sorted.into_iter().take(count) { peers.push(peer_id.clone()); } } peers } fn determine_cluster(&self, capabilities: &[f32]) -> u32 { // Simple clustering based on primary capability if capabilities.is_empty() { return 0; } let max_idx = capabilities.iter() .enumerate() .max_by(|a, b| a.1.partial_cmp(b.1).unwrap_or(std::cmp::Ordering::Equal)) .map(|(i, _)| i) .unwrap_or(0); max_idx as u32 } } /// Economic distribution system for sustainable operations #[wasm_bindgen] #[derive(Clone, Serialize, Deserialize)] pub struct EconomicEngine { /// Total rUv in circulation total_supply: u64, /// Treasury reserve for network operations treasury: u64, /// Contributor allocation pool contributor_pool: u64, /// Protocol development fund (sustains core development) protocol_fund: u64, /// Distribution ratios (must sum to 1.0) distribution: DistributionRatios, /// Economic health metrics health: EconomicHealth, /// Epoch for tracking periods current_epoch: u64, } #[derive(Clone, Serialize, Deserialize, Default)] struct DistributionRatios { /// Share to active contributors contributors: f32, /// Share to treasury for operations treasury: f32, /// Share to protocol development (sustains innovation) protocol: f32, /// Share to founding contributors (vested over time) founders: f32, } #[wasm_bindgen] #[derive(Clone, Serialize, Deserialize, Default)] pub struct EconomicHealth { /// Velocity of rUv (transactions per period) pub velocity: f32, /// Network utilization rate pub utilization: f32, /// Supply growth rate pub growth_rate: f32, /// Stability index (0-1) pub stability: f32, } #[wasm_bindgen] impl EconomicEngine { #[wasm_bindgen(constructor)] pub fn new() -> EconomicEngine { EconomicEngine { total_supply: 0, treasury: 0, contributor_pool: 0, protocol_fund: 0, distribution: DistributionRatios { contributors: 0.70, // 70% to contributors treasury: 0.15, // 15% to operations protocol: 0.10, // 10% to protocol development founders: 0.05, // 5% to founding contributors }, health: EconomicHealth::default(), current_epoch: 0, } } /// Process task completion and distribute rewards #[wasm_bindgen(js_name = processReward)] pub fn process_reward(&mut self, base_amount: u64, multiplier: f32) -> RewardDistribution { let total = (base_amount as f32 * multiplier) as u64; // Mint new rUv self.total_supply += total; // Calculate distributions let to_contributor = (total as f32 * self.distribution.contributors) as u64; let to_treasury = (total as f32 * self.distribution.treasury) as u64; let to_protocol = (total as f32 * self.distribution.protocol) as u64; let to_founders = total - to_contributor - to_treasury - to_protocol; // Update pools self.contributor_pool += to_contributor; self.treasury += to_treasury; self.protocol_fund += to_protocol; // Update health metrics self.health.velocity = (self.health.velocity * 0.99) + 0.01; RewardDistribution { total, contributor_share: to_contributor, treasury_share: to_treasury, protocol_share: to_protocol, founder_share: to_founders, } } /// Check if network can sustain itself #[wasm_bindgen(js_name = isSelfSustaining)] pub fn is_self_sustaining(&self, active_nodes: u32, daily_tasks: u64) -> bool { // Network is self-sustaining when: // 1. Enough nodes for redundancy (100+) // 2. Sufficient daily activity (1000+ tasks) // 3. Treasury can cover 90 days of operations // 4. Positive growth rate let min_nodes = 100; let min_daily_tasks = 1000; let treasury_runway_days = 90; let estimated_daily_cost = (active_nodes as u64) * 10; // 10 rUv per node per day active_nodes >= min_nodes && daily_tasks >= min_daily_tasks && self.treasury >= estimated_daily_cost * treasury_runway_days && self.health.growth_rate >= 0.0 } /// Get protocol fund balance (for development sustainability) #[wasm_bindgen(js_name = getProtocolFund)] pub fn get_protocol_fund(&self) -> u64 { self.protocol_fund } /// Get treasury balance #[wasm_bindgen(js_name = getTreasury)] pub fn get_treasury(&self) -> u64 { self.treasury } /// Get economic health status #[wasm_bindgen(js_name = getHealth)] pub fn get_health(&self) -> EconomicHealth { self.health.clone() } /// Advance to next epoch #[wasm_bindgen(js_name = advanceEpoch)] pub fn advance_epoch(&mut self) { self.current_epoch += 1; // Recalculate health metrics self.health.stability = self.calculate_stability(); } fn calculate_stability(&self) -> f32 { // Stability based on balanced pools let total_pools = self.treasury + self.contributor_pool + self.protocol_fund; if total_pools == 0 { return 0.5; } let treasury_ratio = self.treasury as f32 / total_pools as f32; let contributor_ratio = self.contributor_pool as f32 / total_pools as f32; let protocol_ratio = self.protocol_fund as f32 / total_pools as f32; // Penalize imbalanced distribution let ideal = 0.33f32; let variance = (treasury_ratio - ideal).powi(2) + (contributor_ratio - ideal).powi(2) + (protocol_ratio - ideal).powi(2); (1.0 - variance.sqrt()).max(0.0).min(1.0) } } #[wasm_bindgen] #[derive(Clone, Serialize, Deserialize)] pub struct RewardDistribution { pub total: u64, pub contributor_share: u64, pub treasury_share: u64, pub protocol_share: u64, pub founder_share: u64, } /// Node replication and evolution guidance #[wasm_bindgen] #[derive(Clone)] pub struct EvolutionEngine { /// Fitness scores by capability - FxHashMap for faster lookups fitness_scores: FxHashMap, /// Successful patterns for replication (bounded to 100) successful_patterns: Vec, /// Evolution generation generation: u64, /// Mutation rate for variation mutation_rate: f32, /// Max patterns to track max_patterns: usize, } #[derive(Clone, Serialize, Deserialize)] struct NodePattern { pattern_id: String, capabilities: Vec, configuration: FxHashMap, success_rate: f32, replications: u32, } #[wasm_bindgen] impl EvolutionEngine { #[wasm_bindgen(constructor)] pub fn new() -> EvolutionEngine { EvolutionEngine { fitness_scores: FxHashMap::default(), successful_patterns: Vec::with_capacity(100), // Pre-allocate generation: 0, mutation_rate: 0.05, max_patterns: 100, } } /// Record node performance for fitness evaluation #[wasm_bindgen(js_name = recordPerformance)] pub fn record_performance(&mut self, node_id: &str, success_rate: f32, throughput: f32) { let fitness = success_rate * 0.6 + (throughput / 100.0).min(1.0) * 0.4; if let Some(existing) = self.fitness_scores.get_mut(node_id) { *existing = *existing * 0.9 + fitness * 0.1; // Exponential moving average } else { self.fitness_scores.insert(node_id.to_string(), fitness); } } /// Get recommended configuration for new nodes #[wasm_bindgen(js_name = getRecommendedConfig)] pub fn get_recommended_config(&self) -> String { // Find highest performing pattern let best = self.successful_patterns.iter() .max_by(|a, b| a.success_rate.partial_cmp(&b.success_rate).unwrap_or(std::cmp::Ordering::Equal)); match best { Some(pattern) => serde_json::to_string(&pattern.configuration).unwrap_or_default(), None => r#"{"cpu_limit":0.3,"memory_limit":268435456,"min_idle_time":5000}"#.to_string(), } } /// Check if node should replicate (spawn similar node) #[wasm_bindgen(js_name = shouldReplicate)] pub fn should_replicate(&self, node_id: &str) -> bool { if let Some(&fitness) = self.fitness_scores.get(node_id) { // High performers should replicate fitness > 0.85 } else { false } } /// Get network fitness score #[wasm_bindgen(js_name = getNetworkFitness)] pub fn get_network_fitness(&self) -> f32 { if self.fitness_scores.is_empty() { return 0.0; } let sum: f32 = self.fitness_scores.values().sum(); sum / self.fitness_scores.len() as f32 } /// Evolve patterns for next generation #[wasm_bindgen(js_name = evolve)] pub fn evolve(&mut self) { self.generation += 1; // Remove underperforming patterns self.successful_patterns.retain(|p| p.success_rate > 0.5); // Decrease mutation rate over generations (stabilization) self.mutation_rate = (0.05 * (0.99f32).powi(self.generation as i32)).max(0.01); } } /// Network optimization for resource efficiency #[wasm_bindgen] #[derive(Clone)] pub struct OptimizationEngine { /// Task routing decisions and outcomes (VecDeque for efficient trimming) routing_history: VecDeque, /// Resource utilization by node - FxHashMap for faster lookups resource_usage: FxHashMap, /// Optimization policies policies: OptimizationPolicies, /// Learning from outcomes learning_enabled: bool, /// Max routing history to keep max_history: usize, } #[derive(Clone, Serialize, Deserialize)] struct RoutingDecision { task_type: String, selected_node: String, alternatives: Vec, latency_ms: u64, success: bool, timestamp: u64, } #[derive(Clone, Serialize, Deserialize, Default)] struct ResourceMetrics { cpu_avg: f32, memory_avg: f32, bandwidth_avg: f32, uptime_seconds: u64, tasks_completed: u64, } #[derive(Clone, Serialize, Deserialize)] struct OptimizationPolicies { /// Prefer nodes with lower latency latency_weight: f32, /// Prefer nodes with higher success rate reliability_weight: f32, /// Balance load across nodes load_balance_weight: f32, } impl Default for OptimizationPolicies { fn default() -> Self { OptimizationPolicies { latency_weight: 0.3, reliability_weight: 0.5, load_balance_weight: 0.2, } } } #[wasm_bindgen] impl OptimizationEngine { #[wasm_bindgen(constructor)] pub fn new() -> OptimizationEngine { OptimizationEngine { routing_history: VecDeque::with_capacity(10000), // Pre-allocate resource_usage: FxHashMap::default(), policies: OptimizationPolicies::default(), learning_enabled: true, max_history: 10000, } } /// Record task routing outcome #[wasm_bindgen(js_name = recordRouting)] pub fn record_routing( &mut self, task_type: &str, node_id: &str, latency_ms: u64, success: bool, ) { let decision = RoutingDecision { task_type: task_type.to_string(), selected_node: node_id.to_string(), alternatives: Vec::new(), latency_ms, success, timestamp: js_sys::Date::now() as u64, }; self.routing_history.push_back(decision); // Keep history bounded (O(1) amortized vs O(n) drain) while self.routing_history.len() > self.max_history { self.routing_history.pop_front(); } // Update resource usage if let Some(metrics) = self.resource_usage.get_mut(node_id) { if success { metrics.tasks_completed += 1; } } else { self.resource_usage.insert(node_id.to_string(), ResourceMetrics { tasks_completed: if success { 1 } else { 0 }, ..Default::default() }); } } /// Get optimal node for a task type #[wasm_bindgen(js_name = selectOptimalNode)] pub fn select_optimal_node(&self, task_type: &str, candidates: Vec) -> String { if candidates.is_empty() { return String::new(); } // Score each candidate let mut scored: Vec<(String, f32)> = candidates.into_iter() .map(|node| { let score = self.calculate_node_score(&node, task_type); (node, score) }) .collect(); scored.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal)); scored.into_iter().next().map(|(node, _)| node).unwrap_or_default() } fn calculate_node_score(&self, node_id: &str, task_type: &str) -> f32 { let history: Vec<_> = self.routing_history.iter() .filter(|d| d.selected_node == node_id && d.task_type == task_type) .collect(); if history.is_empty() { return 0.5; // Unknown nodes get neutral score } let success_rate = history.iter().filter(|d| d.success).count() as f32 / history.len() as f32; let avg_latency: f32 = history.iter().map(|d| d.latency_ms as f32).sum::() / history.len() as f32; let latency_score = 1.0 - (avg_latency / 1000.0).min(1.0); success_rate * self.policies.reliability_weight + latency_score * self.policies.latency_weight + 0.5 * self.policies.load_balance_weight // TODO: actual load balance } /// Get optimization stats #[wasm_bindgen(js_name = getStats)] pub fn get_stats(&self) -> String { let total_decisions = self.routing_history.len(); let successes = self.routing_history.iter().filter(|d| d.success).count(); let success_rate = if total_decisions > 0 { successes as f32 / total_decisions as f32 } else { 0.0 }; format!( r#"{{"total_decisions":{},"success_rate":{:.3},"nodes_tracked":{}}}"#, total_decisions, success_rate, self.resource_usage.len() ) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_economic_engine() { let mut engine = EconomicEngine::new(); let reward = engine.process_reward(100, 1.5); assert_eq!(reward.total, 150); assert!(reward.contributor_share > reward.treasury_share); } #[test] fn test_evolution_engine() { let mut engine = EvolutionEngine::new(); // Record multiple high performances to reach replication threshold (0.85) for _ in 0..10 { engine.record_performance("node-1", 0.98, 80.0); } assert!(engine.should_replicate("node-1")); assert!(!engine.should_replicate("node-unknown")); } #[test] fn test_optimization_select() { // Test selection logic without using js_sys::Date let engine = OptimizationEngine::new(); // With empty history, all candidates should get neutral score let result = engine.select_optimal_node("vectors", vec!["node-1".into(), "node-2".into()]); assert!(!result.is_empty()); } }