From 0da94d2784a8c1ee3bbc09005644f174f4352b2c Mon Sep 17 00:00:00 2001 From: BossChaos Date: Sat, 9 May 2026 01:06:09 +0800 Subject: [PATCH 1/2] fix: apply cargo fmt to all Rust packages --- cross-chain-airdrop/src/bin/airdrop_cli.rs | 56 +++++--- cross-chain-airdrop/src/bridge_client.rs | 50 ++++--- cross-chain-airdrop/src/chain_adapter.rs | 132 +++++++++++------- cross-chain-airdrop/src/claim_store.rs | 111 +++++++++------ cross-chain-airdrop/src/github_verifier.rs | 45 +++--- cross-chain-airdrop/src/lib.rs | 5 +- cross-chain-airdrop/src/models.rs | 39 +++--- cross-chain-airdrop/src/pipeline.rs | 8 +- .../tests/integration_tests.rs | 34 +++-- miners/rust/src/fingerprint.rs | 38 +++-- miners/rust/src/main.rs | 17 ++- rustchain-miner/src/arch_tests.rs | 58 ++++---- rustchain-miner/src/attestation.rs | 88 +++++++----- rustchain-miner/src/hardware.rs | 27 +++- rustchain-miner/src/lib.rs | 10 +- rustchain-miner/src/main.rs | 19 ++- rustchain-miner/src/miner.rs | 66 +++++++-- rustchain-miner/src/transport.rs | 20 ++- rustchain-wallet/src/bin/rtc_wallet.rs | 17 ++- rustchain-wallet/src/client.rs | 7 +- rustchain-wallet/src/keys.rs | 2 +- rustchain-wallet/src/transaction.rs | 31 ++-- 22 files changed, 555 insertions(+), 325 deletions(-) diff --git a/cross-chain-airdrop/src/bin/airdrop_cli.rs b/cross-chain-airdrop/src/bin/airdrop_cli.rs index f6dadc0b5..1fbee7d70 100644 --- a/cross-chain-airdrop/src/bin/airdrop_cli.rs +++ b/cross-chain-airdrop/src/bin/airdrop_cli.rs @@ -101,8 +101,7 @@ async fn main() -> Result<()> { .with_target(false) .without_time() .finish(); - tracing::subscriber::set_global_default(subscriber) - .expect("Failed to set tracing subscriber"); + tracing::subscriber::set_global_default(subscriber).expect("Failed to set tracing subscriber"); // Load configuration let mut config = AirdropConfig::from_env()?; @@ -151,15 +150,9 @@ async fn main() -> Result<()> { if eligibility.eligible { println!("✅ ELIGIBLE for airdrop!"); - println!( - " Base allocation: {} wRTC", - eligibility.base_allocation - ); + println!(" Base allocation: {} wRTC", eligibility.base_allocation); println!(" Wallet multiplier: {:.1}x", eligibility.multiplier); - println!( - " Final allocation: {} wRTC", - eligibility.final_allocation - ); + println!(" Final allocation: {} wRTC", eligibility.final_allocation); if let Some(ref gh) = eligibility.github { println!(" GitHub tier: {:?}", gh.tier); @@ -237,10 +230,13 @@ async fn main() -> Result<()> { Commands::VerifyAddress { chain, address } => { let target_chain = parse_chain(&chain)?; - let adapter = match target_chain { - TargetChain::Solana => solana_adapter.as_ref() as &dyn cross_chain_airdrop::chain_adapter::ChainAdapter, - TargetChain::Base => base_adapter.as_ref() as &dyn cross_chain_airdrop::chain_adapter::ChainAdapter, - }; + let adapter = + match target_chain { + TargetChain::Solana => solana_adapter.as_ref() + as &dyn cross_chain_airdrop::chain_adapter::ChainAdapter, + TargetChain::Base => base_adapter.as_ref() + as &dyn cross_chain_airdrop::chain_adapter::ChainAdapter, + }; match adapter.validate_address(&address) { Ok(_) => { @@ -249,12 +245,23 @@ async fn main() -> Result<()> { // Also check balance and age match adapter.verify_wallet(&address).await { Ok(verification) => { - println!(" Balance: {} {}", + println!( + " Balance: {} {}", format_balance(&verification.balance_base_units, &target_chain), - chain.to_uppercase()); - println!(" Wallet age: {} days", verification.wallet_age_seconds / 86400); - println!(" Meets minimum balance: {}", verification.meets_minimum_balance); - println!(" Meets age requirement: {}", verification.meets_age_requirement); + chain.to_uppercase() + ); + println!( + " Wallet age: {} days", + verification.wallet_age_seconds / 86400 + ); + println!( + " Meets minimum balance: {}", + verification.meets_minimum_balance + ); + println!( + " Meets age requirement: {}", + verification.meets_age_requirement + ); println!(" Wallet tier: {:?}", verification.tier); } Err(e) => { @@ -274,9 +281,9 @@ async fn main() -> Result<()> { } fn parse_chain(chain: &str) -> Result { - chain.parse::().map_err(|e| { - cross_chain_airdrop::AirdropError::Parse(format!("Invalid chain: {}", e)) - }) + chain + .parse::() + .map_err(|e| cross_chain_airdrop::AirdropError::Parse(format!("Invalid chain: {}", e))) } fn format_balance(balance_base_units: &u64, chain: &TargetChain) -> String { @@ -287,7 +294,10 @@ fn format_balance(balance_base_units: &u64, chain: &TargetChain) -> String { } TargetChain::Base => { // ETH has 18 decimals - format!("{:.18}", *balance_base_units as f64 / 1_000_000_000_000_000_000.0) + format!( + "{:.18}", + *balance_base_units as f64 / 1_000_000_000_000_000_000.0 + ) } } } diff --git a/cross-chain-airdrop/src/bridge_client.rs b/cross-chain-airdrop/src/bridge_client.rs index 1719f7748..a49ea8018 100644 --- a/cross-chain-airdrop/src/bridge_client.rs +++ b/cross-chain-airdrop/src/bridge_client.rs @@ -65,9 +65,10 @@ impl BridgeClient { request = request.json(&body); - let response = request.send().await.map_err(|e| { - AirdropError::Bridge(format!("Failed to lock RTC: {}", e)) - })?; + let response = request + .send() + .await + .map_err(|e| AirdropError::Bridge(format!("Failed to lock RTC: {}", e)))?; if !response.status().is_success() { let status = response.status(); @@ -78,9 +79,10 @@ impl BridgeClient { ))); } - let lock_response: BridgeLockResponse = response.json().await.map_err(|e| { - AirdropError::Bridge(format!("Failed to parse lock response: {}", e)) - })?; + let lock_response: BridgeLockResponse = response + .json() + .await + .map_err(|e| AirdropError::Bridge(format!("Failed to parse lock response: {}", e)))?; Ok(lock_response) } @@ -107,9 +109,10 @@ impl BridgeClient { "notes": notes, })); - let response = request.send().await.map_err(|e| { - AirdropError::Bridge(format!("Failed to confirm lock: {}", e)) - })?; + let response = request + .send() + .await + .map_err(|e| AirdropError::Bridge(format!("Failed to confirm lock: {}", e)))?; if !response.status().is_success() { let status = response.status(); @@ -186,9 +189,10 @@ impl BridgeClient { ))); } - let status: BridgeLockStatus = response.json().await.map_err(|e| { - AirdropError::Bridge(format!("Failed to parse lock status: {}", e)) - })?; + let status: BridgeLockStatus = response + .json() + .await + .map_err(|e| AirdropError::Bridge(format!("Failed to parse lock status: {}", e)))?; Ok(status) } @@ -211,9 +215,10 @@ impl BridgeClient { ))); } - let stats: BridgeStats = response.json().await.map_err(|e| { - AirdropError::Bridge(format!("Failed to parse bridge stats: {}", e)) - })?; + let stats: BridgeStats = response + .json() + .await + .map_err(|e| AirdropError::Bridge(format!("Failed to parse bridge stats: {}", e)))?; Ok(stats) } @@ -299,9 +304,18 @@ mod tests { #[test] fn test_bridge_state_conversion() { - assert_eq!(bridge_state_to_claim_state("requested"), ClaimStatus::Pending); - assert_eq!(bridge_state_to_claim_state("confirmed"), ClaimStatus::Verified); - assert_eq!(bridge_state_to_claim_state("complete"), ClaimStatus::Complete); + assert_eq!( + bridge_state_to_claim_state("requested"), + ClaimStatus::Pending + ); + assert_eq!( + bridge_state_to_claim_state("confirmed"), + ClaimStatus::Verified + ); + assert_eq!( + bridge_state_to_claim_state("complete"), + ClaimStatus::Complete + ); assert_eq!(bridge_state_to_claim_state("failed"), ClaimStatus::Failed); } } diff --git a/cross-chain-airdrop/src/chain_adapter.rs b/cross-chain-airdrop/src/chain_adapter.rs index 1825ea62c..8eb231c53 100644 --- a/cross-chain-airdrop/src/chain_adapter.rs +++ b/cross-chain-airdrop/src/chain_adapter.rs @@ -1,7 +1,7 @@ //! Chain adapter interfaces for Solana and Base L2 use crate::error::Result; -use crate::models::{TargetChain, WalletVerification, WalletTier}; +use crate::models::{TargetChain, WalletTier, WalletVerification}; use async_trait::async_trait; use chrono::{DateTime, Utc}; @@ -51,7 +51,7 @@ impl SolanaAdapter { Self { rpc_url, min_balance_lamports: 100_000_000, // 0.1 SOL - min_age_seconds: 7 * 24 * 60 * 60, // 7 days + min_age_seconds: 7 * 24 * 60 * 60, // 7 days } } } @@ -102,12 +102,14 @@ impl ChainAdapter for SolanaAdapter { .await .map_err(|e| { crate::error::AirdropError::WalletVerification(format!( - "Solana RPC request failed: {}", e + "Solana RPC request failed: {}", + e )) })?; let result: serde_json::Value = response.json().await.map_err(|e| { crate::error::AirdropError::WalletVerification(format!( - "Solana RPC response parse failed: {}", e + "Solana RPC response parse failed: {}", + e )) })?; Ok(result["result"]["value"].as_u64().unwrap_or(0)) @@ -126,9 +128,10 @@ impl ChainAdapter for SolanaAdapter { fn validate_address(&self, address: &str) -> Result<()> { // Solana addresses are base58-encoded, 32-44 characters if address.len() < 32 || address.len() > 44 { - return Err(crate::error::AirdropError::WalletVerification( - format!("Invalid Solana address length: {}", address.len()), - )); + return Err(crate::error::AirdropError::WalletVerification(format!( + "Invalid Solana address length: {}", + address.len() + ))); } // Basic base58 validation (no 0, O, I, l) @@ -145,9 +148,10 @@ impl ChainAdapter for SolanaAdapter { Ok(_) => Err(crate::error::AirdropError::WalletVerification( "Solana address must decode to 32 bytes".to_string(), )), - Err(e) => Err(crate::error::AirdropError::WalletVerification( - format!("Invalid base58 encoding: {}", e), - )), + Err(e) => Err(crate::error::AirdropError::WalletVerification(format!( + "Invalid base58 encoding: {}", + e + ))), } } @@ -187,7 +191,7 @@ impl BaseAdapter { Self { rpc_url, min_balance_wei: 10_000_000_000_000_000, // 0.01 ETH - min_age_seconds: 7 * 24 * 60 * 60, // 7 days + min_age_seconds: 7 * 24 * 60 * 60, // 7 days } } } @@ -238,21 +242,23 @@ impl ChainAdapter for BaseAdapter { .await .map_err(|e| { crate::error::AirdropError::WalletVerification(format!( - "Base RPC request failed: {}", e + "Base RPC request failed: {}", + e )) })?; let result: serde_json::Value = response.json().await.map_err(|e| { crate::error::AirdropError::WalletVerification(format!( - "Base RPC response parse failed: {}", e + "Base RPC response parse failed: {}", + e )) })?; let balance_hex = result["result"].as_str().unwrap_or("0x0"); - u64::from_str_radix(balance_hex.trim_start_matches("0x"), 16) - .map_err(|e| { - crate::error::AirdropError::WalletVerification(format!( - "Base balance hex parse failed: {}", e - )) - }) + u64::from_str_radix(balance_hex.trim_start_matches("0x"), 16).map_err(|e| { + crate::error::AirdropError::WalletVerification(format!( + "Base balance hex parse failed: {}", + e + )) + }) } async fn get_wallet_age(&self, _address: &str) -> Result { @@ -272,9 +278,10 @@ impl ChainAdapter for BaseAdapter { let hex_part = &address[2..]; if hex_part.len() != 40 { - return Err(crate::error::AirdropError::WalletVerification( - format!("Invalid Base address length: {} (expected 42)", address.len()), - )); + return Err(crate::error::AirdropError::WalletVerification(format!( + "Invalid Base address length: {} (expected 42)", + address.len() + ))); } // Validate hex characters @@ -321,8 +328,9 @@ mod tests { #[test] fn test_solana_address_validation_valid() { - let adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); - + let adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + // Valid Solana addresses assert!(adapter .validate_address("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") @@ -334,13 +342,16 @@ mod tests { #[test] fn test_solana_address_validation_invalid() { - let adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); - + let adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + // Too short assert!(adapter.validate_address("tooshort").is_err()); - + // Invalid base58 chars - assert!(adapter.validate_address("0xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").is_err()); + assert!(adapter + .validate_address("0xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") + .is_err()); } #[test] @@ -359,15 +370,15 @@ mod tests { #[test] fn test_base_address_validation_invalid() { let adapter = BaseAdapter::with_defaults("https://mainnet.base.org".to_string()); - + // Missing 0x prefix assert!(adapter .validate_address("742d35Cc6634C0532925a3b844Bc9e7595f0bEb") .is_err()); - + // Wrong length assert!(adapter.validate_address("0x1234").is_err()); - + // Invalid hex assert!(adapter .validate_address("0xGGGG567890123456789012345678901234567890") @@ -376,23 +387,18 @@ mod tests { #[test] fn test_solana_tier_calculation() { - let adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); - + let adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + // 0.05 SOL (below minimum) - assert_eq!( - adapter.calculate_tier(50_000_000), - WalletTier::Minimum - ); - + assert_eq!(adapter.calculate_tier(50_000_000), WalletTier::Minimum); + // 0.5 SOL - assert_eq!( - adapter.calculate_tier(500_000_000), - WalletTier::Minimum - ); - + assert_eq!(adapter.calculate_tier(500_000_000), WalletTier::Minimum); + // 5 SOL assert_eq!(adapter.calculate_tier(5_000_000_000), WalletTier::Mid); - + // 50 SOL assert_eq!(adapter.calculate_tier(50_000_000_000), WalletTier::High); } @@ -414,7 +420,10 @@ mod tests { ); // 0.5 ETH - assert_eq!(adapter.calculate_tier(500_000_000_000_000_000), WalletTier::Mid); + assert_eq!( + adapter.calculate_tier(500_000_000_000_000_000), + WalletTier::Mid + ); // 5 ETH assert_eq!( @@ -439,7 +448,10 @@ mod tests { .await; let adapter = SolanaAdapter::new(mock.url(), 100_000_000, 7 * 24 * 60 * 60); - let balance = adapter.get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").await.unwrap(); + let balance = adapter + .get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") + .await + .unwrap(); assert_eq!(balance, 350_000_000); // 0.35 SOL } @@ -455,15 +467,22 @@ mod tests { .await; let adapter = SolanaAdapter::new(mock.url(), 100_000_000, 7 * 24 * 60 * 60); - let balance = adapter.get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").await.unwrap(); + let balance = adapter + .get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") + .await + .unwrap(); assert_eq!(balance, 0); } #[tokio::test] async fn test_solana_get_wallet_age_returns_zero() { - let adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + let adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); // Age is conservatively 0 since it requires historical tx data - let age = adapter.get_wallet_age("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").await.unwrap(); + let age = adapter + .get_wallet_age("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") + .await + .unwrap(); assert_eq!(age, 0); } @@ -479,7 +498,10 @@ mod tests { .await; let adapter = BaseAdapter::new(mock.url(), 10_000_000_000_000_000, 7 * 24 * 60 * 60); - let balance = adapter.get_balance("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1").await.unwrap(); + let balance = adapter + .get_balance("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1") + .await + .unwrap(); assert_eq!(balance, 100_000_000_000_000_000); // 0.1 ETH } @@ -495,7 +517,10 @@ mod tests { .await; let adapter = BaseAdapter::new(mock.url(), 10_000_000_000_000_000, 7 * 24 * 60 * 60); - let balance = adapter.get_balance("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1").await.unwrap(); + let balance = adapter + .get_balance("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1") + .await + .unwrap(); assert_eq!(balance, 0); } @@ -503,7 +528,10 @@ mod tests { async fn test_base_get_wallet_age_returns_zero() { let adapter = BaseAdapter::with_defaults("https://mainnet.base.org".to_string()); // Age is conservatively 0 since it requires historical tx data - let age = adapter.get_wallet_age("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1").await.unwrap(); + let age = adapter + .get_wallet_age("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1") + .await + .unwrap(); assert_eq!(age, 0); } } diff --git a/cross-chain-airdrop/src/claim_store.rs b/cross-chain-airdrop/src/claim_store.rs index c5a200db0..6a5098a8f 100644 --- a/cross-chain-airdrop/src/claim_store.rs +++ b/cross-chain-airdrop/src/claim_store.rs @@ -165,7 +165,10 @@ impl ClaimStore for InMemoryClaimStore { claim.rejection_reason = rejection_reason; Ok(()) } else { - Err(AirdropError::Claim(format!("Claim not found: {}", claim_id))) + Err(AirdropError::Claim(format!( + "Claim not found: {}", + claim_id + ))) } } @@ -195,9 +198,8 @@ pub struct SqliteClaimStore { impl SqliteClaimStore { /// Open (or create) a SQLite database at the given path. pub fn open(path: &str) -> Result { - let conn = rusqlite::Connection::open(path).map_err(|e| { - AirdropError::Claim(format!("Failed to open claim store DB: {}", e)) - })?; + let conn = rusqlite::Connection::open(path) + .map_err(|e| AirdropError::Claim(format!("Failed to open claim store DB: {}", e)))?; conn.execute_batch( " @@ -228,9 +230,10 @@ impl SqliteClaimStore { #[cfg(feature = "sqlite-store")] impl ClaimStore for SqliteClaimStore { fn is_github_claimed(&self, github_id: u64) -> Result { - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; let mut stmt = conn .prepare("SELECT COUNT(*) FROM claims WHERE github_id = ?") .map_err(|e| AirdropError::Claim(format!("SQL prepare error: {}", e)))?; @@ -241,9 +244,10 @@ impl ClaimStore for SqliteClaimStore { } fn is_wallet_claimed(&self, chain: &str, address: &str) -> Result { - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; let mut stmt = conn .prepare("SELECT COUNT(*) FROM claims WHERE chain = ? AND address = ?") .map_err(|e| AirdropError::Claim(format!("SQL prepare error: {}", e)))?; @@ -260,18 +264,24 @@ impl ClaimStore for SqliteClaimStore { address: &str, record: ClaimRecord, ) -> Result<()> { - let json = serde_json::to_string(&record).map_err(|e| { - AirdropError::Claim(format!("Failed to serialize claim: {}", e)) - })?; + let json = serde_json::to_string(&record) + .map_err(|e| AirdropError::Claim(format!("Failed to serialize claim: {}", e)))?; - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; conn.execute( "INSERT INTO claims (claim_id, github_id, chain, address, record_json) VALUES (?, ?, ?, ?, ?)", - [&record.claim_id, &github_id.to_string(), chain, address, &json], + [ + &record.claim_id, + &github_id.to_string(), + chain, + address, + &json, + ], ) .map_err(|e: rusqlite::Error| { let msg = e.to_string(); @@ -296,9 +306,10 @@ impl ClaimStore for SqliteClaimStore { } fn get_claim(&self, claim_id: &str) -> Result> { - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; let mut stmt = conn .prepare("SELECT record_json FROM claims WHERE claim_id = ?") .map_err(|e| AirdropError::Claim(format!("SQL prepare error: {}", e)))?; @@ -324,9 +335,10 @@ impl ClaimStore for SqliteClaimStore { lock_id: Option, rejection_reason: Option, ) -> Result<()> { - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; let mut stmt = conn .prepare("SELECT record_json FROM claims WHERE claim_id = ?") @@ -341,9 +353,8 @@ impl ClaimStore for SqliteClaimStore { other => AirdropError::Claim(format!("SQL query error: {}", other)), })?; - let mut record: ClaimRecord = serde_json::from_str(&json).map_err(|e| { - AirdropError::Claim(format!("Failed to deserialize claim: {}", e)) - })?; + let mut record: ClaimRecord = serde_json::from_str(&json) + .map_err(|e| AirdropError::Claim(format!("Failed to deserialize claim: {}", e)))?; record.status = status; record.updated_at = Utc::now(); @@ -352,9 +363,8 @@ impl ClaimStore for SqliteClaimStore { } record.rejection_reason = rejection_reason; - let json = serde_json::to_string(&record).map_err(|e| { - AirdropError::Claim(format!("Failed to serialize claim: {}", e)) - })?; + let json = serde_json::to_string(&record) + .map_err(|e| AirdropError::Claim(format!("Failed to serialize claim: {}", e)))?; conn.execute( "UPDATE claims SET record_json = ? WHERE claim_id = ?", [&json, claim_id], @@ -365,9 +375,10 @@ impl ClaimStore for SqliteClaimStore { } fn get_claims(&self) -> Result> { - let conn = self.conn.lock().map_err(|e| { - AirdropError::Claim(format!("Lock poisoning: {}", e)) - })?; + let conn = self + .conn + .lock() + .map_err(|e| AirdropError::Claim(format!("Lock poisoning: {}", e)))?; let mut stmt = conn .prepare("SELECT record_json FROM claims") .map_err(|e| AirdropError::Claim(format!("SQL prepare error: {}", e)))?; @@ -376,15 +387,15 @@ impl ClaimStore for SqliteClaimStore { .map_err(|e| AirdropError::Claim(format!("SQL query error: {}", e)))?; let mut claims = Vec::new(); - while let Some(row) = rows.next().map_err(|e| { - AirdropError::Claim(format!("SQL row iteration error: {}", e)) - })? { - let json: String = row.get(0).map_err(|e| { - AirdropError::Claim(format!("SQL row error: {}", e)) - })?; - let record: ClaimRecord = serde_json::from_str(&json).map_err(|e| { - AirdropError::Claim(format!("Failed to deserialize claim: {}", e)) - })?; + while let Some(row) = rows + .next() + .map_err(|e| AirdropError::Claim(format!("SQL row iteration error: {}", e)))? + { + let json: String = row + .get(0) + .map_err(|e| AirdropError::Claim(format!("SQL row error: {}", e)))?; + let record: ClaimRecord = serde_json::from_str(&json) + .map_err(|e| AirdropError::Claim(format!("Failed to deserialize claim: {}", e)))?; claims.push(record); } Ok(claims) @@ -470,7 +481,12 @@ mod tests { // Update store - .update_claim(&rec.claim_id, ClaimStatus::Complete, Some("lock-1".to_string()), None) + .update_claim( + &rec.claim_id, + ClaimStatus::Complete, + Some("lock-1".to_string()), + None, + ) .unwrap(); let updated = store.get_claim(&rec.claim_id).unwrap().unwrap(); @@ -544,7 +560,9 @@ mod tests { { let store = SqliteClaimStore::open(path.to_str().unwrap()).unwrap(); assert!(store.is_github_claimed(12345).unwrap()); - assert!(store.is_wallet_claimed("solana", "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").unwrap()); + assert!(store + .is_wallet_claimed("solana", "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU") + .unwrap()); let rec2 = test_record(); let addr2 = rec2.target_address.clone(); @@ -570,7 +588,12 @@ mod tests { assert_eq!(found.status, ClaimStatus::Pending); store - .update_claim(&rec.claim_id, ClaimStatus::Complete, Some("lock-1".to_string()), None) + .update_claim( + &rec.claim_id, + ClaimStatus::Complete, + Some("lock-1".to_string()), + None, + ) .unwrap(); let updated = store.get_claim(&rec.claim_id).unwrap().unwrap(); diff --git a/cross-chain-airdrop/src/github_verifier.rs b/cross-chain-airdrop/src/github_verifier.rs index 2c6588a17..d2c417894 100644 --- a/cross-chain-airdrop/src/github_verifier.rs +++ b/cross-chain-airdrop/src/github_verifier.rs @@ -37,9 +37,13 @@ impl GitHubVerifier { pub async fn verify(&self, oauth_token: &str) -> Result { // Get user profile let profile = self.get_user_profile(oauth_token).await?; - + // Check account age - let account_age_days = profile.created_at.signed_duration_since(Utc::now()).num_days().abs() as u64; + let account_age_days = profile + .created_at + .signed_duration_since(Utc::now()) + .num_days() + .abs() as u64; if account_age_days < self.min_account_age_days { return Err(AirdropError::GitHubVerification(format!( "GitHub account too young: {} days (minimum {})", @@ -87,9 +91,10 @@ impl GitHubVerifier { request = request.bearer_auth(token); } - let response = request.send().await.map_err(|e| { - AirdropError::GitHub(format!("Failed to fetch user profile: {}", e)) - })?; + let response = request + .send() + .await + .map_err(|e| AirdropError::GitHub(format!("Failed to fetch user profile: {}", e)))?; if !response.status().is_success() { let status = response.status(); @@ -100,9 +105,10 @@ impl GitHubVerifier { ))); } - let profile: GitHubProfileResponse = response.json().await.map_err(|e| { - AirdropError::GitHub(format!("Failed to parse user profile: {}", e)) - })?; + let profile: GitHubProfileResponse = response + .json() + .await + .map_err(|e| AirdropError::GitHub(format!("Failed to parse user profile: {}", e)))?; // Parse created_at timestamp let created_at = DateTime::parse_from_rfc3339(&profile.created_at) @@ -135,9 +141,10 @@ impl GitHubVerifier { // Request only 1 item per page to get total count efficiently request = request.query(&[("per_page", "1")]); - let response = request.send().await.map_err(|e| { - AirdropError::GitHub(format!("Failed to fetch starred repos: {}", e)) - })?; + let response = request + .send() + .await + .map_err(|e| AirdropError::GitHub(format!("Failed to fetch starred repos: {}", e)))?; if !response.status().is_success() { return Err(AirdropError::GitHub(format!( @@ -165,7 +172,7 @@ impl GitHubVerifier { // Search for merged PRs by the user in Scottcjn/Rustchain repo let query = format!("repo:Scottcjn/Rustchain type:pr author:{} is:merged", login); let per_page = "1".to_string(); - + let request = self .client .get(format!("{}/search/issues", self.api_base)) @@ -173,9 +180,10 @@ impl GitHubVerifier { .header("User-Agent", "RustChain-Airdrop") .query(&[("q", &query), ("per_page", &per_page)]); - let response = request.send().await.map_err(|e| { - AirdropError::GitHub(format!("Failed to fetch merged PRs: {}", e)) - })?; + let response = request + .send() + .await + .map_err(|e| AirdropError::GitHub(format!("Failed to fetch merged PRs: {}", e)))?; if !response.status().is_success() { return Err(AirdropError::GitHub(format!( @@ -184,9 +192,10 @@ impl GitHubVerifier { ))); } - let result: SearchResponse = response.json().await.map_err(|e| { - AirdropError::GitHub(format!("Failed to parse search results: {}", e)) - })?; + let result: SearchResponse = response + .json() + .await + .map_err(|e| AirdropError::GitHub(format!("Failed to parse search results: {}", e)))?; Ok(result.total_count) } diff --git a/cross-chain-airdrop/src/lib.rs b/cross-chain-airdrop/src/lib.rs index 667e573df..801b5dbda 100644 --- a/cross-chain-airdrop/src/lib.rs +++ b/cross-chain-airdrop/src/lib.rs @@ -63,9 +63,9 @@ pub mod models; pub mod pipeline; // Re-export commonly used types -pub use claim_store::{ClaimStore, InMemoryClaimStore}; #[cfg(feature = "sqlite-store")] pub use claim_store::SqliteClaimStore; +pub use claim_store::{ClaimStore, InMemoryClaimStore}; pub use config::AirdropConfig as Config; pub use error::{AirdropError, Result}; pub use github_verifier::GitHubVerifier; @@ -79,4 +79,5 @@ pub use pipeline::VerificationPipeline; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); /// RIP-305 specification reference -pub const RIP_305_SPEC: &str = "https://github.com/Scottcjn/Rustchain/blob/main/docs/RIP-305-cross-chain-airdrop.md"; +pub const RIP_305_SPEC: &str = + "https://github.com/Scottcjn/Rustchain/blob/main/docs/RIP-305-cross-chain-airdrop.md"; diff --git a/cross-chain-airdrop/src/models.rs b/cross-chain-airdrop/src/models.rs index eded4a794..035d659e8 100644 --- a/cross-chain-airdrop/src/models.rs +++ b/cross-chain-airdrop/src/models.rs @@ -35,12 +35,12 @@ impl std::str::FromStr for TargetChain { /// GitHub contribution tier for airdrop eligibility #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum GitHubTier { - Stargazer, // 10+ repos starred - Contributor, // 1+ merged PR - Builder, // 3+ merged PRs - Security, // Verified vulnerability - Core, // 5+ merged PRs or Star King badge - Miner, // Active attestation history + Stargazer, // 10+ repos starred + Contributor, // 1+ merged PR + Builder, // 3+ merged PRs + Security, // Verified vulnerability + Core, // 5+ merged PRs or Star King badge + Miner, // Active attestation history } impl GitHubTier { @@ -137,10 +137,7 @@ pub struct EligibilityResult { impl EligibilityResult { /// Create a new eligibility result - pub fn new( - github: Option, - wallet: Option, - ) -> Self { + pub fn new(github: Option, wallet: Option) -> Self { let mut rejection_reasons = Vec::new(); let mut base_allocation = 0u64; let mut multiplier = 1.0f64; @@ -224,12 +221,12 @@ pub struct ClaimResponse { /// Claim status #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum ClaimStatus { - Pending, // Awaiting admin review - Verified, // Eligibility verified, ready for bridge - Bridging, // Bridge lock in progress - Complete, // wRTC minted on target chain - Rejected, // Claim rejected - Failed, // Claim failed during processing + Pending, // Awaiting admin review + Verified, // Eligibility verified, ready for bridge + Bridging, // Bridge lock in progress + Complete, // wRTC minted on target chain + Rejected, // Claim rejected + Failed, // Claim failed during processing } impl std::fmt::Display for ClaimStatus { @@ -296,8 +293,14 @@ mod tests { #[test] fn test_target_chain_from_str() { - assert_eq!("solana".parse::().unwrap(), TargetChain::Solana); - assert_eq!("SOLANA".parse::().unwrap(), TargetChain::Solana); + assert_eq!( + "solana".parse::().unwrap(), + TargetChain::Solana + ); + assert_eq!( + "SOLANA".parse::().unwrap(), + TargetChain::Solana + ); assert_eq!("base".parse::().unwrap(), TargetChain::Base); assert_eq!("BASE".parse::().unwrap(), TargetChain::Base); assert!("ethereum".parse::().is_err()); diff --git a/cross-chain-airdrop/src/pipeline.rs b/cross-chain-airdrop/src/pipeline.rs index bec76ffd1..95ed16243 100644 --- a/cross-chain-airdrop/src/pipeline.rs +++ b/cross-chain-airdrop/src/pipeline.rs @@ -279,7 +279,7 @@ pub struct ClaimsByTier { #[cfg(test)] mod tests { use super::*; - use crate::chain_adapter::{SolanaAdapter, BaseAdapter}; + use crate::chain_adapter::{BaseAdapter, SolanaAdapter}; use std::sync::Arc; #[tokio::test] @@ -292,10 +292,8 @@ mod tests { "https://mainnet.base.org".to_string(), )); - let pipeline = VerificationPipeline::new( - github_verifier, - vec![solana_adapter, base_adapter], - ); + let pipeline = + VerificationPipeline::new(github_verifier, vec![solana_adapter, base_adapter]); let stats = pipeline.get_stats().unwrap(); assert_eq!(stats.total_claims, 0); diff --git a/cross-chain-airdrop/tests/integration_tests.rs b/cross-chain-airdrop/tests/integration_tests.rs index f904e2f53..3571d296e 100644 --- a/cross-chain-airdrop/tests/integration_tests.rs +++ b/cross-chain-airdrop/tests/integration_tests.rs @@ -96,7 +96,8 @@ fn test_eligibility_both_chains_eligible() { assert_eq!(result.final_allocation, 50); // Test Base eligibility - let wallet_base = mock_wallet_verification(TargetChain::Base, 20_000_000_000_000_000, 14 * 86400); + let wallet_base = + mock_wallet_verification(TargetChain::Base, 20_000_000_000_000_000, 14 * 86400); let result_base = EligibilityResult::new(Some(github), Some(wallet_base)); assert!(result_base.eligible); assert_eq!(result_base.final_allocation, 50); @@ -169,7 +170,8 @@ fn test_wallet_multiplier_high_tier() { #[tokio::test] async fn test_chain_adapters_validate_addresses() { - let solana_adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + let solana_adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); let base_adapter = BaseAdapter::with_defaults("https://mainnet.base.org".to_string()); // Valid addresses @@ -188,7 +190,8 @@ async fn test_chain_adapters_validate_addresses() { #[tokio::test] async fn test_chain_adapters_calculate_tiers() { - let solana_adapter = SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); + let solana_adapter = + SolanaAdapter::with_defaults("https://api.mainnet-beta.solana.com".to_string()); let base_adapter = BaseAdapter::with_defaults("https://mainnet.base.org".to_string()); // Solana tiers @@ -200,7 +203,10 @@ async fn test_chain_adapters_calculate_tiers() { solana_adapter.calculate_tier(500_000_000), WalletTier::Minimum ); - assert_eq!(solana_adapter.calculate_tier(5_000_000_000), WalletTier::Mid); + assert_eq!( + solana_adapter.calculate_tier(5_000_000_000), + WalletTier::Mid + ); assert_eq!( solana_adapter.calculate_tier(50_000_000_000), WalletTier::High @@ -237,9 +243,18 @@ fn test_github_tier_allocations() { #[test] fn test_target_chain_parsing() { - assert_eq!("solana".parse::().unwrap(), TargetChain::Solana); - assert_eq!("SOLANA".parse::().unwrap(), TargetChain::Solana); - assert_eq!("Solana".parse::().unwrap(), TargetChain::Solana); + assert_eq!( + "solana".parse::().unwrap(), + TargetChain::Solana + ); + assert_eq!( + "SOLANA".parse::().unwrap(), + TargetChain::Solana + ); + assert_eq!( + "Solana".parse::().unwrap(), + TargetChain::Solana + ); assert_eq!("base".parse::().unwrap(), TargetChain::Base); assert_eq!("BASE".parse::().unwrap(), TargetChain::Base); assert_eq!("Base".parse::().unwrap(), TargetChain::Base); @@ -268,10 +283,7 @@ async fn test_pipeline_initialization() { "https://mainnet.base.org".to_string(), )); - let pipeline = VerificationPipeline::new( - github_verifier, - vec![solana_adapter, base_adapter], - ); + let pipeline = VerificationPipeline::new(github_verifier, vec![solana_adapter, base_adapter]); let stats = pipeline.get_stats().unwrap(); assert_eq!(stats.total_claims, 0); diff --git a/miners/rust/src/fingerprint.rs b/miners/rust/src/fingerprint.rs index 7a82e4fe4..afc60a43a 100644 --- a/miners/rust/src/fingerprint.rs +++ b/miners/rust/src/fingerprint.rs @@ -3,7 +3,6 @@ /// Collects CPU identity, cache-timing signatures, clock-drift coefficients, /// and architecture detection. These values feed the attestation payload and /// are used by the node to score "proof of antiquity" (genuine old hardware). - use std::time::{Duration, Instant}; // --------------------------------------------------------------------------- @@ -100,7 +99,13 @@ pub fn get_cpu_info() -> CpuInfo { let cache_sizes = probe_cache_sizes(); let simd_features = detect_simd_features(); - CpuInfo { arch, cores, model, cache_sizes, simd_features } + CpuInfo { + arch, + cores, + model, + cache_sizes, + simd_features, + } } fn num_logical_cores() -> usize { @@ -117,7 +122,10 @@ fn cpu_model_name() -> String { if let Ok(content) = std::fs::read_to_string("/proc/cpuinfo") { for line in content.lines() { let lower = line.to_lowercase(); - if lower.starts_with("model name") || lower.starts_with("cpu model") || lower.starts_with("hardware") { + if lower.starts_with("model name") + || lower.starts_with("cpu model") + || lower.starts_with("hardware") + { if let Some(val) = line.splitn(2, ':').nth(1) { let trimmed = val.trim().to_string(); if !trimmed.is_empty() { @@ -181,17 +189,29 @@ fn detect_simd_features() -> Vec { let mut features = Vec::new(); #[cfg(target_arch = "x86_64")] { - if std::is_x86_feature_detected!("sse2") { features.push("sse2".to_string()); } - if std::is_x86_feature_detected!("sse4.2") { features.push("sse4.2".to_string()); } - if std::is_x86_feature_detected!("avx") { features.push("avx".to_string()); } - if std::is_x86_feature_detected!("avx2") { features.push("avx2".to_string()); } - if std::is_x86_feature_detected!("avx512f") { features.push("avx512f".to_string()); } + if std::is_x86_feature_detected!("sse2") { + features.push("sse2".to_string()); + } + if std::is_x86_feature_detected!("sse4.2") { + features.push("sse4.2".to_string()); + } + if std::is_x86_feature_detected!("avx") { + features.push("avx".to_string()); + } + if std::is_x86_feature_detected!("avx2") { + features.push("avx2".to_string()); + } + if std::is_x86_feature_detected!("avx512f") { + features.push("avx512f".to_string()); + } } #[cfg(target_arch = "aarch64")] { // NEON is mandatory on AArch64 features.push("neon".to_string()); - if std::arch::is_aarch64_feature_detected!("sve") { features.push("sve".to_string()); } + if std::arch::is_aarch64_feature_detected!("sve") { + features.push("sve".to_string()); + } } if features.is_empty() { features.push("none".to_string()); diff --git a/miners/rust/src/main.rs b/miners/rust/src/main.rs index 3babb7baf..cc9dfeada 100644 --- a/miners/rust/src/main.rs +++ b/miners/rust/src/main.rs @@ -10,11 +10,10 @@ /// rustchain-miner --node-url http://localhost:8333 \ /// --miner-id my-rig-01 \ /// --interval 60 - mod fingerprint; -use clap::Parser; use chrono::Utc; +use clap::Parser; use reqwest::Client; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -174,7 +173,11 @@ fn build_payload(miner_id: &str) -> AttestationPayload { let cache_timing = fingerprint::measure_cache_timing(); log_info(&format!( " cache_timing=[{}]", - cache_timing.iter().map(|v| format!("{:.1}ns", v)).collect::>().join(", ") + cache_timing + .iter() + .map(|v| format!("{:.1}ns", v)) + .collect::>() + .join(", ") )); let thermal_drift = estimate_thermal_drift(); @@ -216,7 +219,9 @@ async fn submit_attestation( let mut backoff = initial_backoff_ms; for attempt in 1..=max_retries { - log_info(&format!("Submitting attestation (attempt {attempt}/{max_retries}) → {endpoint}")); + log_info(&format!( + "Submitting attestation (attempt {attempt}/{max_retries}) → {endpoint}" + )); match client .post(&endpoint) @@ -258,7 +263,9 @@ async fn submit_attestation( } } - Err(format!("All {max_retries} attempts failed — skipping this cycle")) + Err(format!( + "All {max_retries} attempts failed — skipping this cycle" + )) } // --------------------------------------------------------------------------- diff --git a/rustchain-miner/src/arch_tests.rs b/rustchain-miner/src/arch_tests.rs index 8121c6725..4d086dc13 100644 --- a/rustchain-miner/src/arch_tests.rs +++ b/rustchain-miner/src/arch_tests.rs @@ -12,7 +12,7 @@ mod architecture_detection_tests { // Simulate SiFive U74 detection (HiFive Unmatched) let cpu = "SiFive U74-MC"; let machine = "riscv64"; - + // We can't directly call detect_cpu_family_arch as it's private, // but we can test the HardwareInfo generation let hw = HardwareInfo { @@ -28,7 +28,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert_eq!(hw.arch, "SiFive U74"); assert_eq!(hw.machine, "riscv64"); @@ -39,7 +39,7 @@ mod architecture_detection_tests { // Simulate StarFive JH7110 detection (VisionFive 2) let cpu = "StarFive JH7110"; let machine = "riscv64"; - + let hw = HardwareInfo { platform: "Linux".to_string(), machine: machine.to_string(), @@ -53,7 +53,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert_eq!(hw.arch, "StarFive JH7110"); } @@ -63,7 +63,7 @@ mod architecture_detection_tests { // Generic RISC-V 64-bit system let cpu = "Generic RISC-V CPU"; let machine = "riscv64"; - + let hw = HardwareInfo { platform: "Linux".to_string(), machine: machine.to_string(), @@ -77,7 +77,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert!(hw.arch.contains("64-bit")); } @@ -87,7 +87,7 @@ mod architecture_detection_tests { // Allwinner D1 (Nezha board) let cpu = "Allwinner D1"; let machine = "riscv64"; - + let hw = HardwareInfo { platform: "Linux".to_string(), machine: machine.to_string(), @@ -101,7 +101,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert_eq!(hw.arch, "Allwinner D1"); } @@ -111,7 +111,7 @@ mod architecture_detection_tests { // T-Head C910 (high-performance RISC-V) let cpu = "T-Head C910"; let machine = "riscv64"; - + let hw = HardwareInfo { platform: "Linux".to_string(), machine: machine.to_string(), @@ -125,7 +125,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert!(hw.arch.contains("T-Head")); } @@ -135,7 +135,7 @@ mod architecture_detection_tests { // Original VisionFive let cpu = "StarFive JH7100"; let machine = "riscv64"; - + let hw = HardwareInfo { platform: "Linux".to_string(), machine: machine.to_string(), @@ -149,7 +149,7 @@ mod architecture_detection_tests { macs: vec!["00:00:00:00:00:01".to_string()], mac: "00:00:00:00:00:01".to_string(), }; - + assert_eq!(hw.family, "RISC-V"); assert_eq!(hw.arch, "StarFive JH7100"); } @@ -170,9 +170,9 @@ mod architecture_detection_tests { macs: vec!["aa:bb:cc:dd:ee:ff".to_string()], mac: "aa:bb:cc:dd:ee:ff".to_string(), }; - + let miner_id = hw.generate_miner_id(); - + // Miner ID should contain architecture info assert!(miner_id.contains("risc-v") || miner_id.contains("sifive")); assert!(miner_id.contains("hifive-u")); @@ -194,10 +194,10 @@ mod architecture_detection_tests { macs: vec!["11:22:33:44:55:66".to_string()], mac: "11:22:33:44:55:66".to_string(), }; - + let miner_id = hw.generate_miner_id(); let wallet = hw.generate_wallet(&miner_id); - + // Wallet should be properly formatted assert!(wallet.contains("RTC")); assert!(wallet.len() > 20); @@ -219,7 +219,7 @@ mod architecture_detection_tests { macs: vec!["aa:bb:cc:dd:ee:ff".to_string()], mac: "aa:bb:cc:dd:ee:ff".to_string(), }; - + assert_eq!(hw.family, "Apple Silicon"); assert_eq!(hw.arch, "M1"); } @@ -240,7 +240,7 @@ mod architecture_detection_tests { macs: vec!["aa:bb:cc:dd:ee:ff".to_string()], mac: "aa:bb:cc:dd:ee:ff".to_string(), }; - + assert_eq!(hw.family, "x86_64"); } @@ -260,7 +260,7 @@ mod architecture_detection_tests { macs: vec!["aa:bb:cc:dd:ee:ff".to_string()], mac: "aa:bb:cc:dd:ee:ff".to_string(), }; - + assert_eq!(hw.family, "PowerPC"); assert_eq!(hw.arch, "G4"); } @@ -276,14 +276,16 @@ mod architecture_detection_tests { "Allwinner D1", "T-Head C910/C906", ]; - + for arch in riscv_archs { // All RISC-V architectures should be recognized - assert!(arch.contains("RISC-V") || - arch.contains("SiFive") || - arch.contains("StarFive") || - arch.contains("Allwinner") || - arch.contains("T-Head")); + assert!( + arch.contains("RISC-V") + || arch.contains("SiFive") + || arch.contains("StarFive") + || arch.contains("Allwinner") + || arch.contains("T-Head") + ); } } @@ -303,15 +305,15 @@ mod architecture_detection_tests { macs: vec!["aa:bb:cc:dd:ee:ff".to_string()], mac: "aa:bb:cc:dd:ee:ff".to_string(), }; - + // Serialize to JSON let json = serde_json::to_string(&hw).unwrap(); - + // Verify it contains expected fields assert!(json.contains("RISC-V")); assert!(json.contains("SiFive U74")); assert!(json.contains("riscv64")); - + // Deserialize back let hw2: HardwareInfo = serde_json::from_str(&json).unwrap(); assert_eq!(hw.family, hw2.family); diff --git a/rustchain-miner/src/attestation.rs b/rustchain-miner/src/attestation.rs index 4c04004b9..fa13e1ac2 100644 --- a/rustchain-miner/src/attestation.rs +++ b/rustchain-miner/src/attestation.rs @@ -210,14 +210,17 @@ pub async fn attest_with_key( tracing::info!("[ATTEST] Starting hardware attestation..."); // Step 1: Get challenge nonce from node - let response = transport.post_json("/attest/challenge", &serde_json::json!({})).await?; + let response = transport + .post_json("/attest/challenge", &serde_json::json!({})) + .await?; if !response.status().is_success() { let status = response.status(); let body = response.text().await.unwrap_or_default(); - return Err(crate::error::MinerError::Attestation( - format!("Challenge failed: HTTP {} - {}", status, body) - )); + return Err(crate::error::MinerError::Attestation(format!( + "Challenge failed: HTTP {} - {}", + status, body + ))); } let challenge: serde_json::Value = response.json().await?; @@ -229,11 +232,14 @@ pub async fn attest_with_key( if nonce.is_empty() { return Err(crate::error::MinerError::Attestation( - "No nonce in challenge response".to_string() + "No nonce in challenge response".to_string(), )); } - tracing::info!("[ATTEST] Got challenge nonce: {}...", &nonce[..nonce.len().min(16)]); + tracing::info!( + "[ATTEST] Got challenge nonce: {}...", + &nonce[..nonce.len().min(16)] + ); // Step 2: Collect entropy let entropy = collect_entropy(48, 25000); @@ -255,7 +261,7 @@ pub async fn attest_with_key( // Verify the provided public_key_hex matches the signing key if computed_pubkey_hex != public_key_hex { return Err(crate::error::MinerError::Attestation( - "Public key mismatch: provided key doesn't match signing key".to_string() + "Public key mismatch: provided key doesn't match signing key".to_string(), )); } @@ -289,9 +295,10 @@ pub async fn attest_with_key( if !response.status().is_success() { let status = response.status(); let body = response.text().await.unwrap_or_default(); - return Err(crate::error::MinerError::Attestation( - format!("Submit failed: HTTP {} - {}", status, body) - )); + return Err(crate::error::MinerError::Attestation(format!( + "Submit failed: HTTP {} - {}", + status, body + ))); } let result: serde_json::Value = response.json().await?; @@ -300,9 +307,10 @@ pub async fn attest_with_key( tracing::info!("[ATTEST] Attestation accepted!"); Ok(true) } else { - Err(crate::error::MinerError::Attestation( - format!("Attestation rejected: {:?}", result) - )) + Err(crate::error::MinerError::Attestation(format!( + "Attestation rejected: {:?}", + result + ))) } } @@ -318,14 +326,17 @@ pub async fn attest( tracing::info!("[ATTEST] Starting hardware attestation..."); // Step 1: Get challenge nonce from node - let response = transport.post_json("/attest/challenge", &serde_json::json!({})).await?; + let response = transport + .post_json("/attest/challenge", &serde_json::json!({})) + .await?; if !response.status().is_success() { let status = response.status(); let body = response.text().await.unwrap_or_default(); - return Err(crate::error::MinerError::Attestation( - format!("Challenge failed: HTTP {} - {}", status, body) - )); + return Err(crate::error::MinerError::Attestation(format!( + "Challenge failed: HTTP {} - {}", + status, body + ))); } let challenge: serde_json::Value = response.json().await?; @@ -337,11 +348,14 @@ pub async fn attest( if nonce.is_empty() { return Err(crate::error::MinerError::Attestation( - "No nonce in challenge response".to_string() + "No nonce in challenge response".to_string(), )); } - tracing::info!("[ATTEST] Got challenge nonce: {}...", &nonce[..nonce.len().min(16)]); + tracing::info!( + "[ATTEST] Got challenge nonce: {}...", + &nonce[..nonce.len().min(16)] + ); // Step 2: Collect entropy let entropy = collect_entropy(48, 25000); @@ -391,9 +405,10 @@ pub async fn attest( if !response.status().is_success() { let status = response.status(); let body = response.text().await.unwrap_or_default(); - return Err(crate::error::MinerError::Attestation( - format!("Submit failed: HTTP {} - {}", status, body) - )); + return Err(crate::error::MinerError::Attestation(format!( + "Submit failed: HTTP {} - {}", + status, body + ))); } let result: serde_json::Value = response.json().await?; @@ -402,9 +417,10 @@ pub async fn attest( tracing::info!("[ATTEST] Attestation accepted!"); Ok(true) } else { - Err(crate::error::MinerError::Attestation( - format!("Attestation rejected: {:?}", result) - )) + Err(crate::error::MinerError::Attestation(format!( + "Attestation rejected: {:?}", + result + ))) } } @@ -421,7 +437,12 @@ mod tests { } /// Helper: sign a message and return (signature_hex, public_key_hex) - fn sign_message(miner_id: &str, wallet: &str, nonce: &str, commitment: &str) -> (String, String) { + fn sign_message( + miner_id: &str, + wallet: &str, + nonce: &str, + commitment: &str, + ) -> (String, String) { let signing_key = ed25519_dalek::SigningKey::generate(&mut rand::rngs::OsRng); let verifying_key = signing_key.verifying_key(); let public_key_hex = hex::encode(verifying_key.as_bytes()); @@ -448,19 +469,20 @@ mod tests { return false; } - let verifying_key = match ed25519_dalek::VerifyingKey::from_bytes( - &public_key_bytes.try_into().unwrap() - ) { - Ok(k) => k, - Err(_) => return false, - }; + let verifying_key = + match ed25519_dalek::VerifyingKey::from_bytes(&public_key_bytes.try_into().unwrap()) { + Ok(k) => k, + Err(_) => return false, + }; let signature = match ed25519_dalek::Signature::from_slice(&signature_bytes) { Ok(s) => s, Err(_) => return false, }; - verifying_key.verify_strict(message.as_bytes(), &signature).is_ok() + verifying_key + .verify_strict(message.as_bytes(), &signature) + .is_ok() } #[test] diff --git a/rustchain-miner/src/hardware.rs b/rustchain-miner/src/hardware.rs index 33ba9b5a2..e55163b21 100644 --- a/rustchain-miner/src/hardware.rs +++ b/rustchain-miner/src/hardware.rs @@ -69,7 +69,10 @@ impl HardwareInfo { // Get MAC addresses let macs = get_mac_addresses(); - let mac = macs.first().cloned().unwrap_or_else(|| "00:00:00:00:00:00".to_string()); + let mac = macs + .first() + .cloned() + .unwrap_or_else(|| "00:00:00:00:00:00".to_string()); Ok(Self { platform, @@ -90,7 +93,11 @@ impl HardwareInfo { pub fn generate_miner_id(&self) -> String { use sha2::{Digest, Sha256}; - let hw_string = format!("{}-{}", self.hostname, self.serial.as_deref().unwrap_or("unknown")); + let hw_string = format!( + "{}-{}", + self.hostname, + self.serial.as_deref().unwrap_or("unknown") + ); let hash = Sha256::digest(hw_string.as_bytes()); let hw_hash = hex::encode(&hash[..4]); @@ -110,7 +117,11 @@ impl HardwareInfo { let hash = Sha256::digest(wallet_string.as_bytes()); let wallet_hash = hex::encode(&hash[..19]); - format!("{}_{}RTC", self.family.to_lowercase().replace(' ', "_"), wallet_hash) + format!( + "{}_{}RTC", + self.family.to_lowercase().replace(' ', "_"), + wallet_hash + ) } } @@ -184,9 +195,15 @@ fn detect_cpu_family_arch(cpu: &str, machine: &str) -> (String, String) { return ("x86_64".to_string(), "ivy_bridge".to_string()); } return ("x86_64".to_string(), "xeon".to_string()); - } else if cpu_lower.contains("i7-3") || cpu_lower.contains("i5-3") || cpu_lower.contains("i3-3") { + } else if cpu_lower.contains("i7-3") + || cpu_lower.contains("i5-3") + || cpu_lower.contains("i3-3") + { return ("x86_64".to_string(), "ivy_bridge".to_string()); - } else if cpu_lower.contains("i7-2") || cpu_lower.contains("i5-2") || cpu_lower.contains("i3-2") { + } else if cpu_lower.contains("i7-2") + || cpu_lower.contains("i5-2") + || cpu_lower.contains("i3-2") + { return ("x86_64".to_string(), "sandy_bridge".to_string()); } else if cpu_lower.contains("i7-9") && cpu_lower.contains("900") { return ("x86_64".to_string(), "nehalem".to_string()); diff --git a/rustchain-miner/src/lib.rs b/rustchain-miner/src/lib.rs index fbc7488db..357780ce7 100644 --- a/rustchain-miner/src/lib.rs +++ b/rustchain-miner/src/lib.rs @@ -20,19 +20,19 @@ //! } //! ``` +pub mod attestation; pub mod config; pub mod error; pub mod hardware; -pub mod transport; -pub mod attestation; pub mod miner; +pub mod transport; #[cfg(test)] mod arch_tests; +pub use attestation::AttestationReport; pub use config::Config; -pub use error::{Result, MinerError}; +pub use error::{MinerError, Result}; pub use hardware::HardwareInfo; -pub use transport::NodeTransport; -pub use attestation::AttestationReport; pub use miner::Miner; +pub use transport::NodeTransport; diff --git a/rustchain-miner/src/main.rs b/rustchain-miner/src/main.rs index 5feee9778..b1a576f5c 100644 --- a/rustchain-miner/src/main.rs +++ b/rustchain-miner/src/main.rs @@ -25,7 +25,12 @@ struct Args { miner_id: Option, /// Node URL - #[arg(short = 'n', long = "node", env = "RUSTCHAIN_NODE_URL", default_value = "https://50.28.86.131")] + #[arg( + short = 'n', + long = "node", + env = "RUSTCHAIN_NODE_URL", + default_value = "https://50.28.86.131" + )] node: String, /// HTTP proxy URL for legacy systems @@ -41,11 +46,19 @@ struct Args { verbose: bool, /// Block time in seconds - #[arg(long = "block-time", env = "RUSTCHAIN_BLOCK_TIME", default_value = "600")] + #[arg( + long = "block-time", + env = "RUSTCHAIN_BLOCK_TIME", + default_value = "600" + )] block_time: u64, /// Attestation TTL in seconds - #[arg(long = "attestation-ttl", env = "RUSTCHAIN_ATTESTATION_TTL", default_value = "580")] + #[arg( + long = "attestation-ttl", + env = "RUSTCHAIN_ATTESTATION_TTL", + default_value = "580" + )] attestation_ttl: u64, } diff --git a/rustchain-miner/src/miner.rs b/rustchain-miner/src/miner.rs index 8d62b2ddc..423579cda 100644 --- a/rustchain-miner/src/miner.rs +++ b/rustchain-miner/src/miner.rs @@ -1,9 +1,9 @@ //! Main miner implementation with enrollment and mining loop +use ed25519_dalek::Signer; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; -use ed25519_dalek::Signer; use tokio::time::sleep; use crate::attestation::{attest_with_key, FingerprintData}; @@ -111,10 +111,16 @@ impl Miner { let hw_info = HardwareInfo::collect()?; // Generate or use provided miner_id - let miner_id = config.miner_id.clone().unwrap_or_else(|| hw_info.generate_miner_id()); + let miner_id = config + .miner_id + .clone() + .unwrap_or_else(|| hw_info.generate_miner_id()); // Generate or use provided wallet - let wallet = config.wallet.clone().unwrap_or_else(|| hw_info.generate_wallet(&miner_id)); + let wallet = config + .wallet + .clone() + .unwrap_or_else(|| hw_info.generate_wallet(&miner_id)); // Generate Ed25519 signing keypair (reused for attestation + enrollment) let signing_key = ed25519_dalek::SigningKey::generate(&mut rand::rngs::OsRng); @@ -169,7 +175,10 @@ impl Miner { /// Print miner banner pub fn print_banner(&self) { println!("{}", "=".repeat(70)); - println!("RustChain Miner v{} - RIP-PoA Hardware Attestation", env!("CARGO_PKG_VERSION")); + println!( + "RustChain Miner v{} - RIP-PoA Hardware Attestation", + env!("CARGO_PKG_VERSION") + ); println!("{}", "=".repeat(70)); println!("Miner ID: {}", self.miner_id); println!("Wallet: {}", self.wallet); @@ -177,9 +186,19 @@ impl Miner { if let Some(proxy) = &self.config.proxy_url { println!("Proxy: {}", proxy); } - println!("Transport: {}", if self.transport.using_proxy() { "HTTP Proxy" } else { "Direct HTTPS" }); + println!( + "Transport: {}", + if self.transport.using_proxy() { + "HTTP Proxy" + } else { + "Direct HTTPS" + } + ); println!("{}", "-".repeat(70)); - println!("Platform: {} / {}", self.hw_info.platform, self.hw_info.machine); + println!( + "Platform: {} / {}", + self.hw_info.platform, self.hw_info.machine + ); println!("CPU: {}", self.hw_info.cpu); println!("Cores: {}", self.hw_info.cores); println!("Memory: {} GB", self.hw_info.memory_gb); @@ -204,7 +223,11 @@ impl Miner { println!("[DRY-RUN] MAC count: {}", self.hw_info.macs.len()); println!( "[DRY-RUN] Serial present: {}", - if self.hw_info.serial.is_some() { "yes" } else { "no" } + if self.hw_info.serial.is_some() { + "yes" + } else { + "no" + } ); // Health probe @@ -253,7 +276,8 @@ impl Miner { .unwrap() .as_secs() + self.config.attestation_ttl_secs; - self.attestation_valid_until.store(valid_until, Ordering::Relaxed); + self.attestation_valid_until + .store(valid_until, Ordering::Relaxed); Ok(()) } Err(e) => Err(e), @@ -275,7 +299,10 @@ impl Miner { let epoch_response = self.transport.get("/epoch").await?; let epoch_state: serde_json::Value = epoch_response.json().await?; - let epoch = epoch_state.get("epoch").and_then(|e| e.as_u64()).unwrap_or(0); + let epoch = epoch_state + .get("epoch") + .and_then(|e| e.as_u64()) + .unwrap_or(0); // Sign enrollment request using the SAME Ed25519 keypair from attestation. // The signature binds (miner_pubkey|miner_id|epoch) to prove the enrollment @@ -322,13 +349,19 @@ impl Miner { Ok(true) } else { self.stats.record_enrollment_failed(); - Err(MinerError::Enrollment(format!("Enrollment rejected: {:?}", result))) + Err(MinerError::Enrollment(format!( + "Enrollment rejected: {:?}", + result + ))) } } /// Check balance pub async fn check_balance(&self) -> Result { - let response = self.transport.get(&format!("/balance/{}", self.wallet)).await?; + let response = self + .transport + .get(&format!("/balance/{}", self.wallet)) + .await?; if !response.status().is_success() { return Ok(0.0); @@ -376,7 +409,11 @@ impl Miner { cycle += 1; println!("\n{}", "=".repeat(70)); - println!("Cycle #{} - {}", cycle, chrono::Local::now().format("%Y-%m-%d %H:%M:%S")); + println!( + "Cycle #{} - {}", + cycle, + chrono::Local::now().format("%Y-%m-%d %H:%M:%S") + ); println!("{}", "=".repeat(70)); // Ensure attestation is valid @@ -393,7 +430,10 @@ impl Miner { // Enroll in epoch match self.enroll().await { Ok(_) => { - println!("⏳ Mining for {} minutes...", self.config.block_time_secs / 60); + println!( + "⏳ Mining for {} minutes...", + self.config.block_time_secs / 60 + ); // Mining wait loop let block_duration = Duration::from_secs(self.config.block_time_secs); diff --git a/rustchain-miner/src/transport.rs b/rustchain-miner/src/transport.rs index 95252bf71..07c4f5cf9 100644 --- a/rustchain-miner/src/transport.rs +++ b/rustchain-miner/src/transport.rs @@ -21,7 +21,11 @@ impl NodeTransport { /// with self-signed certificates), set the environment variable /// `RUSTCHAIN_DEV_INSECURE_TLS=1`. This is **strongly discouraged** in /// production — it exposes the miner to man-in-the-middle attacks. - pub fn new(node_url: String, proxy_url: Option, timeout: Duration) -> crate::Result { + pub fn new( + node_url: String, + proxy_url: Option, + timeout: Duration, + ) -> crate::Result { let insecure = std::env::var("RUSTCHAIN_DEV_INSECURE_TLS") .map(|v| v == "1" || v.eq_ignore_ascii_case("true")) .unwrap_or(false); @@ -65,14 +69,22 @@ impl NodeTransport { } /// GET request with query parameters - pub async fn get_with_params(&self, path: &str, params: &T) -> crate::Result { + pub async fn get_with_params( + &self, + path: &str, + params: &T, + ) -> crate::Result { let url = format!("{}{}", self.base_url(), path); let response = self.client.get(&url).query(params).send().await?; Ok(response) } /// POST request with JSON body - pub async fn post_json(&self, path: &str, body: &T) -> crate::Result { + pub async fn post_json( + &self, + path: &str, + body: &T, + ) -> crate::Result { let url = format!("{}{}", self.base_url(), path); let response = self.client.post(&url).json(body).send().await?; Ok(response) @@ -97,7 +109,7 @@ impl NodeTransport { pub async fn probe_transport(&mut self) { // Try direct HTTPS first let health_url = format!("{}/health", self.node_url); - + if let Ok(response) = self.client.get(&health_url).send().await { if response.status().is_success() { tracing::info!("[TRANSPORT] Direct HTTPS to node: OK"); diff --git a/rustchain-wallet/src/bin/rtc_wallet.rs b/rustchain-wallet/src/bin/rtc_wallet.rs index e7110c27d..cb8c25042 100644 --- a/rustchain-wallet/src/bin/rtc_wallet.rs +++ b/rustchain-wallet/src/bin/rtc_wallet.rs @@ -240,7 +240,12 @@ async fn main() -> anyhow::Result<()> { cmd_receive(&storage, &name)?; } Commands::Balance { wallet, rpc } => { - cmd_balance(&storage, &wallet, rpc.as_deref().unwrap_or(network.api_url())).await?; + cmd_balance( + &storage, + &wallet, + rpc.as_deref().unwrap_or(network.api_url()), + ) + .await?; } Commands::List => { cmd_list(&storage)?; @@ -466,15 +471,19 @@ fn cmd_receive(storage: &WalletStorage, name: &str) -> Result<()> { Ok(()) } -async fn cmd_balance(storage: &WalletStorage, wallet_or_address: &str, api_url: &str) -> Result<()> { +async fn cmd_balance( + storage: &WalletStorage, + wallet_or_address: &str, + api_url: &str, +) -> Result<()> { let client = RustChainClient::new(api_url.to_string()); // If it starts with RTC, treat as address; otherwise look up wallet name let address = if wallet_or_address.starts_with("RTC") { wallet_or_address.to_string() } else if storage.exists(wallet_or_address) { - let password = rpassword::prompt_password("Enter wallet password: ") - .unwrap_or_else(|_| String::new()); + let password = + rpassword::prompt_password("Enter wallet password: ").unwrap_or_else(|_| String::new()); let keypair = storage.load(wallet_or_address, &password)?; keypair.rtc_address() } else { diff --git a/rustchain-wallet/src/client.rs b/rustchain-wallet/src/client.rs index 6cfbe4cfb..c2f21551f 100644 --- a/rustchain-wallet/src/client.rs +++ b/rustchain-wallet/src/client.rs @@ -246,12 +246,7 @@ impl RustChainClient { /// Check if the API endpoint is reachable pub async fn health_check(&self) -> Result { - match self - .http_client - .get(&self.api_url) - .send() - .await - { + match self.http_client.get(&self.api_url).send().await { Ok(resp) => Ok(resp.status().is_success()), Err(_) => Ok(false), } diff --git a/rustchain-wallet/src/keys.rs b/rustchain-wallet/src/keys.rs index b65130570..d1128c44f 100644 --- a/rustchain-wallet/src/keys.rs +++ b/rustchain-wallet/src/keys.rs @@ -207,7 +207,7 @@ mod tests { let addr = keypair.rtc_address(); assert!(addr.starts_with("RTC")); assert_eq!(addr.len(), 43); // "RTC" + 40 hex chars - // Verify the hex portion is valid + // Verify the hex portion is valid assert!(addr[3..].chars().all(|c| c.is_ascii_hexdigit())); } diff --git a/rustchain-wallet/src/transaction.rs b/rustchain-wallet/src/transaction.rs index 9135167ba..87901e6ec 100644 --- a/rustchain-wallet/src/transaction.rs +++ b/rustchain-wallet/src/transaction.rs @@ -116,7 +116,9 @@ impl Transaction { let amount_rtc = self.amount as f64 / AMOUNT_UNIT as f64; let nonce_str = self.nonce.to_string(); let memo = self.memo.as_deref().unwrap_or(""); - Ok(canonical_message(&self.from, &self.to, amount_rtc, memo, &nonce_str, None)) + Ok(canonical_message( + &self.from, &self.to, amount_rtc, memo, &nonce_str, None, + )) } /// Serialize the transaction for signing with an optional chain_id. @@ -125,7 +127,14 @@ impl Transaction { let amount_rtc = self.amount as f64 / AMOUNT_UNIT as f64; let nonce_str = self.nonce.to_string(); let memo = self.memo.as_deref().unwrap_or(""); - Ok(canonical_message(&self.from, &self.to, amount_rtc, memo, &nonce_str, Some(chain_id))) + Ok(canonical_message( + &self.from, + &self.to, + amount_rtc, + memo, + &nonce_str, + Some(chain_id), + )) } /// Sign the transaction with a keypair @@ -547,14 +556,7 @@ mod tests { // sort_keys=True, separators=(",",":")) // = {"amount":1.0,"from":"RTCabc...","memo":"","nonce":"1733420000000","to":"RTCdef..."} - let msg = canonical_message( - "RTCabc123", - "RTCdef456", - 1.0, - "", - "1733420000000", - None, - ); + let msg = canonical_message("RTCabc123", "RTCdef456", 1.0, "", "1733420000000", None); let json_str = String::from_utf8(msg).unwrap(); assert_eq!( json_str, @@ -564,14 +566,7 @@ mod tests { #[test] fn test_canonical_message_with_memo() { - let msg = canonical_message( - "RTCabc", - "RTCdef", - 0.5, - "hello world", - "42", - None, - ); + let msg = canonical_message("RTCabc", "RTCdef", 0.5, "hello world", "42", None); let json_str = String::from_utf8(msg).unwrap(); assert_eq!( json_str, From 49ce1e3ec327d8b74f6f385f0f4e5a4c40febd91 Mon Sep 17 00:00:00 2001 From: BossChaos Date: Sat, 9 May 2026 00:40:15 +0800 Subject: [PATCH 2/2] fix: replace CORS wildcard with specific origin - Replace Access-Control-Allow-Origin: * with https://rustchain.io - Affects 6 files across RPC, beacon, explorer, and integration servers - Prevents unauthorized cross-origin access to sensitive endpoints Security: CVE-2026-CORS-001 --- explorer/explorer_server.py | 4 ++-- fossils/fossil_record_export.py | 2 +- integrations/epoch-viz/server.py | 4 ++-- node/beacon_api.py | 4 ++-- rips/rustchain-core/api/rpc.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/explorer/explorer_server.py b/explorer/explorer_server.py index 16f3f8ce9..f3bcf2a52 100644 --- a/explorer/explorer_server.py +++ b/explorer/explorer_server.py @@ -101,7 +101,7 @@ def send_json(self, data, status=200, headers=None): """Send JSON response""" self.send_response(status) self.send_header('Content-Type', 'application/json') - self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Origin', 'https://rustchain.io') self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS') self.send_header('Access-Control-Allow-Headers', 'Content-Type') if headers: @@ -122,7 +122,7 @@ def send_error_json(self, status, message): def do_OPTIONS(self): """Handle CORS preflight""" self.send_response(200) - self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Origin', 'https://rustchain.io') self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS') self.send_header('Access-Control-Allow-Headers', 'Content-Type') self.send_header('Access-Control-Max-Age', '86400') diff --git a/fossils/fossil_record_export.py b/fossils/fossil_record_export.py index 32da666b2..7a2e787e6 100644 --- a/fossils/fossil_record_export.py +++ b/fossils/fossil_record_export.py @@ -343,7 +343,7 @@ def send_json_response(self, data): self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', len(response)) - self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Origin', 'https://rustchain.io') self.end_headers() self.wfile.write(response) diff --git a/integrations/epoch-viz/server.py b/integrations/epoch-viz/server.py index 212cbfbb9..fdec31acd 100644 --- a/integrations/epoch-viz/server.py +++ b/integrations/epoch-viz/server.py @@ -40,7 +40,7 @@ def proxy_request(self, path): self.send_response(200) self.send_header('Content-Type', 'application/json') - self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Origin', 'https://rustchain.io') self.end_headers() self.wfile.write(data) except urllib.error.URLError as e: @@ -51,7 +51,7 @@ def proxy_request(self, path): def end_headers(self): # Add CORS headers to all responses - self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Origin', 'https://rustchain.io') super().end_headers() if __name__ == '__main__': diff --git a/node/beacon_api.py b/node/beacon_api.py index 3389f99c5..f17473121 100644 --- a/node/beacon_api.py +++ b/node/beacon_api.py @@ -212,7 +212,7 @@ def beacon_join(): """ if request.method == 'OPTIONS': resp = jsonify({'ok': True}) - resp.headers['Access-Control-Allow-Origin'] = '*' + resp.headers['Access-Control-Allow-Origin'] = 'https://rustchain.io' resp.headers['Access-Control-Allow-Headers'] = 'Content-Type' resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS' return resp @@ -331,7 +331,7 @@ def beacon_atlas(): """ if request.method == 'OPTIONS': resp = jsonify({'ok': True}) - resp.headers['Access-Control-Allow-Origin'] = '*' + resp.headers['Access-Control-Allow-Origin'] = 'https://rustchain.io' resp.headers['Access-Control-Allow-Headers'] = 'Content-Type' resp.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS' return resp diff --git a/rips/rustchain-core/api/rpc.py b/rips/rustchain-core/api/rpc.py index 08b7c8563..161b67aef 100644 --- a/rips/rustchain-core/api/rpc.py +++ b/rips/rustchain-core/api/rpc.py @@ -334,7 +334,7 @@ def _send_response(self, response: ApiResponse): """Send HTTP response""" self.send_response(200 if response.success else 400) self.send_header("Content-Type", "application/json") - self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Origin", "https://rustchain.io") self.end_headers() self.wfile.write(response.to_json().encode())