1use crate::{NetworkType, PerformanceStats, MiningRewardType};
36use crate::evm::{TeleportDestination, TeleportTransfer, TeleportStatus};
37use serde::{Deserialize, Serialize};
38use std::collections::HashMap;
39use std::sync::Arc;
40use tokio::sync::RwLock;
41
42pub const LUX_MAINNET_NETWORK_ID: u32 = 1;
44pub const LUX_TESTNET_NETWORK_ID: u32 = 5;
45
46pub const AI_MAINNET_ID: u32 = 36963;
48pub const AI_TESTNET_ID: u32 = 36964;
49
50pub const BLOCK_TIME_MS: u64 = 500; pub const QUORUM_THRESHOLD: f64 = 0.69; pub const FINALITY_ROUNDS: u32 = 2; #[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct LedgerConfig {
58 pub network: NetworkType,
60 pub consensus_rpc: String,
62 pub bootstrap_peers: Vec<String>,
64 pub block_time_ms: u64,
66 pub quantum_safe: bool,
68 pub security_level: u8,
70}
71
72impl LedgerConfig {
73 pub fn mainnet() -> Self {
74 Self {
75 network: NetworkType::HanzoMainnet,
76 consensus_rpc: "https://consensus.hanzo.network".to_string(),
77 bootstrap_peers: vec![
78 "/dns4/boot1.hanzo.network/tcp/3691".to_string(),
79 "/dns4/boot2.hanzo.network/tcp/3691".to_string(),
80 "/dns4/boot3.hanzo.network/tcp/3691".to_string(),
81 ],
82 block_time_ms: BLOCK_TIME_MS,
83 quantum_safe: true,
84 security_level: 3, }
86 }
87
88 pub fn testnet() -> Self {
89 Self {
90 network: NetworkType::HanzoTestnet,
91 consensus_rpc: "https://consensus.hanzo-test.network".to_string(),
92 bootstrap_peers: vec![
93 "/dns4/boot1.hanzo-test.network/tcp/3691".to_string(),
94 ],
95 block_time_ms: BLOCK_TIME_MS,
96 quantum_safe: true,
97 security_level: 3,
98 }
99 }
100
101 pub fn zoo_mainnet() -> Self {
102 Self {
103 network: NetworkType::ZooMainnet,
104 consensus_rpc: "https://consensus.zoo.network".to_string(),
105 bootstrap_peers: vec![
106 "/dns4/boot1.zoo.network/tcp/3691".to_string(),
107 "/dns4/boot2.zoo.network/tcp/3691".to_string(),
108 ],
109 block_time_ms: BLOCK_TIME_MS,
110 quantum_safe: true,
111 security_level: 3,
112 }
113 }
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct BlockHeader {
119 pub height: u64,
121 pub parent_hash: [u8; 32],
123 pub hash: [u8; 32],
125 pub timestamp: u64,
127 pub proposer: Vec<u8>,
129 pub tx_root: [u8; 32],
131 pub state_root: [u8; 32],
133 pub tx_count: u32,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139pub enum MiningTransaction {
140 RegisterMiner {
142 public_key: Vec<u8>,
144 capabilities: Vec<u8>,
146 stats: PerformanceStats,
148 signature: Vec<u8>,
150 },
151 SubmitProof {
153 miner: Vec<u8>,
155 reward_type: MiningRewardType,
157 proof: Vec<u8>,
159 signature: Vec<u8>,
161 },
162 ClaimReward {
164 miner: Vec<u8>,
166 amount: u128,
168 recipient: String,
170 proof: Vec<u8>,
172 signature: Vec<u8>,
174 },
175 TeleportOut {
177 from: Vec<u8>,
179 destination: TeleportDestination,
181 to_address: String,
183 amount: u128,
185 signature: Vec<u8>,
187 },
188 TeleportIn {
190 source_chain: u64,
192 source_tx: String,
194 recipient: Vec<u8>,
196 amount: u128,
198 relay_signature: Vec<u8>,
200 },
201 UpdateMiner {
203 miner: Vec<u8>,
205 capabilities: Option<Vec<u8>>,
207 stats: Option<PerformanceStats>,
209 signature: Vec<u8>,
211 },
212 Vote {
214 voter: Vec<u8>,
216 block_hash: [u8; 32],
218 vote_type: VoteType,
220 signature: Vec<u8>,
222 },
223}
224
225#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
227pub enum VoteType {
228 Preference,
230 Commit,
232 Cancel,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
238pub enum TransactionStatus {
239 Pending,
241 InMempool,
243 Included { block_height: u64 },
245 Finalized { block_height: u64 },
247 Failed { reason: String },
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct MinerState {
254 pub public_key: Vec<u8>,
256 pub address: String,
258 pub total_earned: u128,
260 pub pending_rewards: u128,
262 pub registered_at: u64,
264 pub last_active: u64,
266 pub reputation: u64,
268 pub jobs_completed: u64,
270 pub stats: PerformanceStats,
272 pub capabilities: Vec<u8>,
274}
275
276pub struct MiningLedger {
278 config: LedgerConfig,
280 current_height: Arc<RwLock<u64>>,
282 miners: Arc<RwLock<HashMap<String, MinerState>>>,
284 pending_txs: Arc<RwLock<Vec<(String, MiningTransaction)>>>,
286 connected: Arc<RwLock<bool>>,
288 http_client: reqwest::Client,
290}
291
292impl MiningLedger {
293 pub async fn connect(config: LedgerConfig) -> Result<Self, LedgerError> {
295 let ledger = Self {
296 config,
297 current_height: Arc::new(RwLock::new(0)),
298 miners: Arc::new(RwLock::new(HashMap::new())),
299 pending_txs: Arc::new(RwLock::new(Vec::new())),
300 connected: Arc::new(RwLock::new(false)),
301 http_client: reqwest::Client::new(),
302 };
303
304 ledger.sync_state().await?;
306 *ledger.connected.write().await = true;
307
308 Ok(ledger)
309 }
310
311 async fn sync_state(&self) -> Result<(), LedgerError> {
313 let height = self.get_block_height().await?;
315 *self.current_height.write().await = height;
316 Ok(())
317 }
318
319 pub async fn get_block_height(&self) -> Result<u64, LedgerError> {
321 let response = self.rpc_call("ledger.getHeight", serde_json::json!({})).await?;
322 let height = response.get("height")
323 .and_then(|h| h.as_u64())
324 .unwrap_or(0);
325 Ok(height)
326 }
327
328 pub async fn register_miner(
330 &self,
331 public_key: &[u8],
332 capabilities: &[u8],
333 stats: &PerformanceStats,
334 signature: &[u8],
335 ) -> Result<String, LedgerError> {
336 let tx = MiningTransaction::RegisterMiner {
337 public_key: public_key.to_vec(),
338 capabilities: capabilities.to_vec(),
339 stats: stats.clone(),
340 signature: signature.to_vec(),
341 };
342
343 self.submit_transaction(tx).await
344 }
345
346 pub async fn submit_proof(
348 &self,
349 miner: &[u8],
350 reward_type: MiningRewardType,
351 proof: &[u8],
352 signature: &[u8],
353 ) -> Result<String, LedgerError> {
354 let tx = MiningTransaction::SubmitProof {
355 miner: miner.to_vec(),
356 reward_type,
357 proof: proof.to_vec(),
358 signature: signature.to_vec(),
359 };
360
361 self.submit_transaction(tx).await
362 }
363
364 pub async fn claim_rewards(
366 &self,
367 miner: &[u8],
368 amount: u128,
369 recipient: &str,
370 proof: &[u8],
371 signature: &[u8],
372 ) -> Result<String, LedgerError> {
373 let tx = MiningTransaction::ClaimReward {
374 miner: miner.to_vec(),
375 amount,
376 recipient: recipient.to_string(),
377 proof: proof.to_vec(),
378 signature: signature.to_vec(),
379 };
380
381 self.submit_transaction(tx).await
382 }
383
384 pub async fn teleport_out(
386 &self,
387 from: &[u8],
388 destination: TeleportDestination,
389 to_address: &str,
390 amount: u128,
391 signature: &[u8],
392 ) -> Result<TeleportTransfer, LedgerError> {
393 let tx = MiningTransaction::TeleportOut {
394 from: from.to_vec(),
395 destination: destination.clone(),
396 to_address: to_address.to_string(),
397 amount,
398 signature: signature.to_vec(),
399 };
400
401 let tx_hash = self.submit_transaction(tx).await?;
402
403 Ok(TeleportTransfer {
404 teleport_id: tx_hash.clone(),
405 amount,
406 from_address: hex::encode(from),
407 to_address: to_address.to_string(),
408 destination,
409 status: TeleportStatus::Initiated,
410 protocol_tx: Some(tx_hash),
411 evm_tx: None,
412 initiated_at: std::time::SystemTime::now()
413 .duration_since(std::time::UNIX_EPOCH)
414 .unwrap()
415 .as_secs(),
416 completed_at: None,
417 })
418 }
419
420 pub async fn get_miner_state(&self, address: &str) -> Result<Option<MinerState>, LedgerError> {
422 if let Some(state) = self.miners.read().await.get(address) {
424 return Ok(Some(state.clone()));
425 }
426
427 let response = self.rpc_call(
429 "ledger.getMiner",
430 serde_json::json!({ "address": address }),
431 ).await?;
432
433 if response.is_null() {
434 return Ok(None);
435 }
436
437 let state: MinerState = serde_json::from_value(response)
438 .map_err(|e| LedgerError::InvalidResponse(e.to_string()))?;
439
440 self.miners.write().await.insert(address.to_string(), state.clone());
442
443 Ok(Some(state))
444 }
445
446 pub async fn get_pending_rewards(&self, miner: &[u8]) -> Result<u128, LedgerError> {
448 let address = derive_address_from_pubkey(miner);
449
450 let response = self.rpc_call(
451 "ledger.getPendingRewards",
452 serde_json::json!({ "address": address }),
453 ).await?;
454
455 let rewards = response.get("rewards")
456 .and_then(|r| r.as_str())
457 .and_then(|s| s.parse::<u128>().ok())
458 .unwrap_or(0);
459
460 Ok(rewards)
461 }
462
463 pub async fn get_teleport_status(&self, teleport_id: &str) -> Result<TeleportStatus, LedgerError> {
465 let response = self.rpc_call(
466 "ledger.getTeleportStatus",
467 serde_json::json!({ "id": teleport_id }),
468 ).await?;
469
470 let status_str = response.get("status")
471 .and_then(|s| s.as_str())
472 .unwrap_or("unknown");
473
474 let status = match status_str {
475 "initiated" => TeleportStatus::Initiated,
476 "pending_confirmation" => TeleportStatus::PendingConfirmation,
477 "processing" => TeleportStatus::Processing,
478 "minting" => TeleportStatus::Minting,
479 "completed" => TeleportStatus::Completed,
480 other => TeleportStatus::Failed(format!("Unknown status: {}", other)),
481 };
482
483 Ok(status)
484 }
485
486 pub async fn submit_vote(
488 &self,
489 voter: &[u8],
490 block_hash: [u8; 32],
491 vote_type: VoteType,
492 signature: &[u8],
493 ) -> Result<(), LedgerError> {
494 let tx = MiningTransaction::Vote {
495 voter: voter.to_vec(),
496 block_hash,
497 vote_type,
498 signature: signature.to_vec(),
499 };
500
501 self.submit_transaction(tx).await?;
502 Ok(())
503 }
504
505 pub async fn get_transaction_status(&self, tx_hash: &str) -> Result<TransactionStatus, LedgerError> {
507 let response = self.rpc_call(
508 "ledger.getTransactionStatus",
509 serde_json::json!({ "hash": tx_hash }),
510 ).await?;
511
512 let status_str = response.get("status")
513 .and_then(|s| s.as_str())
514 .unwrap_or("unknown");
515
516 let status = match status_str {
517 "pending" => TransactionStatus::Pending,
518 "mempool" => TransactionStatus::InMempool,
519 "included" => {
520 let height = response.get("block_height")
521 .and_then(|h| h.as_u64())
522 .unwrap_or(0);
523 TransactionStatus::Included { block_height: height }
524 }
525 "finalized" => {
526 let height = response.get("block_height")
527 .and_then(|h| h.as_u64())
528 .unwrap_or(0);
529 TransactionStatus::Finalized { block_height: height }
530 }
531 _ => {
532 let reason = response.get("reason")
533 .and_then(|r| r.as_str())
534 .unwrap_or("Unknown error")
535 .to_string();
536 TransactionStatus::Failed { reason }
537 }
538 };
539
540 Ok(status)
541 }
542
543 pub async fn subscribe_blocks(&self, callback: impl Fn(BlockHeader) + Send + Sync + 'static) {
545 let connected = self.connected.clone();
546 let height = self.current_height.clone();
547 let rpc_url = self.config.consensus_rpc.clone();
548
549 tokio::spawn(async move {
550 let client = reqwest::Client::new();
551 let mut last_height = 0u64;
552
553 while *connected.read().await {
554 tokio::time::sleep(tokio::time::Duration::from_millis(BLOCK_TIME_MS)).await;
556
557 let current = *height.read().await;
558 if current > last_height {
559 if let Ok(response) = client.post(&rpc_url)
561 .json(&serde_json::json!({
562 "jsonrpc": "2.0",
563 "method": "ledger.getBlock",
564 "params": { "height": current },
565 "id": 1
566 }))
567 .send()
568 .await
569 {
570 if let Ok(json) = response.json::<serde_json::Value>().await {
571 if let Ok(header) = serde_json::from_value::<BlockHeader>(
572 json.get("result").cloned().unwrap_or_default()
573 ) {
574 callback(header);
575 }
576 }
577 }
578 last_height = current;
579 }
580 }
581 });
582 }
583
584 async fn submit_transaction(&self, tx: MiningTransaction) -> Result<String, LedgerError> {
586 let tx_bytes = serde_json::to_vec(&tx)
587 .map_err(|e| LedgerError::SerializationError(e.to_string()))?;
588
589 let tx_hash = hex::encode(blake3::hash(&tx_bytes).as_bytes());
590
591 self.pending_txs.write().await.push((tx_hash.clone(), tx.clone()));
593
594 let response = self.rpc_call(
596 "ledger.submitTransaction",
597 serde_json::json!({
598 "tx": hex::encode(&tx_bytes),
599 }),
600 ).await?;
601
602 let network_hash = response.get("hash")
603 .and_then(|h| h.as_str())
604 .unwrap_or(&tx_hash)
605 .to_string();
606
607 Ok(network_hash)
608 }
609
610 async fn rpc_call(&self, method: &str, params: serde_json::Value) -> Result<serde_json::Value, LedgerError> {
612 let request = serde_json::json!({
613 "jsonrpc": "2.0",
614 "method": method,
615 "params": params,
616 "id": 1
617 });
618
619 let response = self.http_client
620 .post(&self.config.consensus_rpc)
621 .json(&request)
622 .send()
623 .await
624 .map_err(|e| LedgerError::NetworkError(e.to_string()))?;
625
626 let json: serde_json::Value = response.json().await
627 .map_err(|e| LedgerError::NetworkError(e.to_string()))?;
628
629 if let Some(error) = json.get("error") {
630 return Err(LedgerError::RpcError(error.to_string()));
631 }
632
633 Ok(json.get("result").cloned().unwrap_or_default())
634 }
635
636 pub async fn get_stats(&self) -> LedgerStats {
638 LedgerStats {
639 network: self.config.network.clone(),
640 current_height: *self.current_height.read().await,
641 connected: *self.connected.read().await,
642 miners_cached: self.miners.read().await.len(),
643 pending_txs: self.pending_txs.read().await.len(),
644 quantum_safe: self.config.quantum_safe,
645 }
646 }
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
651pub struct LedgerStats {
652 pub network: NetworkType,
653 pub current_height: u64,
654 pub connected: bool,
655 pub miners_cached: usize,
656 pub pending_txs: usize,
657 pub quantum_safe: bool,
658}
659
660#[derive(Debug, thiserror::Error)]
662pub enum LedgerError {
663 #[error("Network error: {0}")]
664 NetworkError(String),
665 #[error("RPC error: {0}")]
666 RpcError(String),
667 #[error("Invalid response: {0}")]
668 InvalidResponse(String),
669 #[error("Serialization error: {0}")]
670 SerializationError(String),
671 #[error("Transaction failed: {0}")]
672 TransactionFailed(String),
673 #[error("Not connected to network")]
674 NotConnected,
675 #[error("Invalid signature")]
676 InvalidSignature,
677 #[error("Insufficient balance")]
678 InsufficientBalance,
679}
680
681pub fn derive_address_from_pubkey(pubkey: &[u8]) -> String {
683 let hash = blake3::hash(pubkey);
684 format!("0x{}", hex::encode(&hash.as_bytes()[..20]))
685}
686
687pub fn verify_quantum_signature(pubkey: &[u8], message: &[u8], signature: &[u8]) -> bool {
689 !pubkey.is_empty() && !message.is_empty() && !signature.is_empty()
692}
693
694#[cfg(test)]
695mod tests {
696 use super::*;
697
698 #[test]
699 fn test_ledger_config() {
700 let config = LedgerConfig::mainnet();
701 assert!(config.quantum_safe);
702 assert_eq!(config.security_level, 3);
703 assert!(!config.bootstrap_peers.is_empty());
704 }
705
706 #[test]
707 fn test_derive_address() {
708 let pubkey = vec![1u8; 32];
709 let address = derive_address_from_pubkey(&pubkey);
710 assert!(address.starts_with("0x"));
711 assert_eq!(address.len(), 42); }
713
714 #[test]
715 fn test_vote_types() {
716 assert_eq!(VoteType::Preference, VoteType::Preference);
717 assert_ne!(VoteType::Commit, VoteType::Cancel);
718 }
719
720 #[test]
721 fn test_transaction_status() {
722 let status = TransactionStatus::Finalized { block_height: 100 };
723 match status {
724 TransactionStatus::Finalized { block_height } => {
725 assert_eq!(block_height, 100);
726 }
727 _ => panic!("Wrong status"),
728 }
729 }
730}