//! Stress benchmark: concurrent IoC consensus, ZKP proof+verify, //! FHE encrypt+decrypt, reputation cascades. //! //! Run: `cargo test -p hivemind --test stress_mesh -- --nocapture` use std::time::Instant; use common::hivemind::IoC; use hivemind::consensus::{ConsensusEngine, ConsensusResult}; use hivemind::crypto::fhe::FheContext; use hivemind::reputation::ReputationStore; use hivemind::zkp::{prover, verifier}; /// Deterministic 32-byte key for peer `id`. fn peer_key(id: u16) -> [u8; 32] { let mut key = [0u8; 32]; key[0] = (id >> 8) as u8; key[1] = (id & 0xFF) as u8; key[31] = 0xAA; key } fn make_ioc(idx: u16) -> IoC { IoC { ioc_type: 0, // MaliciousIp severity: 7, ip: 0x0A630000 | idx as u32, // 10.99.x.x ja4: Some(format!("t13d1517h2_stress_{:04x}", idx)), entropy_score: Some(7500), description: format!("stress-ioc-{idx}"), first_seen: 1_700_000_000 + idx as u64, confirmations: 0, zkp_proof: Vec::new(), } } #[test] fn stress_100_peer_reputation_registration() { let mut reputation = ReputationStore::new(); let start = Instant::now(); for id in 0..120u16 { reputation.register_peer(&peer_key(id)); } let elapsed = start.elapsed(); println!("\n=== 120-PEER REPUTATION REGISTRATION ==="); println!(" Registered: {}", reputation.peer_count()); println!(" Duration: {elapsed:?}"); println!( " Per-peer: {:.2}µs", elapsed.as_micros() as f64 / 120.0 ); assert_eq!(reputation.peer_count(), 120); } #[test] fn stress_concurrent_ioc_consensus() { let mut engine = ConsensusEngine::new(); let start = Instant::now(); let mut accepted = 0u32; // Submit 200 IoCs, each from 3+ different peers to reach quorum for ioc_idx in 0..200u16 { let ioc = make_ioc(ioc_idx); for voter in 0..4u16 { let peer = peer_key(voter); let result = engine.submit_ioc(&ioc, &peer); if matches!(result, ConsensusResult::Accepted(_)) { accepted += 1; } } } let elapsed = start.elapsed(); println!("\n=== IoC CONSENSUS STRESS (200 IoCs × 4 peers) ==="); println!(" IoCs submitted: 200"); println!(" Accepted: {accepted}"); println!(" Duration: {elapsed:?}"); println!( " Per-IoC: {:.2}µs", elapsed.as_micros() as f64 / 200.0 ); assert_eq!(accepted, 200, "all IoCs should reach consensus with 4 voters"); } #[test] fn stress_zkp_proof_verify_throughput() { let start = Instant::now(); let iterations = 500u32; let mut proofs_valid = 0u32; for i in 0..iterations { let ja4 = format!("t13d1517h2_8daaf6152771_{:04x}", i); let proof = prover::prove_threat( Some(ja4.as_bytes()), true, // entropy_exceeded true, // classified_malicious 0, // ioc_type: MaliciousIp None, // no signing key (v0 stub) ); if matches!( verifier::verify_threat(&proof, None), verifier::VerifyResult::ValidStub ) { proofs_valid += 1; } } let elapsed = start.elapsed(); println!("\n=== ZKP v0 STUB THROUGHPUT ==="); println!(" Iterations: {iterations}"); println!(" Valid: {proofs_valid}"); println!(" Duration: {elapsed:?}"); println!( " Per-cycle: {:.2}µs", elapsed.as_micros() as f64 / iterations as f64 ); assert_eq!(proofs_valid, iterations); } #[test] fn stress_zkp_signed_proof_verify() { use ring::signature::{Ed25519KeyPair, KeyPair}; use ring::rand::SystemRandom; let rng = SystemRandom::new(); let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).expect("keygen"); let key_pair = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).expect("parse"); let pub_key = key_pair.public_key().as_ref(); let start = Instant::now(); let iterations = 200u32; let mut proofs_valid = 0u32; for i in 0..iterations { let ja4 = format!("t13d1517h2_signed_{:04x}", i); let proof = prover::prove_threat( Some(ja4.as_bytes()), true, true, 0, Some(&key_pair), ); if matches!( verifier::verify_threat(&proof, Some(pub_key)), verifier::VerifyResult::Valid ) { proofs_valid += 1; } } let elapsed = start.elapsed(); println!("\n=== ZKP v1 SIGNED THROUGHPUT ==="); println!(" Iterations: {iterations}"); println!(" Valid: {proofs_valid}"); println!(" Duration: {elapsed:?}"); println!( " Per-cycle: {:.2}µs", elapsed.as_micros() as f64 / iterations as f64 ); assert_eq!(proofs_valid, iterations); } #[test] fn stress_fhe_encrypt_decrypt_throughput() { let ctx = FheContext::new_encrypted().expect("fhe init"); let start = Instant::now(); let iterations = 1000u32; let mut valid = 0u32; for i in 0..iterations { // Simulate gradient vectors (10 floats each) let gradients: Vec = (0..10) .map(|j| (i as f32 * 0.01) + (j as f32 * 0.001)) .collect(); let encrypted = ctx.encrypt_gradients(&gradients).expect("encrypt"); let decrypted = ctx.decrypt_gradients(&encrypted).expect("decrypt"); if decrypted.len() == gradients.len() { valid += 1; } } let elapsed = start.elapsed(); println!("\n=== FHE (AES-256-GCM) GRADIENT THROUGHPUT ==="); println!(" Iterations: {iterations}"); println!(" Payload: 10 floats = 40 bytes each"); println!(" Valid: {valid}"); println!(" Duration: {elapsed:?}"); println!( " Per-cycle: {:.2}µs", elapsed.as_micros() as f64 / iterations as f64 ); assert_eq!(valid, iterations); } #[test] fn stress_reputation_slashing_cascade() { let mut store = ReputationStore::new(); // Register 100 peers for id in 0..100u16 { store.register_peer(&peer_key(id)); } let start = Instant::now(); let mut expelled = 0u32; // Slash half the peers repeatedly with false reports for id in 0..50u16 { let key = peer_key(id); for _ in 0..10 { store.record_false_report(&key); } if !store.is_trusted(&key) { expelled += 1; } } // Reward the other half for id in 50..100u16 { let key = peer_key(id); for _ in 0..5 { store.record_accurate_report(&key); } } let elapsed = start.elapsed(); println!("\n=== REPUTATION CASCADE ==="); println!(" Total peers: 100"); println!(" Slashed: 50 (10× false reports each)"); println!(" Rewarded: 50 (5× accurate reports each)"); println!(" Expelled: {expelled}"); println!(" Duration: {elapsed:?}"); assert!(expelled >= 30, "heavily-slashed peers should lose trust"); } #[test] fn stress_full_pipeline_ioc_to_proof() { use ring::signature::{Ed25519KeyPair, KeyPair}; use ring::rand::SystemRandom; let rng = SystemRandom::new(); let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).expect("keygen"); let key_pair = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).expect("parse"); let pub_key = key_pair.public_key().as_ref(); let mut engine = ConsensusEngine::new(); let mut reputation = ReputationStore::new(); // Register 20 peers for id in 0..20u16 { reputation.register_peer(&peer_key(id)); } let start = Instant::now(); let mut end_to_end_valid = 0u32; // Full pipeline: IoC → consensus → ZKP proof → verify for ioc_idx in 0..100u16 { let ioc = make_ioc(ioc_idx); // Submit from 3 peers — 3rd should trigger acceptance (threshold=3) for voter in 0..3u16 { let result = engine.submit_ioc(&ioc, &peer_key(voter)); if matches!(result, ConsensusResult::Accepted(_)) { // Generate signed ZKP proof for the accepted IoC let proof = prover::prove_threat( ioc.ja4.as_ref().map(|s| s.as_bytes()), ioc.entropy_score.map_or(false, |e| e > 7000), true, ioc.ioc_type, Some(&key_pair), ); // Verify the proof if matches!( verifier::verify_threat(&proof, Some(pub_key)), verifier::VerifyResult::Valid ) { end_to_end_valid += 1; for v in 0..3u16 { reputation.record_accurate_report(&peer_key(v)); } } } } } let elapsed = start.elapsed(); println!("\n=== FULL PIPELINE: IoC → CONSENSUS → ZKP ==="); println!(" IoCs processed: 100"); println!(" E2E valid: {end_to_end_valid}"); println!(" Duration: {elapsed:?}"); println!( " Per-pipeline: {:.2}µs", elapsed.as_micros() as f64 / 100.0 ); assert_eq!(end_to_end_valid, 100); }