/// Demonstration of OnionCoin's Proof-of-Contribution consensus /// /// Shows how validators earn rewards through: /// - Stake (40%) /// - Tor relay work (30%) ← UNIQUE! /// - Bandwidth (15%) /// - Uptime (10%) /// - Storage (5%) use onioncoin_consensus::*; use onioncoin_consensus::proof_of_contribution::ScoreWeights; fn main() { println!("=== OnionCoin Proof-of-Contribution Demo ===\n"); demo_validator_tiers(); println!(); demo_contribution_scoring(); println!(); demo_relay_proof(); println!(); demo_validator_selection(); println!(); demo_genesis_mining(); } fn demo_validator_tiers() { println!("šŸŽÆ VALIDATOR TIERS"); println!("=================="); let tiers = [ ValidatorTier::Micro, ValidatorTier::Light, ValidatorTier::Standard, ValidatorTier::Power, ]; println!("ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”"); println!("│ Tier │ Min Stake │ Hardware │ Monthly Return │"); println!("ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"); for tier in &tiers { println!( "│ {:11} │ {:10} ONC │ {:18} │ ~{:13} ONC │", format!("{:?}", tier), tier.min_stake(), match tier { ValidatorTier::Micro => "Raspberry Pi Zero", ValidatorTier::Light => "Raspberry Pi 4", ValidatorTier::Standard => "Desktop PC/VPS", ValidatorTier::Power => "Server 24/7", }, format!("{:.1}", tier.expected_monthly_return()) ); } println!("ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜"); println!("\nāœ… Even a Raspberry Pi Zero can validate!"); } fn demo_contribution_scoring() { println!("šŸ“Š CONTRIBUTION SCORING"); println!("======================"); // Scenario 1: Whale with just stake (lazy validator) let whale = Validator::new([1u8; 32], 10000, "whale.onion".to_string(), 0).unwrap(); let whale_score = ProofOfContribution::calculate( &whale, None, // No relay work &BandwidthMetrics::new(), &UptimeMetrics::new(0), &StorageMetrics::new(), ); println!("Scenario 1: Whale Validator (10,000 ONC stake, no work)"); println!("{}", whale_score.score.breakdown()); println!("\n─────────────────────────────────────────────────────\n"); // Scenario 2: Micro validator with relay work (active participant) let micro = Validator::new([2u8; 32], 10, "micro.onion".to_string(), 0).unwrap(); // Excellent relay metrics let mut relay_metrics = RelayMetrics::new(); relay_metrics.bytes_relayed = 100 * 1024 * 1024 * 1024; // 100 GB! relay_metrics.unique_circuits = 200; relay_metrics.packets_relayed = 1_000_000; relay_metrics.avg_latency_ms = 500; let relay_proof = RelayProof::new([2u8; 32], 0, 3600, relay_metrics); // Good bandwidth let mut bandwidth = BandwidthMetrics::new(); bandwidth.update(10_000_000, 10_000_000, 100); // Great uptime let mut uptime = UptimeMetrics::new(0); for i in 1..=1000 { uptime.record_heartbeat(i * 60); } // Some storage let mut storage = StorageMetrics::new(); storage.update(20 * 1024 * 1024 * 1024, 10 * 1024 * 1024 * 1024, 1000, 10000); let micro_score = ProofOfContribution::calculate( µ, Some(&relay_proof), &bandwidth, &uptime, &storage, ); println!("Scenario 2: Micro Validator (10 ONC stake, LOTS of work)"); println!("{}", micro_score.score.breakdown()); println!("\nšŸŽÆ KEY INSIGHT:"); println!(" Whale total score: {:.3}", whale_score.total_score()); println!(" Micro total score: {:.3}", micro_score.total_score()); println!("\n Micro validator is {}% as competitive as whale!", (micro_score.total_score() / whale_score.total_score() * 100.0) as i32); println!(" šŸ’” OnionCoin rewards WORK, not just wealth!"); } fn demo_relay_proof() { println!("🌐 PROOF-OF-RELAY (OnionCoin's UNIQUE Feature)"); println!("=============================================="); println!("Relay Node Activity:"); println!(" - Relayed: 50 GB of OnionCoin traffic"); println!(" - Circuits: 150 unique Tor circuits"); println!(" - Packets: 500,000"); println!(" - Latency: 800ms average"); let mut metrics = RelayMetrics::new(); metrics.bytes_relayed = 50 * 1024 * 1024 * 1024; metrics.unique_circuits = 150; metrics.packets_relayed = 500_000; metrics.avg_latency_ms = 800; let proof = RelayProof::new([42u8; 32], 0, 3600, metrics); println!("\nRelay Proof:"); println!(" - Valid: {}", proof.verify()); println!(" - Quality Score: {:.2}", proof.metrics.quality_score()); println!(" - Reward: {} ONC", proof.calculate_reward()); println!("\nāœ… NO OTHER CRYPTOCURRENCY REWARDS TOR RELAY WORK!"); } fn demo_validator_selection() { println!("šŸŽ² VALIDATOR SELECTION"); println!("====================="); let mut registry = ValidatorRegistry::new(); // Create diverse validators let validators_data = vec![ ("whale.onion", 10000, 0.3), // High stake, low work ("worker.onion", 100, 0.8), // Low stake, high work ("balanced.onion", 1000, 0.6), // Balanced ]; let mut validators = Vec::new(); for (i, (addr, stake, score)) in validators_data.iter().enumerate() { let pubkey = [(i + 1) as u8; 32]; let validator = Validator::new(pubkey, *stake, addr.to_string(), 0).unwrap(); registry.register(validator.clone()).unwrap(); validators.push((validator, *score)); } println!("Validators:"); for (validator, score) in &validators { println!(" - {}: {} ONC (score: {:.2})", validator.onion_address, validator.stake, score); } // Create contribution proofs let candidates: Vec<_> = validators .iter() .map(|(v, score)| { let poc = create_mock_poc(v.pubkey, *score); (v, poc) }) .collect(); let selector = ValidatorSelector::default(); println!("\nSelection Simulation (1000 rounds):"); let mut selection_counts = std::collections::HashMap::new(); for height in 0..1000 { let prev_hash = [height as u8; 32]; if let Some(selected) = selector.select_validator(&candidates, &prev_hash, height) { *selection_counts.entry(selected).or_insert(0) += 1; } } for (validator, _) in &validators { let count = selection_counts.get(&validator.pubkey).unwrap_or(&0); let percentage = (*count as f64 / 1000.0) * 100.0; println!(" - {}: selected {} times ({:.1}%)", validator.onion_address, count, percentage); } println!("\nāœ… High-work validators get selected more often!"); } fn demo_genesis_mining() { println!("🌱 GENESIS MINING (Fair Launch)"); println!("================================"); let config = GenesisConfig::default(); let mut genesis = GenesisMining::new(config.clone(), 0); println!("Genesis Phase:"); println!(" - Duration: 6 months"); println!(" - Total Supply: 1,000,000 ONC"); println!(" - Distribution: 100% to Tor relay operators"); println!(" - NO pre-mine, NO ICO, completely FAIR\n"); // Simulate 3 relay operators let operators = vec![ ("Early adopter (day 1)", [1u8; 32], "early.onion", 0, 100 * 1024 * 1024 * 1024u64), ("Mid participant (month 2)", [2u8; 32], "mid.onion", 60 * 24 * 3600, 80 * 1024 * 1024 * 1024), ("Late joiner (month 4)", [3u8; 32], "late.onion", 120 * 24 * 3600, 50 * 1024 * 1024 * 1024), ]; for (name, pubkey, addr, reg_time, bytes) in &operators { genesis.register_relay(*pubkey, addr.to_string(), *reg_time); genesis.record_relay_activity(pubkey, *bytes, 86400 * 30); // 30 days uptime let rewards = genesis.calculate_rewards(pubkey, config.duration_seconds); println!("{}", name); println!(" - Relayed: {} GB", bytes / (1024 * 1024 * 1024)); println!(" - Rewards: {} ONC", rewards); } let stats = genesis.stats(); println!("\nGenesis Stats:"); println!(" - Total relay nodes: {}", stats.total_relay_nodes); println!(" - Total relayed: {} GB", stats.total_bytes_relayed / (1024 * 1024 * 1024)); println!("\nāœ… Early participants get bonus, but everyone can join!"); } // Helper function fn create_mock_poc(pubkey: [u8; 32], total_score: f64) -> ProofOfContribution { let score = ContributionScore { stake_score: total_score * 0.4, relay_score: total_score * 0.3, bandwidth_score: total_score * 0.15, uptime_score: total_score * 0.1, storage_score: total_score * 0.05, weights: ScoreWeights::default(), }; ProofOfContribution { validator_pubkey: pubkey, score, timestamp: 0, } }