diff --git a/src/blockchain/blockchain.rs b/src/blockchain/blockchain.rs index 235a5b6..a648e7d 100644 --- a/src/blockchain/blockchain.rs +++ b/src/blockchain/blockchain.rs @@ -4,6 +4,8 @@ use crate::{Block, Bytes, Keystore, Transaction}; use crate::settings::Settings; #[allow(unused_imports)] use log::{trace, debug, info, warn, error}; +use std::collections::HashSet; +use std::cell::RefCell; const DB_NAME: &str = "blockchain.db"; @@ -13,6 +15,7 @@ pub struct Blockchain { pub blocks: Vec, last_block: Option, db: Connection, + zones: RefCell> } impl Blockchain { @@ -21,7 +24,7 @@ impl Blockchain { let version = settings.version; let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB"); - let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, db}; + let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, db, zones: RefCell::new(HashSet::new()) }; blockchain.init_db(); blockchain } @@ -173,20 +176,29 @@ impl Blockchain { if parts.last().unwrap().contains(".") { return false; } - // Checking for available zone, for this domain - let identity_hash = Transaction::hash_identity(parts.first().unwrap()); - let mut statement = self.db.prepare("SELECT identity FROM transactions WHERE identity = ? ORDER BY id DESC LIMIT 1;").unwrap(); - statement.bind(1, identity_hash.as_bytes()).expect("Error in bind"); - while let State::Row = statement.next().unwrap() { - // If there is such a zone - return true; - } - return false; + return self.is_zone_in_blockchain(parts.first().unwrap()); } true } + pub fn is_zone_in_blockchain(&self, zone: &str) -> bool { + if self.zones.borrow().contains(zone) { + return true; + } + + // Checking for existing zone in DB + let identity_hash = Transaction::hash_identity(zone); + let mut statement = self.db.prepare("SELECT identity FROM transactions WHERE identity = ? ORDER BY id DESC LIMIT 1;").unwrap(); + statement.bind(1, identity_hash.as_bytes()).expect("Error in bind"); + while let State::Row = statement.next().unwrap() { + // If there is such a zone + self.zones.borrow_mut().insert(zone.to_owned()); + return true; + } + false + } + pub fn get_domain_transaction(&self, domain: &str) -> Option { if domain.is_empty() { return None; diff --git a/src/blockchain/filter.rs b/src/blockchain/filter.rs index 55024b4..097853f 100644 --- a/src/blockchain/filter.rs +++ b/src/blockchain/filter.rs @@ -1,7 +1,7 @@ use crate::Context; use std::sync::{Mutex, Arc}; use crate::dns::filter::DnsFilter; -use crate::dns::protocol::{DnsPacket, QueryType, DnsRecord, DnsQuestion}; +use crate::dns::protocol::{DnsPacket, QueryType, DnsRecord, DnsQuestion, ResultCode}; #[allow(unused_imports)] use log::{trace, debug, info, warn, error}; @@ -35,7 +35,17 @@ impl DnsFilter for BlockchainFilter { let data = self.context.lock().unwrap().blockchain.get_domain_info(&search); match data { - None => { debug!("Not found data for domain {}", &search); } + None => { + debug!("Not found data for domain {}", &search); + if self.context.lock().unwrap().blockchain.is_zone_in_blockchain(parts[0]) { + // Create DnsPacket + let mut packet = DnsPacket::new(); + packet.questions.push(DnsQuestion::new(String::from(qname), qtype)); + packet.header.rescode = ResultCode::SERVFAIL; + trace!("Returning packet: {:?}", &packet); + return Some(packet); + } + } Some(data) => { info!("Found data for domain {}", &search); let mut records: Vec = match serde_json::from_str(&data) { @@ -118,14 +128,22 @@ impl DnsFilter for BlockchainFilter { } } - if !answers.is_empty() { + return if !answers.is_empty() { // Create DnsPacket let mut packet = DnsPacket::new(); packet.questions.push(DnsQuestion::new(String::from(qname), qtype)); for answer in answers { packet.answers.push(answer); } - return Some(packet); + trace!("Returning packet: {:?}", &packet); + Some(packet) + } else { + // Create DnsPacket + let mut packet = DnsPacket::new(); + packet.questions.push(DnsQuestion::new(String::from(qname), qtype)); + packet.header.rescode = ResultCode::SERVFAIL; + trace!("Returning packet: {:?}", &packet); + Some(packet) } } }