Rust · 18189 bytes Raw Blame History
1 //! Contribution-Based Economic Manager
2 //!
3 //! Replaces token-based economics with contribution tracking and cooperative resource allocation
4
5 use anyhow::Result;
6 use serde::{Deserialize, Serialize};
7 use std::collections::HashMap;
8 use chrono::{DateTime, Utc, Duration};
9
10 use super::contribution_tracker::{ContributionTracker, UserContribution, PriorityLevel, AccountStatus};
11
12 /// Main economic manager using contribution-based model
13 #[derive(Debug, Clone, Serialize, Deserialize)]
14 pub struct ContributionEconomicManager {
15 /// Contribution tracking system
16 pub contribution_tracker: ContributionTracker,
17 /// Resource allocation queue
18 pub allocation_queue: AllocationQueue,
19 /// Network resource management
20 pub resource_manager: ResourceManager,
21 /// Simple referral tracking
22 pub referral_tracker: SimpleReferralTracker,
23 }
24
25 #[derive(Debug, Clone, Serialize, Deserialize)]
26 pub struct AllocationQueue {
27 /// Pending storage requests ordered by priority
28 pub storage_requests: Vec<StorageRequest>,
29 /// Active storage allocations
30 pub active_allocations: HashMap<String, StorageAllocation>,
31 /// Allocation history for analytics
32 pub allocation_history: Vec<AllocationRecord>,
33 }
34
35 #[derive(Debug, Clone, Serialize, Deserialize)]
36 pub struct StorageRequest {
37 pub request_id: String,
38 pub user_id: String,
39 pub requested_gb: u64,
40 pub priority_score: u32,
41 pub requested_at: DateTime<Utc>,
42 pub expires_at: DateTime<Utc>,
43 pub requirements: StorageRequirements,
44 }
45
46 #[derive(Debug, Clone, Serialize, Deserialize)]
47 pub struct StorageRequirements {
48 pub durability_level: DurabilityLevel,
49 pub access_frequency: AccessFrequency,
50 pub geographic_preference: Option<String>,
51 pub max_latency_ms: Option<u64>,
52 }
53
54 #[derive(Debug, Clone, Serialize, Deserialize)]
55 pub enum DurabilityLevel {
56 /// Standard redundancy (3 copies)
57 Standard,
58 /// High redundancy (5 copies)
59 High,
60 /// Critical redundancy (7 copies)
61 Critical,
62 }
63
64 #[derive(Debug, Clone, Serialize, Deserialize)]
65 pub enum AccessFrequency {
66 /// Rarely accessed, optimize for cost
67 Cold,
68 /// Occasionally accessed
69 Warm,
70 /// Frequently accessed, optimize for speed
71 Hot,
72 }
73
74 #[derive(Debug, Clone, Serialize, Deserialize)]
75 pub struct StorageAllocation {
76 pub allocation_id: String,
77 pub user_id: String,
78 pub allocated_gb: u64,
79 pub allocated_to_nodes: Vec<String>,
80 pub allocated_at: DateTime<Utc>,
81 pub expires_at: Option<DateTime<Utc>>,
82 pub status: AllocationStatus,
83 }
84
85 #[derive(Debug, Clone, Serialize, Deserialize)]
86 pub enum AllocationStatus {
87 Active,
88 Expired,
89 Revoked,
90 }
91
92 #[derive(Debug, Clone, Serialize, Deserialize)]
93 pub struct AllocationRecord {
94 pub user_id: String,
95 pub action: AllocationAction,
96 pub amount_gb: u64,
97 pub reason: String,
98 pub timestamp: DateTime<Utc>,
99 }
100
101 #[derive(Debug, Clone, Serialize, Deserialize)]
102 pub enum AllocationAction {
103 Granted,
104 Denied,
105 Revoked,
106 Expired,
107 }
108
109 #[derive(Debug, Clone, Serialize, Deserialize)]
110 pub struct ResourceManager {
111 /// Available storage capacity per node
112 pub node_capacity: HashMap<String, NodeCapacity>,
113 /// Current utilization statistics
114 pub utilization_stats: UtilizationStats,
115 /// Resource allocation policies
116 pub allocation_policies: AllocationPolicies,
117 }
118
119 #[derive(Debug, Clone, Serialize, Deserialize)]
120 pub struct NodeCapacity {
121 pub node_id: String,
122 pub total_capacity_gb: u64,
123 pub available_capacity_gb: u64,
124 pub allocated_capacity_gb: u64,
125 pub reliability_score: f64,
126 pub performance_metrics: NodePerformance,
127 pub last_updated: DateTime<Utc>,
128 }
129
130 #[derive(Debug, Clone, Serialize, Deserialize)]
131 pub struct NodePerformance {
132 pub uptime_percentage: f64,
133 pub average_response_time_ms: u64,
134 pub bandwidth_mbps: f64,
135 pub success_rate: f64,
136 }
137
138 #[derive(Debug, Clone, Serialize, Deserialize)]
139 pub struct UtilizationStats {
140 pub total_network_capacity_gb: u64,
141 pub total_allocated_gb: u64,
142 pub total_available_gb: u64,
143 pub utilization_percentage: f64,
144 pub active_nodes: u32,
145 pub last_updated: DateTime<Utc>,
146 }
147
148 #[derive(Debug, Clone, Serialize, Deserialize)]
149 pub struct AllocationPolicies {
150 /// Maximum allocation per user based on contribution level
151 pub max_allocation_ratios: HashMap<PriorityLevel, f64>,
152 /// Minimum contribution score for allocation
153 pub min_contribution_score: f64,
154 /// Grace period for new users (days)
155 pub new_user_grace_period: u32,
156 /// Allocation request timeout (hours)
157 pub request_timeout_hours: u32,
158 }
159
160 #[derive(Debug, Clone, Serialize, Deserialize)]
161 pub struct SimpleReferralTracker {
162 /// User referrals (referrer -> list of referred users)
163 pub referrals: HashMap<String, Vec<ReferralRecord>>,
164 /// Referral bonuses awarded
165 pub bonuses: HashMap<String, Vec<ReferralBonus>>,
166 /// Configuration
167 pub config: ReferralConfig,
168 }
169
170 #[derive(Debug, Clone, Serialize, Deserialize)]
171 pub struct ReferralRecord {
172 pub referred_user_id: String,
173 pub referred_at: DateTime<Utc>,
174 pub bonus_awarded: bool,
175 pub bonus_awarded_at: Option<DateTime<Utc>>,
176 }
177
178 #[derive(Debug, Clone, Serialize, Deserialize)]
179 pub struct ReferralBonus {
180 pub bonus_gb: u64,
181 pub reason: String,
182 pub awarded_at: DateTime<Utc>,
183 pub expires_at: Option<DateTime<Utc>>,
184 }
185
186 #[derive(Debug, Clone, Serialize, Deserialize)]
187 pub struct ReferralConfig {
188 /// Storage bonus for successful referral (GB)
189 pub referral_bonus_gb: u64,
190 /// Minimum contribution from referee before bonus
191 pub min_referee_contribution_gb: u64,
192 /// Maximum number of referral bonuses per user
193 pub max_referral_bonuses: u32,
194 /// Bonus expiration time (days)
195 pub bonus_expires_days: u32,
196 }
197
198 impl ContributionEconomicManager {
199 pub fn new() -> Self {
200 Self {
201 contribution_tracker: ContributionTracker::new(),
202 allocation_queue: AllocationQueue {
203 storage_requests: Vec::new(),
204 active_allocations: HashMap::new(),
205 allocation_history: Vec::new(),
206 },
207 resource_manager: ResourceManager {
208 node_capacity: HashMap::new(),
209 utilization_stats: UtilizationStats {
210 total_network_capacity_gb: 0,
211 total_allocated_gb: 0,
212 total_available_gb: 0,
213 utilization_percentage: 0.0,
214 active_nodes: 0,
215 last_updated: Utc::now(),
216 },
217 allocation_policies: AllocationPolicies {
218 max_allocation_ratios: {
219 let mut ratios = HashMap::new();
220 ratios.insert(PriorityLevel::Deficit, 0.5); // Can use 50% of what they offer
221 ratios.insert(PriorityLevel::Balanced, 1.0); // Can use 100% of what they offer
222 ratios.insert(PriorityLevel::Surplus, 1.5); // Can use 150% of what they offer
223 ratios.insert(PriorityLevel::Generous, 2.0); // Can use 200% of what they offer
224 ratios
225 },
226 min_contribution_score: 0.5,
227 new_user_grace_period: 30,
228 request_timeout_hours: 24,
229 },
230 },
231 referral_tracker: SimpleReferralTracker {
232 referrals: HashMap::new(),
233 bonuses: HashMap::new(),
234 config: ReferralConfig {
235 referral_bonus_gb: 10,
236 min_referee_contribution_gb: 100,
237 max_referral_bonuses: 10,
238 bonus_expires_days: 365,
239 },
240 },
241 }
242 }
243
244 /// Register a new node offering storage
245 pub async fn register_node(&mut self, user_id: String, storage_gb: u64, performance: NodePerformance) -> Result<()> {
246 // Register in contribution tracker
247 self.contribution_tracker.register_user(user_id.clone(), storage_gb).await?;
248
249 // Add node capacity
250 self.resource_manager.node_capacity.insert(user_id.clone(), NodeCapacity {
251 node_id: user_id,
252 total_capacity_gb: storage_gb,
253 available_capacity_gb: storage_gb,
254 allocated_capacity_gb: 0,
255 reliability_score: 1.0, // Start with neutral score
256 performance_metrics: performance,
257 last_updated: Utc::now(),
258 });
259
260 self.update_utilization_stats().await?;
261 Ok(())
262 }
263
264 /// Request storage allocation
265 pub async fn request_storage(&mut self, user_id: String, requested_gb: u64, requirements: StorageRequirements) -> Result<String> {
266 // Check if user can make this request
267 if !self.contribution_tracker.can_request_storage(&user_id, requested_gb)? {
268 return Err(anyhow::anyhow!("Request denied: insufficient contribution or account status"));
269 }
270
271 // Get priority score
272 let priority_score = self.contribution_tracker.get_allocation_priority(&user_id)?;
273
274 // Create storage request
275 let request_id = format!("req_{}", uuid::Uuid::new_v4());
276 let request = StorageRequest {
277 request_id: request_id.clone(),
278 user_id: user_id.clone(),
279 requested_gb,
280 priority_score,
281 requested_at: Utc::now(),
282 expires_at: Utc::now() + Duration::hours(self.resource_manager.allocation_policies.request_timeout_hours as i64),
283 requirements,
284 };
285
286 // Insert request in priority order
287 self.allocation_queue.storage_requests.push(request);
288 self.allocation_queue.storage_requests.sort_by(|a, b| b.priority_score.cmp(&a.priority_score));
289
290 // Try to process immediately
291 self.process_allocation_queue().await?;
292
293 Ok(request_id)
294 }
295
296 /// Process pending storage allocations
297 pub async fn process_allocation_queue(&mut self) -> Result<()> {
298 let mut processed_requests = Vec::new();
299 let mut allocations_to_record = Vec::new();
300 let mut new_allocations = Vec::new();
301
302 // First pass: collect requests to process without borrowing conflicts
303 let requests_to_process: Vec<(usize, crate::allocation::AllocationRequest)> = self.allocation_queue.storage_requests
304 .iter()
305 .enumerate()
306 .map(|(i, req)| (i, req.clone()))
307 .collect();
308
309 for (i, request) in requests_to_process {
310 // Check if request expired
311 if request.expires_at < Utc::now() {
312 allocations_to_record.push((request.user_id.clone(), AllocationAction::Expired, request.requested_gb, "Request expired".to_string()));
313 processed_requests.push(i);
314 continue;
315 }
316
317 // Try to allocate storage
318 match self.allocate_storage_for_request(&request).await {
319 Ok(allocation) => {
320 new_allocations.push(allocation.clone());
321 allocations_to_record.push((request.user_id.clone(), AllocationAction::Granted, request.requested_gb, "Storage allocated successfully".to_string()));
322 processed_requests.push(i);
323 },
324 Err(_) => {
325 // Cannot allocate right now, leave in queue
326 }
327 }
328 }
329
330 // Record all allocations
331 for (user_id, action, gb, message) in allocations_to_record {
332 self.record_allocation(user_id, action, gb, message).await;
333 }
334
335 // Add new allocations
336 for allocation in new_allocations {
337 self.allocation_queue.active_allocations.insert(allocation.allocation_id.clone(), allocation);
338 }
339
340 // Remove processed requests (in reverse order to maintain indices)
341 for &i in processed_requests.iter().rev() {
342 self.allocation_queue.storage_requests.remove(i);
343 }
344
345 Ok(())
346 }
347
348 /// Allocate storage for a specific request
349 async fn allocate_storage_for_request(&mut self, request: &StorageRequest) -> Result<StorageAllocation> {
350 // Find suitable nodes based on requirements
351 let suitable_nodes = self.find_suitable_nodes(&request.requirements, request.requested_gb)?;
352
353 if suitable_nodes.is_empty() {
354 return Err(anyhow::anyhow!("No suitable nodes available"));
355 }
356
357 // Update user's storage usage
358 self.contribution_tracker.update_storage_usage(&request.user_id,
359 self.contribution_tracker.get_user_status(&request.user_id).unwrap().storage_used_gb + request.requested_gb).await?;
360
361 // Create allocation
362 let allocation = StorageAllocation {
363 allocation_id: format!("alloc_{}", uuid::Uuid::new_v4()),
364 user_id: request.user_id.clone(),
365 allocated_gb: request.requested_gb,
366 allocated_to_nodes: suitable_nodes,
367 allocated_at: Utc::now(),
368 expires_at: None, // No expiration for now
369 status: AllocationStatus::Active,
370 };
371
372 Ok(allocation)
373 }
374
375 /// Find suitable nodes for storage requirements
376 fn find_suitable_nodes(&self, requirements: &StorageRequirements, needed_gb: u64) -> Result<Vec<String>> {
377 let mut suitable_nodes: Vec<_> = self.resource_manager.node_capacity.values()
378 .filter(|node| {
379 node.available_capacity_gb >= needed_gb &&
380 node.reliability_score >= 0.8 &&
381 node.performance_metrics.uptime_percentage >= 95.0
382 })
383 .collect();
384
385 // Sort by reliability and performance
386 suitable_nodes.sort_by(|a, b| {
387 b.reliability_score.partial_cmp(&a.reliability_score).unwrap()
388 .then_with(|| b.performance_metrics.uptime_percentage.partial_cmp(&a.performance_metrics.uptime_percentage).unwrap())
389 });
390
391 // Return top nodes (could implement more sophisticated selection based on requirements)
392 let num_nodes = match requirements.durability_level {
393 DurabilityLevel::Standard => 3,
394 DurabilityLevel::High => 5,
395 DurabilityLevel::Critical => 7,
396 };
397
398 Ok(suitable_nodes.iter()
399 .take(num_nodes.min(suitable_nodes.len()))
400 .map(|node| node.node_id.clone())
401 .collect())
402 }
403
404 /// Record allocation action in history
405 async fn record_allocation(&mut self, user_id: String, action: AllocationAction, amount_gb: u64, reason: String) {
406 let record = AllocationRecord {
407 user_id,
408 action,
409 amount_gb,
410 reason,
411 timestamp: Utc::now(),
412 };
413 self.allocation_queue.allocation_history.push(record);
414 }
415
416 /// Update network utilization statistics
417 async fn update_utilization_stats(&mut self) -> Result<()> {
418 let mut total_capacity = 0u64;
419 let mut total_allocated = 0u64;
420 let mut active_nodes = 0u32;
421
422 for capacity in self.resource_manager.node_capacity.values() {
423 total_capacity += capacity.total_capacity_gb;
424 total_allocated += capacity.allocated_capacity_gb;
425 if capacity.available_capacity_gb > 0 {
426 active_nodes += 1;
427 }
428 }
429
430 self.resource_manager.utilization_stats = UtilizationStats {
431 total_network_capacity_gb: total_capacity,
432 total_allocated_gb: total_allocated,
433 total_available_gb: total_capacity - total_allocated,
434 utilization_percentage: if total_capacity > 0 {
435 (total_allocated as f64 / total_capacity as f64) * 100.0
436 } else {
437 0.0
438 },
439 active_nodes,
440 last_updated: Utc::now(),
441 };
442
443 Ok(())
444 }
445
446 /// Simple referral system - award bonus for successful referral
447 pub async fn process_referral(&mut self, referrer_id: String, referred_user_id: String) -> Result<()> {
448 // Check if referred user meets minimum contribution
449 let referred_contribution = self.contribution_tracker.get_user_status(&referred_user_id)
450 .ok_or_else(|| anyhow::anyhow!("Referred user not found"))?;
451
452 if referred_contribution.storage_offered_gb >= self.referral_tracker.config.min_referee_contribution_gb {
453 // Award bonus to both users
454 let bonus = ReferralBonus {
455 bonus_gb: self.referral_tracker.config.referral_bonus_gb,
456 reason: format!("Referral bonus for {}", referred_user_id),
457 awarded_at: Utc::now(),
458 expires_at: Some(Utc::now() + Duration::days(self.referral_tracker.config.bonus_expires_days as i64)),
459 };
460
461 // Add bonus storage allocation for referrer
462 self.referral_tracker.bonuses.entry(referrer_id.clone()).or_insert_with(Vec::new).push(bonus.clone());
463 self.referral_tracker.bonuses.entry(referred_user_id.clone()).or_insert_with(Vec::new).push(bonus);
464
465 // Record the referral
466 let referral_record = ReferralRecord {
467 referred_user_id: referred_user_id.clone(),
468 referred_at: Utc::now(),
469 bonus_awarded: true,
470 bonus_awarded_at: Some(Utc::now()),
471 };
472 self.referral_tracker.referrals.entry(referrer_id).or_insert_with(Vec::new).push(referral_record);
473 }
474
475 Ok(())
476 }
477
478 /// Get contribution tracker reference
479 pub fn get_contribution_tracker(&self) -> &ContributionTracker {
480 &self.contribution_tracker
481 }
482
483 /// Get resource manager reference
484 pub fn get_resource_manager(&self) -> &ResourceManager {
485 &self.resource_manager
486 }
487
488 /// Get allocation queue reference
489 pub fn get_allocation_queue(&self) -> &AllocationQueue {
490 &self.allocation_queue
491 }
492 }
493
494 impl Default for ContributionEconomicManager {
495 fn default() -> Self {
496 Self::new()
497 }
498 }