From f671de37460851e95c0bc92c5cda2c3a4a5ca04f Mon Sep 17 00:00:00 2001 From: Revertron Date: Sat, 10 Apr 2021 20:02:51 +0200 Subject: [PATCH] Added some checks for "Yggdrasil only" zones. --- src/blockchain/chain.rs | 20 ++++++++++++++++++-- src/blockchain/hash_utils.rs | 7 ++++++- src/blockchain/transaction.rs | 10 ++++++++++ src/commons/mod.rs | 19 +++++++++++++++++++ src/web_ui.rs | 16 +++++++++++++++- 5 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/blockchain/chain.rs b/src/blockchain/chain.rs index b2ec367..6b1b3d0 100644 --- a/src/blockchain/chain.rs +++ b/src/blockchain/chain.rs @@ -8,7 +8,7 @@ use chrono::Utc; use log::{debug, error, info, trace, warn}; use sqlite::{Connection, State, Statement}; -use crate::{Block, Bytes, Keystore, Transaction, check_domain, get_domain_zone}; +use crate::{Block, Bytes, Keystore, Transaction, check_domain, get_domain_zone, is_yggdrasil_record}; use crate::commons::constants::*; use crate::blockchain::types::{BlockQuality, MineResult, Options}; use crate::blockchain::types::BlockQuality::*; @@ -558,7 +558,7 @@ impl Chain { } if let Some(transaction) = &block.transaction { // TODO check for zone transaction - if !self.is_id_available(&transaction.identity, &block.pub_key, false) { + if !self.is_id_available(&transaction.identity, &block.pub_key, false) || !self.is_id_available(&transaction.identity, &block.pub_key, true) { warn!("Block {:?} is trying to spoof an identity!", &block); return Bad; } @@ -569,6 +569,22 @@ impl Chain { return Bad; } } + // Check if yggdrasil only quality of zone is not violated + if let Some(block_data) = transaction.get_domain_data() { + let zones = self.get_zones(); + for z in &zones { + if z.name == block_data.zone { + if z.yggdrasil { + for record in &block_data.records { + if !is_yggdrasil_record(record) { + warn!("Someone mined domain with clearnet records for Yggdrasil only zone!"); + return Bad; + } + } + } + } + } + } } match &self.last_block { None => { diff --git a/src/blockchain/hash_utils.rs b/src/blockchain/hash_utils.rs index 9070e2a..220536a 100644 --- a/src/blockchain/hash_utils.rs +++ b/src/blockchain/hash_utils.rs @@ -58,7 +58,8 @@ pub fn same_hash(left: &[u8], right: &[u8]) -> bool { result } -/// Returns hash difficulty +/// Returns hash difficulty (sum of zeroes from start and end) +#[inline] pub fn hash_difficulty(hash: &[u8]) -> u32 { let bytes: [u8; 8] = hash[..8].try_into().unwrap(); let int_start = u64::from_be_bytes(bytes); @@ -67,12 +68,16 @@ pub fn hash_difficulty(hash: &[u8]) -> u32 { int_start.leading_zeros() + int_end.trailing_zeros() } +/// Returns hash difficulty for keys (only from the start) +#[inline] pub fn hash_difficulty_key(hash: &[u8]) -> u32 { let bytes: [u8; 8] = hash[..8].try_into().unwrap(); let int = u64::from_be_bytes(bytes); int.leading_zeros() } +/// Hashes data by Sha256 algorithm +#[inline] pub fn hash_sha256(data: &[u8]) -> Vec { let mut digest = Sha256::default(); digest.update(data.as_ref()); diff --git a/src/blockchain/transaction.rs b/src/blockchain/transaction.rs index b024185..8cd99a4 100644 --- a/src/blockchain/transaction.rs +++ b/src/blockchain/transaction.rs @@ -53,6 +53,16 @@ impl Transaction { let confirmation = hash_identity(&domain, Some(&self.pub_key)); self.identity.eq(&hash) && self.confirmation.eq(&confirmation) } + + /// Returns [DomainData] from this transaction if it has it + pub fn get_domain_data(&self) -> Option { + if self.class == "domain" { + if let Ok(data) = serde_json::from_str::(&self.data) { + return Some(data) + } + } + None + } } impl fmt::Debug for Transaction { diff --git a/src/commons/mod.rs b/src/commons/mod.rs index 7e0851c..9d8c0ea 100644 --- a/src/commons/mod.rs +++ b/src/commons/mod.rs @@ -7,6 +7,7 @@ use std::net::IpAddr; #[cfg(not(target_os = "macos"))] use thread_priority::*; +use crate::dns::protocol::DnsRecord; /// Convert bytes array to HEX format pub fn to_hex(buf: &[u8]) -> String { @@ -94,6 +95,24 @@ pub fn is_yggdrasil(addr: &IpAddr) -> bool { false } +/// Checks if this record has IP from Yggdrasil network +/// https://yggdrasil-network.github.io +pub fn is_yggdrasil_record(record: &DnsRecord) -> bool { + match record { + DnsRecord::UNKNOWN { .. } => {} + DnsRecord::A { .. } => { return false } + DnsRecord::NS { .. } => {} + DnsRecord::CNAME { .. } => {} + DnsRecord::SOA { .. } => {} + DnsRecord::MX { .. } => {} + DnsRecord::TXT { .. } => {} + DnsRecord::AAAA { addr, .. } => { return is_yggdrasil(&IpAddr::from(*addr))} + DnsRecord::SRV { .. } => {} + DnsRecord::OPT { .. } => {} + } + true +} + #[cfg(target_os = "windows")] #[allow(unused_variables)] pub fn setup_miner_thread(cpu: u32) { diff --git a/src/web_ui.rs b/src/web_ui.rs index eefe85b..b3d93bc 100644 --- a/src/web_ui.rs +++ b/src/web_ui.rs @@ -14,7 +14,7 @@ use log::{debug, error, info, LevelFilter, trace, warn}; use serde::Deserialize; use web_view::Content; -use alfis::{Block, Bytes, Context, get_domain_zone, Keystore, Transaction, ZONE_MIN_DIFFICULTY}; +use alfis::{Block, Bytes, Context, get_domain_zone, Keystore, Transaction, ZONE_MIN_DIFFICULTY, is_yggdrasil_record}; use alfis::{check_domain, keys}; use alfis::blockchain::transaction::{DomainData, ZoneData}; use alfis::blockchain::types::MineResult; @@ -336,6 +336,20 @@ fn action_create_domain(context: Arc>, miner: Arc>, return; } }; + // Check if yggdrasil only quality of zone is not violated + let zones = context.chain.get_zones(); + for z in &zones { + if z.name == data.zone { + if z.yggdrasil { + for record in &data.records { + if !is_yggdrasil_record(record) { + show_warning(web_view, &format!("Zone {} is Yggdrasil only, you cannot use IPs from clearnet!", &data.zone)); + return; + } + } + } + } + } match context.chain.can_mine_domain(&name, &pub_key) { MineResult::Fine => { let zone = get_domain_zone(&name);