avila_async/
blockchain.rs

1//! Blockchain Module
2//!
3//! Immutable audit trail and distributed consensus for runtime events
4
5use std::sync::{Arc, Mutex};
6use std::time::{SystemTime, UNIX_EPOCH};
7use std::collections::HashMap;
8
9/// Blockchain for runtime event logging
10#[derive(Clone)]
11pub struct RuntimeBlockchain {
12    chain: Arc<Mutex<Vec<Block>>>,
13    difficulty: usize,
14    pending_transactions: Arc<Mutex<Vec<Transaction>>>,
15}
16
17#[derive(Clone, Debug)]
18pub struct Block {
19    pub index: u64,
20    pub timestamp: u128,
21    pub transactions: Vec<Transaction>,
22    pub previous_hash: String,
23    pub hash: String,
24    pub nonce: u64,
25}
26
27#[derive(Clone, Debug)]
28pub struct Transaction {
29    pub tx_type: TransactionType,
30    pub data: String,
31    pub timestamp: u128,
32}
33
34#[derive(Clone, Debug)]
35pub enum TransactionType {
36    TaskSpawned,
37    TaskCompleted,
38    ThreadScaled,
39    AnomalyDetected,
40    ConfigChanged,
41    Custom(String),
42}
43
44impl RuntimeBlockchain {
45    pub fn new(difficulty: usize) -> Self {
46        let genesis = Block::genesis();
47        
48        Self {
49            chain: Arc::new(Mutex::new(vec![genesis])),
50            difficulty,
51            pending_transactions: Arc::new(Mutex::new(Vec::new())),
52        }
53    }
54
55    /// Add a transaction to pending pool
56    pub fn add_transaction(&self, tx_type: TransactionType, data: String) {
57        let mut pending = self.pending_transactions.lock().unwrap();
58        pending.push(Transaction {
59            tx_type,
60            data,
61            timestamp: Self::current_timestamp(),
62        });
63    }
64
65    /// Mine a new block with pending transactions
66    pub fn mine_block(&self) -> Block {
67        let mut pending = self.pending_transactions.lock().unwrap();
68        let transactions = pending.drain(..).collect();
69        drop(pending);
70
71        let mut chain = self.chain.lock().unwrap();
72        let previous_block = chain.last().unwrap();
73        
74        let mut block = Block {
75            index: previous_block.index + 1,
76            timestamp: Self::current_timestamp(),
77            transactions,
78            previous_hash: previous_block.hash.clone(),
79            hash: String::new(),
80            nonce: 0,
81        };
82
83        // Proof of work
84        let target = "0".repeat(self.difficulty);
85        while !block.calculate_hash().starts_with(&target) {
86            block.nonce += 1;
87        }
88        
89        block.hash = block.calculate_hash();
90        chain.push(block.clone());
91        
92        block
93    }
94
95    /// Verify blockchain integrity
96    pub fn verify(&self) -> bool {
97        let chain = self.chain.lock().unwrap();
98        
99        for i in 1..chain.len() {
100            let current = &chain[i];
101            let previous = &chain[i - 1];
102
103            // Verify hash
104            if current.hash != current.calculate_hash() {
105                return false;
106            }
107
108            // Verify chain link
109            if current.previous_hash != previous.hash {
110                return false;
111            }
112
113            // Verify proof of work
114            let target = "0".repeat(self.difficulty);
115            if !current.hash.starts_with(&target) {
116                return false;
117            }
118        }
119
120        true
121    }
122
123    /// Get blockchain statistics
124    pub fn stats(&self) -> BlockchainStats {
125        let chain = self.chain.lock().unwrap();
126        let pending = self.pending_transactions.lock().unwrap();
127
128        let total_transactions: usize = chain.iter()
129            .map(|b| b.transactions.len())
130            .sum();
131
132        let block_count = chain.len();
133        let pending_count = pending.len();
134        drop(chain);
135        drop(pending);
136        
137        let is_valid = self.verify();
138        
139        BlockchainStats {
140            block_count,
141            total_transactions,
142            pending_transactions: pending_count,
143            difficulty: self.difficulty,
144            is_valid,
145        }
146    }
147
148    /// Get recent blocks
149    pub fn recent_blocks(&self, count: usize) -> Vec<Block> {
150        let chain = self.chain.lock().unwrap();
151        let start = if chain.len() > count { chain.len() - count } else { 0 };
152        chain[start..].to_vec()
153    }
154
155    /// Search transactions by type
156    pub fn search_transactions(&self, tx_type: &str) -> Vec<Transaction> {
157        let chain = self.chain.lock().unwrap();
158        chain.iter()
159            .flat_map(|block| &block.transactions)
160            .filter(|tx| match &tx.tx_type {
161                TransactionType::TaskSpawned => tx_type == "TaskSpawned",
162                TransactionType::TaskCompleted => tx_type == "TaskCompleted",
163                TransactionType::ThreadScaled => tx_type == "ThreadScaled",
164                TransactionType::AnomalyDetected => tx_type == "AnomalyDetected",
165                TransactionType::ConfigChanged => tx_type == "ConfigChanged",
166                TransactionType::Custom(name) => tx_type == name,
167            })
168            .cloned()
169            .collect()
170    }
171
172    fn current_timestamp() -> u128 {
173        SystemTime::now()
174            .duration_since(UNIX_EPOCH)
175            .unwrap()
176            .as_millis()
177    }
178}
179
180impl Block {
181    fn genesis() -> Self {
182        Self {
183            index: 0,
184            timestamp: 0,
185            transactions: vec![],
186            previous_hash: "0".to_string(),
187            hash: "genesis".to_string(),
188            nonce: 0,
189        }
190    }
191
192    fn calculate_hash(&self) -> String {
193        let data = format!(
194            "{}{}{}{}{}",
195            self.index,
196            self.timestamp,
197            self.transactions.len(),
198            self.previous_hash,
199            self.nonce
200        );
201        
202        // Simple hash function (djb2)
203        let mut hash: u64 = 5381;
204        for byte in data.bytes() {
205            hash = hash.wrapping_mul(33).wrapping_add(byte as u64);
206        }
207        
208        format!("{:016x}", hash)
209    }
210}
211
212#[derive(Debug, Clone)]
213pub struct BlockchainStats {
214    pub block_count: usize,
215    pub total_transactions: usize,
216    pub pending_transactions: usize,
217    pub difficulty: usize,
218    pub is_valid: bool,
219}
220
221impl std::fmt::Display for Block {
222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223        write!(
224            f,
225            "Block[#{}, txs={}, hash={}...{}]",
226            self.index,
227            self.transactions.len(),
228            &self.hash[..8],
229            &self.hash[self.hash.len()-4..]
230        )
231    }
232}
233
234impl std::fmt::Display for BlockchainStats {
235    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236        write!(
237            f,
238            "BlockchainStats[blocks={}, txs={}, pending={}, valid={}]",
239            self.block_count, self.total_transactions, self.pending_transactions, self.is_valid
240        )
241    }
242}
243
244/// Distributed consensus mechanism
245#[derive(Clone)]
246pub struct ConsensusManager {
247    nodes: Arc<Mutex<HashMap<String, NodeState>>>,
248    quorum_size: usize,
249}
250
251#[derive(Clone, Debug)]
252struct NodeState {
253    node_id: String,
254    last_vote: u64,
255    reputation: f64,
256}
257
258impl ConsensusManager {
259    pub fn new(quorum_size: usize) -> Self {
260        Self {
261            nodes: Arc::new(Mutex::new(HashMap::new())),
262            quorum_size,
263        }
264    }
265
266    /// Register a node in the consensus network
267    pub fn register_node(&self, node_id: String) {
268        let mut nodes = self.nodes.lock().unwrap();
269        nodes.insert(node_id.clone(), NodeState {
270            node_id,
271            last_vote: 0,
272            reputation: 1.0,
273        });
274    }
275
276    /// Vote on a decision (returns true if consensus reached)
277    pub fn vote(&self, _decision: &str) -> bool {
278        let nodes = self.nodes.lock().unwrap();
279        nodes.len() >= self.quorum_size
280    }
281
282    /// Get consensus statistics
283    pub fn stats(&self) -> ConsensusStats {
284        let nodes = self.nodes.lock().unwrap();
285        let avg_reputation = if !nodes.is_empty() {
286            nodes.values().map(|n| n.reputation).sum::<f64>() / nodes.len() as f64
287        } else {
288            0.0
289        };
290
291        ConsensusStats {
292            total_nodes: nodes.len(),
293            quorum_size: self.quorum_size,
294            avg_reputation,
295        }
296    }
297}
298
299#[derive(Debug, Clone)]
300pub struct ConsensusStats {
301    pub total_nodes: usize,
302    pub quorum_size: usize,
303    pub avg_reputation: f64,
304}