From 1d9833db0f194f89ec7f7f4239499e34039c0c62 Mon Sep 17 00:00:00 2001 From: Revertron Date: Wed, 17 Mar 2021 14:55:05 +0100 Subject: [PATCH] Implemented right way to constrain zone difficulty. --- alfis.toml | 2 +- src/blockchain/block.rs | 4 +-- src/blockchain/chain.rs | 22 ++++++++++++++ src/blockchain/constants.rs | 1 + src/blockchain/filter.rs | 9 +++--- src/blockchain/transaction.rs | 19 ++++++++++++ src/main.rs | 3 +- src/miner.rs | 6 ++-- src/utils.rs | 9 ++++++ src/web_ui.rs | 56 ++++++++++++++++++++--------------- 10 files changed, 95 insertions(+), 36 deletions(-) diff --git a/alfis.toml b/alfis.toml index 3af0af2..e188bec 100644 --- a/alfis.toml +++ b/alfis.toml @@ -1,5 +1,5 @@ # Settings -origin = "" +origin = "00000087A1BA6F94781C77BBDA96CC548E1E7F502DB3EA3F103ACD9301813B43" key_file = "default.key" listen = "[::]:4244" public = false diff --git a/src/blockchain/block.rs b/src/blockchain/block.rs index bf32ab9..7e629c2 100644 --- a/src/blockchain/block.rs +++ b/src/blockchain/block.rs @@ -29,12 +29,12 @@ pub struct Block { } impl Block { - pub fn new(transaction: Option, pub_key: Bytes, prev_block_hash: Bytes) -> Self { + pub fn new(transaction: Option, pub_key: Bytes, prev_block_hash: Bytes, difficulty: u32) -> Self { Block { index: 0, timestamp: 0, version: 0, - difficulty: 0, + difficulty, random: 0, nonce: 0, transaction, diff --git a/src/blockchain/chain.rs b/src/blockchain/chain.rs index ec8d919..5a57fab 100644 --- a/src/blockchain/chain.rs +++ b/src/blockchain/chain.rs @@ -14,6 +14,7 @@ use crate::blockchain::hash_utils::*; use crate::settings::Settings; use crate::keys::check_public_key_strength; use std::cmp::{min, max}; +use crate::blockchain::transaction::{ZoneData, DomainData}; const DB_NAME: &str = "blockchain.db"; const SQL_CREATE_TABLES: &str = "CREATE TABLE blocks ( @@ -309,6 +310,21 @@ impl Chain { } } + pub fn get_zone_difficulty(&self, zone: &str) -> u32 { + match self.get_domain_transaction(zone) { + None => { u32::max_value() } + Some(transaction) => { + match serde_json::from_str::(&transaction.data) { + Ok(data) => { data.difficulty } + Err(_) => { + warn!("Wrong data for zone {}!", zone); + u32::max_value() + } + } + } + } + } + pub fn last_block(&self) -> Option { self.last_block.clone() } @@ -395,6 +411,12 @@ impl Chain { return Bad; } } + if let Ok(data) = serde_json::from_str::(&transaction.data) { + if self.get_zone_difficulty(&data.zone) > block.difficulty { + warn!("Block {:?} is mined with too low difficulty!", &block); + return Bad; + } + } } match &self.last_block { None => { diff --git a/src/blockchain/constants.rs b/src/blockchain/constants.rs index e77a104..57ca10e 100644 --- a/src/blockchain/constants.rs +++ b/src/blockchain/constants.rs @@ -1,5 +1,6 @@ pub const CHAIN_VERSION: u32 = 1; +pub const ZONE_DIFFICULTY: u32 = 28; pub const BLOCK_DIFFICULTY: u32 = 24; pub const LOCKER_DIFFICULTY: u32 = 18; pub const KEYSTORE_DIFFICULTY: usize = 25; diff --git a/src/blockchain/filter.rs b/src/blockchain/filter.rs index b8ea362..1b02663 100644 --- a/src/blockchain/filter.rs +++ b/src/blockchain/filter.rs @@ -4,6 +4,7 @@ use crate::dns::filter::DnsFilter; use crate::dns::protocol::{DnsPacket, QueryType, DnsRecord, DnsQuestion, ResultCode}; #[allow(unused_imports)] use log::{trace, debug, info, warn, error}; +use crate::blockchain::transaction::DomainData; pub struct BlockchainFilter { context: Arc> @@ -48,12 +49,12 @@ impl DnsFilter for BlockchainFilter { } Some(data) => { info!("Found data for domain {}", &search); - let mut records: Vec = match serde_json::from_str(&data) { + let mut data: DomainData = match serde_json::from_str(&data) { Err(_) => { return None; } - Ok(records) => { records } + Ok(data) => { data } }; let mut answers: Vec = Vec::new(); - for mut record in records.iter_mut() { + for mut record in data.records.iter_mut() { if record.get_querytype() == qtype { match &mut record { DnsRecord::A { domain, .. } @@ -98,7 +99,7 @@ impl DnsFilter for BlockchainFilter { } if answers.is_empty() { // If there are no records found we search for *.domain.ltd record - for mut record in records { + for mut record in data.records { if record.get_querytype() == qtype { match record.get_domain() { None => {} diff --git a/src/blockchain/transaction.rs b/src/blockchain/transaction.rs index b01ddf4..1e4c8e7 100644 --- a/src/blockchain/transaction.rs +++ b/src/blockchain/transaction.rs @@ -5,6 +5,7 @@ use serde::ser::SerializeStruct; use crate::blockchain::hash_utils::*; use crate::bytes::Bytes; +use crate::dns::protocol::DnsRecord; extern crate serde; extern crate serde_json; @@ -75,4 +76,22 @@ impl Serialize for Transaction { structure.serialize_field("pub_key", &self.pub_key)?; structure.end() } +} + +#[derive(Clone, Serialize, Deserialize, PartialEq)] +pub struct DomainData { + pub zone: String, + pub records: Vec +} + +impl DomainData { + pub fn new(zone: String, records: Vec) -> Self { + Self { zone, records } + } +} + +#[derive(Clone, Serialize, Deserialize, PartialEq)] +pub struct ZoneData { + pub name: String, + pub difficulty: u32 } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 20a3348..050ec43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ use simple_logger::SimpleLogger; use winapi::um::wincon::{ATTACH_PARENT_PROCESS, AttachConsole, FreeConsole}; use alfis::{Block, Bytes, Chain, Miner, Context, Network, Settings, dns_utils, Keystore}; +use alfis::blockchain::BLOCK_DIFFICULTY; mod web_ui; @@ -126,7 +127,7 @@ fn create_genesis_if_needed(context: &Arc>, miner: &Arc { if !mining.load(Ordering::SeqCst) { - let mut block = Block::new(None, Bytes::default(), hash); + let mut block = Block::new(None, Bytes::default(), hash, LOCKER_DIFFICULTY); block.index = index; blocks.lock().unwrap().push(block); cond_var.notify_all(); @@ -109,7 +109,6 @@ impl Miner { // If this block needs to be a locker if block.index > 0 && !block.prev_block_hash.is_empty() { info!("Mining locker block"); - block.difficulty = LOCKER_DIFFICULTY; block.pub_key = context.lock().unwrap().keystore.get_public(); if !check_public_key_strength(&block.pub_key, KEYSTORE_DIFFICULTY) { warn!("Can not mine block with weak public key!"); @@ -131,7 +130,6 @@ impl Miner { } } } else { - block.difficulty = BLOCK_DIFFICULTY; block.index = context.lock().unwrap().chain.height() + 1; block.prev_block_hash = match context.lock().unwrap().chain.last_block() { None => { Bytes::default() } diff --git a/src/utils.rs b/src/utils.rs index 0c8dc01..3b14c13 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -64,6 +64,15 @@ pub fn check_domain(name: &str, allow_dots: bool) -> bool { true } +pub fn get_domain_zone(domain: &str) -> String { + let parts: Vec<&str> = domain.rsplitn(2, ".").collect(); + if !parts.is_empty() { + parts[0].to_owned() + } else { + String::new() + } +} + fn split_n(s: &str, n: usize) -> Vec<&str> { (0..=(s.len() - n + 1) / 2) .map(|i| &s[2 * i..2 * i + n]) diff --git a/src/web_ui.rs b/src/web_ui.rs index d5a05fd..33d4a66 100644 --- a/src/web_ui.rs +++ b/src/web_ui.rs @@ -12,13 +12,14 @@ use web_view::Content; use log::{debug, error, info, LevelFilter, trace, warn}; use serde::Deserialize; -use alfis::{Block, Bytes, Context, Keystore, Transaction}; +use alfis::{Block, Bytes, Context, Keystore, Transaction, get_domain_zone}; use alfis::miner::Miner; use alfis::{keys, check_domain}; use alfis::event::Event; use alfis::dns::protocol::DnsRecord; -use alfis::blockchain::ZONE_MAX_LENGTH; +use alfis::blockchain::{ZONE_MAX_LENGTH, ZONE_DIFFICULTY}; use Cmd::*; +use alfis::blockchain::transaction::DomainData; pub fn run_interface(context: Arc>, miner: Arc>) { let file_content = include_str!("webview/index.html"); @@ -158,27 +159,34 @@ pub fn run_interface(context: Arc>, miner: Arc>) { if !check_domain(&name, true) { return Ok(()); } - if serde_json::from_str::>(&records).is_ok() { - let (keystore, transaction) = { - let context = context.lock().unwrap(); - (context.get_keystore(), context.chain.get_domain_transaction(&name)) - }; - match transaction { - None => { - create_domain(context.clone(), miner.clone(), &name, &records, &keystore); - } - Some(transaction) => { - if transaction.pub_key == keystore.get_public() { - create_domain(context.clone(), miner.clone(), &name, &records, &keystore); - } else { - warn!("Tried to mine not owned domain!"); - let _ = web_view.eval(&format!("showWarning('{}');", "You cannot change domain that you don't own!")); + let rec_vec = serde_json::from_str::>(&records); + match rec_vec { + Ok(records) => { + let zone = get_domain_zone(&name); + let data = DomainData::new(zone.clone(), records); + let (keystore, transaction, difficulty) = { + let context = context.lock().unwrap(); + (context.get_keystore(), context.chain.get_domain_transaction(&name), context.chain.get_zone_difficulty(&name)) + }; + let data = serde_json::to_string(&data).unwrap(); + match transaction { + None => { + create_domain(context.clone(), miner.clone(), &name, &data, difficulty, &keystore); + } + Some(transaction) => { + if transaction.pub_key == keystore.get_public() { + create_domain(context.clone(), miner.clone(), &name, &data, difficulty, &keystore); + } else { + warn!("Tried to mine not owned domain!"); + let _ = web_view.eval(&format!("showWarning('{}');", "You cannot change domain that you don't own!")); + } } } } - } else { - warn!("Error in DNS records for domain!"); - let _ = web_view.eval(&format!("showWarning('{}');", "Something wrong with your records! Please, correct the error and try again.")); + Err(e) => { + warn!("Error in DNS records for domain!\n{}", e); + let _ = web_view.eval(&format!("showWarning('{}');", "Something wrong with your records! Please, correct the error and try again.")); + } } } ChangeDomain { .. } => {} @@ -208,11 +216,11 @@ pub fn run_interface(context: Arc>, miner: Arc>) { }; match transaction { None => { - create_domain(context.clone(), miner.clone(), &name, &data, &keystore); + create_domain(context.clone(), miner.clone(), &name, &data, ZONE_DIFFICULTY, &keystore); } Some(transaction) => { if transaction.pub_key == keystore.get_public() { - create_domain(context.clone(), miner.clone(), &name, &data, &keystore); + create_domain(context.clone(), miner.clone(), &name, &data, ZONE_DIFFICULTY, &keystore); } else { warn!("Tried to mine not owned domain!"); let _ = web_view.eval(&format!("showWarning('{}');", "You cannot change domain that you don't own!")); @@ -259,7 +267,7 @@ pub fn run_interface(context: Arc>, miner: Arc>) { interface.exit(); } -fn create_domain(context: Arc>, miner: Arc>, name: &str, data: &str, keystore: &Keystore) { +fn create_domain(context: Arc>, miner: Arc>, name: &str, data: &str, difficulty: u32, keystore: &Keystore) { let name = name.to_owned(); info!("Generating domain or zone {}", &name); if context.lock().unwrap().x_zones.has_zone(&name) { @@ -268,7 +276,7 @@ fn create_domain(context: Arc>, miner: Arc>, name: & } //let tags_vector: Vec = tags.into().trim().split(",").map(|s| s.trim()).map(String::from).collect(); let transaction = Transaction::from_str(name, "dns".to_owned(), data.to_owned(), keystore.get_public().clone()); - let block = Block::new(Some(transaction), keystore.get_public(), Bytes::default()); + let block = Block::new(Some(transaction), keystore.get_public(), Bytes::default(), difficulty); miner.lock().unwrap().add_block(block); }