diff --git a/src/blockchain/chain.rs b/src/blockchain/chain.rs index 717141d..5f45dc6 100644 --- a/src/blockchain/chain.rs +++ b/src/blockchain/chain.rs @@ -45,6 +45,7 @@ const SQL_GET_LAST_FULL_BLOCK_FOR_KEY: &str = "SELECT * FROM blocks WHERE `trans const SQL_GET_PUBLIC_KEY_BY_ID: &str = "SELECT pub_key FROM transactions WHERE identity = ? ORDER BY id DESC LIMIT 1;"; const SQL_GET_ID_BY_ID: &str = "SELECT identity FROM transactions WHERE identity = ? ORDER BY id DESC LIMIT 1;"; const SQL_GET_TRANSACTION_BY_ID: &str = "SELECT * FROM transactions WHERE identity = ? ORDER BY id DESC LIMIT 1;"; +const SQL_GET_TRANSACTIONS_WITH_ZONE: &str = "SELECT data FROM transactions WHERE data LIKE '%difficulty%';"; pub struct Chain { origin: Bytes, @@ -271,6 +272,25 @@ impl Chain { true } + pub fn get_zones(&self) -> Vec { + let mut result = Vec::new(); + match self.db.prepare(SQL_GET_TRANSACTIONS_WITH_ZONE) { + Ok(mut statement) => { + while statement.next().unwrap() == State::Row { + let data = statement.read::(0).unwrap(); + info!("Got zone data {}", &data); + if let Ok(zone_data) = serde_json::from_str(&data) { + result.push(zone_data); + } + } + } + Err(e) => { + warn!("Can't get zones from DB {}", e); + } + } + result + } + /// Checks if some zone exists in our blockchain pub fn is_zone_in_blockchain(&self, zone: &str) -> bool { if self.zones.borrow().contains(zone) { diff --git a/src/blockchain/transaction.rs b/src/blockchain/transaction.rs index 1e4c8e7..32fe748 100644 --- a/src/blockchain/transaction.rs +++ b/src/blockchain/transaction.rs @@ -6,6 +6,7 @@ use serde::ser::SerializeStruct; use crate::blockchain::hash_utils::*; use crate::bytes::Bytes; use crate::dns::protocol::DnsRecord; +use std::fmt::{Display, Formatter}; extern crate serde; extern crate serde_json; @@ -90,8 +91,14 @@ impl DomainData { } } -#[derive(Clone, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ZoneData { pub name: String, pub difficulty: u32 +} + +impl Display for ZoneData { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.write_str(&format!("{} ({})", self.name, self.difficulty)) + } } \ No newline at end of file diff --git a/src/web_ui.rs b/src/web_ui.rs index 0518c52..8bc789a 100644 --- a/src/web_ui.rs +++ b/src/web_ui.rs @@ -20,7 +20,7 @@ use alfis::dns::protocol::DnsRecord; use alfis::commons::{ZONE_MAX_LENGTH, ZONE_DIFFICULTY}; use Cmd::*; use alfis::blockchain::transaction::{DomainData, ZoneData}; -use self::web_view::WebView; +use self::web_view::{WebView, Handle}; use alfis::blockchain::enums::MineResult; pub fn run_interface(context: Arc>, miner: Arc>) { @@ -175,92 +175,110 @@ fn action_load_key(context: &Arc>, web_view: &mut WebView<()>) { fn action_loaded(context: &Arc>, web_view: &mut WebView<()>) { web_view.eval("showMiningIndicator(false, false);").expect("Error evaluating!"); - let handle = web_view.handle(); - let mut status = Status::new(); + let handle: Handle<()> = web_view.handle(); + let status = Arc::new(Mutex::new(Status::new())); + let context_copy = Arc::clone(&context); let mut c = context.lock().unwrap(); c.bus.register(move |_uuid, e| { //debug!("Got event from bus {:?}", &e); - let eval = match e { - Event::KeyCreated { path, public, hash } | - Event::KeyLoaded { path, public, hash } | - Event::KeySaved { path, public, hash } => { - format!("keystoreChanged('{}', '{}', '{}');", &path, &public, &hash) - } - Event::MinerStarted | Event::KeyGeneratorStarted => { - status.mining = true; - String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") - } - Event::MinerStopped {success, full} => { - status.mining = false; - let mut s = if status.syncing { - String::from("setLeftStatusBarText('Syncing...'); showMiningIndicator(true, true);") - } else { - String::from("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") - }; - if full { + let status = Arc::clone(&status); + let handle = handle.clone(); + let context_copy = Arc::clone(&context_copy); + thread::spawn(move || { + let mut status = status.lock().unwrap(); + let context = context_copy.lock().unwrap(); + let eval = match e { + Event::KeyCreated { path, public, hash } | + Event::KeyLoaded { path, public, hash } | + Event::KeySaved { path, public, hash } => { + format!("keystoreChanged('{}', '{}', '{}');", &path, &public, &hash) + } + Event::MinerStarted | Event::KeyGeneratorStarted => { + status.mining = true; + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") + } + Event::MinerStopped {success, full} => { + status.mining = false; + let mut s = if status.syncing { + String::from("setLeftStatusBarText('Syncing...'); showMiningIndicator(true, true);") + } else { + String::from("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + }; + if full { + match success { + true => { s.push_str(" showSuccess('Block successfully mined!')"); } + false => { s.push_str(" showSuccess('Mining unsuccessful, sorry.')"); } + } + } + s + } + Event::KeyGeneratorStopped {success} => { + status.mining = false; + let mut s = if status.syncing { + String::from("setLeftStatusBarText('Syncing...'); showMiningIndicator(true, true);") + } else { + String::from("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + }; match success { - true => { s.push_str(" showSuccess('Block successfully mined!')"); } - false => { s.push_str(" showSuccess('Mining unsuccessful, sorry.')"); } + true => { s.push_str(" showSuccess('Key pair successfully mined!
Don`t forget to save!')"); } + false => { s.push_str(" showSuccess('Key mining got nothing, sorry.')"); } + } + s + } + Event::Syncing { have, height } => { + status.syncing = true; + status.synced_blocks = have; + status.sync_height = height; + if status.mining { + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") + } else { + format!("setLeftStatusBarText('Synchronizing {}/{}'); showMiningIndicator(true, true);", have, height) } } - s - } - Event::KeyGeneratorStopped {success} => { - status.mining = false; - let mut s = if status.syncing { - String::from("setLeftStatusBarText('Syncing...'); showMiningIndicator(true, true);") - } else { - String::from("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") - }; - match success { - true => { s.push_str(" showSuccess('Key pair successfully mined!
Don`t forget to save!')"); } - false => { s.push_str(" showSuccess('Key mining got nothing, sorry.')"); } + Event::SyncFinished => { + status.syncing = false; + if status.mining { + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") + } else { + format!("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + } } - s - } - Event::Syncing { have, height } => { - status.syncing = true; - status.synced_blocks = have; - status.sync_height = height; - if status.mining { - String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") - } else { - format!("setLeftStatusBarText('Synchronizing {}/{}'); showMiningIndicator(true, true);", have, height) + Event::NetworkStatus { nodes, blocks } => { + if status.mining || status.syncing || nodes < 3 { + format!("setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) + } else { + format!("setLeftStatusBarText('Idle'); setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) + } } - } - Event::SyncFinished => { - status.syncing = false; - if status.mining { - String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") - } else { - format!("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + Event::BlockchainChanged {index} => { + info!("Current blockchain height is {}", index); + if let Ok(zones) = serde_json::to_string(&context.chain.get_zones()) { + let _ = handle.dispatch(move |web_view|{ + web_view.eval(&format!("zonesChanged('{}');", &zones)) + }); + } + String::new() // Nothing } - } - Event::NetworkStatus { nodes, blocks } => { - if status.mining || status.syncing || nodes < 3 { - format!("setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) - } else { - format!("setLeftStatusBarText('Idle'); setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) - } - } - _ => { String::new() } - }; + _ => { String::new() } + }; - if !eval.is_empty() { - handle.dispatch(move |web_view| { - web_view.eval(&eval.replace("\\", "\\\\")) - }).expect("Error dispatching!"); - } + if !eval.is_empty() { + handle.dispatch(move |web_view| { + web_view.eval(&eval.replace("\\", "\\\\")) + }).expect("Error dispatching!"); + } + }); true }); + if let Some(keystore) = c.get_keystore() { - let eval = format!("keystoreChanged('{}', '{}', '{}');", - keystore.get_path(), - &keystore.get_public().to_string(), - &keystore.get_hash().to_string()); - //debug!("Evaluating {}", &eval); - web_view.eval(&eval.replace("\\", "\\\\")).expect("Error evaluating!"); + let path = keystore.get_path().to_owned(); + let public = keystore.get_public().to_string(); + let hash = keystore.get_hash().to_string(); + c.bus.post(Event::KeyLoaded { path, public, hash }); } + let index = c.chain.height(); + c.bus.post(Event::BlockchainChanged { index }); } fn action_create_domain(context: Arc>, miner: Arc>, web_view: &mut WebView<()>, name: String, records: &String) { diff --git a/src/webview/index.html b/src/webview/index.html index 7fb4f71..2a0f7be 100644 --- a/src/webview/index.html +++ b/src/webview/index.html @@ -76,16 +76,39 @@