mirror of
https://github.com/Revertron/Alfis
synced 2024-11-03 15:40:19 +00:00
Reworked handling appropriate (mined) keys absence. Now that info handled in UI as well. It won't allow users without keys to mine domains or zones.
This commit is contained in:
parent
046c06beeb
commit
f5949e6ec0
@ -1,8 +1,8 @@
|
||||
# Settings
|
||||
origin = "00000102C2F9BFD2803284D93327F089D60FC72A06F19AF2384567F2646B8348"
|
||||
key_file = "default.key"
|
||||
key_file = "default1.key"
|
||||
listen = "[::]:4244"
|
||||
public = false
|
||||
public = true
|
||||
|
||||
# Bootstrap nodes
|
||||
#peers = ["test-ip4.alfis.name:4244", "test-ip6.alfis.name:4244"]
|
||||
|
@ -6,7 +6,7 @@ use log::{trace, debug, info, warn, error};
|
||||
pub struct Context {
|
||||
pub app_version: String,
|
||||
pub settings: Settings,
|
||||
pub keystore: Keystore,
|
||||
pub keystore: Option<Keystore>,
|
||||
pub chain: Chain,
|
||||
pub x_zones: ExternalZones,
|
||||
pub bus: Bus<Event>,
|
||||
@ -14,7 +14,7 @@ pub struct Context {
|
||||
|
||||
impl Context {
|
||||
/// Creating an essential context to work with
|
||||
pub fn new(app_version: String, settings: Settings, keystore: Keystore, chain: Chain) -> Context {
|
||||
pub fn new(app_version: String, settings: Settings, keystore: Option<Keystore>, chain: Chain) -> Context {
|
||||
Context { app_version, settings, keystore, chain, x_zones: ExternalZones::new(), bus: Bus::new() }
|
||||
}
|
||||
|
||||
@ -26,17 +26,17 @@ impl Context {
|
||||
warn!("Error loading keystore '{}'!", filename);
|
||||
},
|
||||
Some(keystore) => {
|
||||
self.keystore = keystore;
|
||||
self.keystore = Some(keystore);
|
||||
},
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_keystore(&self) -> Keystore {
|
||||
pub fn get_keystore(&self) -> Option<Keystore> {
|
||||
self.keystore.clone()
|
||||
}
|
||||
|
||||
pub fn set_keystore(&mut self, keystore: Keystore) {
|
||||
pub fn set_keystore(&mut self, keystore: Option<Keystore>) {
|
||||
self.keystore = keystore;
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,14 @@ impl DnsServer for DnsUdpServer {
|
||||
let mut req_buffer = BytePacketBuffer::new();
|
||||
let (_, src) = match socket.recv_from(&mut req_buffer.buf) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
debug!("Failed to read from UDP socket: {:?}", e);
|
||||
Err(err) => {
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
if code == 10004 {
|
||||
debug!("UDP service loop has finished");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug!("Failed to read from UDP socket: {:?}", err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@ -347,6 +353,12 @@ impl DnsServer for DnsTcpServer {
|
||||
let stream = match wrap_stream {
|
||||
Ok(stream) => stream,
|
||||
Err(err) => {
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
if code == 10004 {
|
||||
debug!("TCP service loop has finished");
|
||||
break;
|
||||
}
|
||||
}
|
||||
warn!("Failed to accept TCP connection: {:?}", err);
|
||||
continue;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::Bytes;
|
||||
use crate::{Bytes, Keystore};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Event {
|
||||
@ -12,7 +12,8 @@ pub enum Event {
|
||||
NewBlockReceived,
|
||||
BlockchainChanged { index: u64 },
|
||||
ActionStopMining,
|
||||
ActionMineLocker { index: u64, hash: Bytes },
|
||||
ActionMineLocker { index: u64, hash: Bytes, keystore: Box<Keystore> },
|
||||
ActionQuit,
|
||||
NetworkStatus { nodes: usize, blocks: u64 },
|
||||
Syncing { have: u64, height: u64 },
|
||||
SyncFinished,
|
||||
|
@ -128,6 +128,12 @@ impl Clone for Keystore {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Keystore {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.keypair.to_bytes().eq(&other.keypair.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if some public key is "strong" enough to mine domains
|
||||
/// TODO Optimize by caching Blakeout somewhere
|
||||
pub fn check_public_key_strength(key: &Bytes, strength: usize) -> bool {
|
||||
@ -155,7 +161,7 @@ pub fn create_key(context: Arc<Mutex<Context>>) {
|
||||
let hash = keystore.get_hash().to_string();
|
||||
info!("Key mined successfully: {:?}, hash: {}", &keystore.get_public(), &hash);
|
||||
context.bus.post(Event::KeyCreated { path: keystore.get_path().to_owned(), public: keystore.get_public().to_string(), hash });
|
||||
context.set_keystore(keystore);
|
||||
context.set_keystore(Some(keystore));
|
||||
}
|
||||
}
|
||||
let miners = miners_count.fetch_sub(1, atomic::Ordering::SeqCst) - 1;
|
||||
|
19
src/main.rs
19
src/main.rs
@ -80,13 +80,7 @@ fn main() {
|
||||
|
||||
let settings = Settings::load(&config_name);
|
||||
info!(target: LOG_TARGET_MAIN, "Loaded settings: {:?}", &settings);
|
||||
let keystore: Keystore = match Keystore::from_file(&settings.key_file, "") {
|
||||
None => {
|
||||
warn!(target: LOG_TARGET_MAIN, "Generated temporary keystore. Please, generate full-privileged keys.");
|
||||
Keystore::new()
|
||||
}
|
||||
Some(keystore) => { keystore }
|
||||
};
|
||||
let keystore = Keystore::from_file(&settings.key_file, "");
|
||||
let chain: Chain = Chain::new(&settings);
|
||||
if opt_matches.opt_present("l") {
|
||||
for i in 1..(chain.height() + 1) {
|
||||
@ -102,7 +96,8 @@ fn main() {
|
||||
Some(block) => { trace!(target: LOG_TARGET_MAIN, "Loaded DB with origin {:?}", &block.hash); }
|
||||
}
|
||||
let settings_copy = settings.clone();
|
||||
let context: Arc<Mutex<Context>> = Arc::new(Mutex::new(Context::new(env!("CARGO_PKG_VERSION").to_owned(), settings, keystore, chain)));
|
||||
let context = Context::new(env!("CARGO_PKG_VERSION").to_owned(), settings, keystore, chain);
|
||||
let context: Arc<Mutex<Context>> = Arc::new(Mutex::new(context));
|
||||
dns_utils::start_dns_server(&context, &settings_copy);
|
||||
|
||||
let mut miner_obj = Miner::new(Arc::clone(&context));
|
||||
@ -136,9 +131,11 @@ fn create_genesis_if_needed(context: &Arc<Mutex<Context>>, miner: &Arc<Mutex<Min
|
||||
let last_block = context.get_chain().last_block();
|
||||
let origin = context.settings.origin.clone();
|
||||
if origin.eq("") && last_block.is_none() {
|
||||
// If blockchain is empty, we are going to mine a Genesis block
|
||||
let block = Block::new(None, context.get_keystore().get_public(), Bytes::default(), BLOCK_DIFFICULTY);
|
||||
miner.lock().unwrap().add_block(block);
|
||||
if let Some(keystore) = &context.keystore {
|
||||
// If blockchain is empty, we are going to mine a Genesis block
|
||||
let block = Block::new(None, context.get_keystore().unwrap().get_public(), Bytes::default(), BLOCK_DIFFICULTY);
|
||||
miner.lock().unwrap().add_block(block, keystore.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
51
src/miner.rs
51
src/miner.rs
@ -8,17 +8,18 @@ use chrono::Utc;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use num_cpus;
|
||||
|
||||
use crate::{Block, Bytes, Context};
|
||||
use crate::{Block, Bytes, Context, Keystore};
|
||||
use crate::commons::{CHAIN_VERSION, LOCKER_DIFFICULTY, KEYSTORE_DIFFICULTY};
|
||||
use crate::blockchain::enums::BlockQuality;
|
||||
use crate::blockchain::hash_utils::*;
|
||||
use crate::keys::check_public_key_strength;
|
||||
use crate::event::Event;
|
||||
use blakeout::Blakeout;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Miner {
|
||||
context: Arc<Mutex<Context>>,
|
||||
blocks: Arc<Mutex<Vec<Block>>>,
|
||||
jobs: Arc<Mutex<Vec<MineJob>>>,
|
||||
running: Arc<AtomicBool>,
|
||||
mining: Arc<AtomicBool>,
|
||||
cond_var: Arc<Condvar>
|
||||
@ -28,15 +29,15 @@ impl Miner {
|
||||
pub fn new(context: Arc<Mutex<Context>>) -> Self {
|
||||
Miner {
|
||||
context,
|
||||
blocks: Arc::new(Mutex::new(Vec::new())),
|
||||
jobs: Arc::new(Mutex::new(Vec::new())),
|
||||
running: Arc::new(AtomicBool::new(false)),
|
||||
mining: Arc::new(AtomicBool::new(false)),
|
||||
cond_var: Arc::new(Condvar::new())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_block(&mut self, block: Block) {
|
||||
self.blocks.lock().unwrap().push(block);
|
||||
pub fn add_block(&mut self, block: Block, keystore: Keystore) {
|
||||
self.jobs.lock().unwrap().push(MineJob { block, keystore });
|
||||
self.cond_var.notify_one();
|
||||
}
|
||||
|
||||
@ -48,7 +49,7 @@ impl Miner {
|
||||
|
||||
pub fn start_mining_thread(&mut self) {
|
||||
let context = Arc::clone(&self.context);
|
||||
let blocks = self.blocks.clone();
|
||||
let blocks = self.jobs.clone();
|
||||
let running = self.running.clone();
|
||||
let mining = self.mining.clone();
|
||||
let cond_var = self.cond_var.clone();
|
||||
@ -73,7 +74,7 @@ impl Miner {
|
||||
}
|
||||
});
|
||||
let mining = self.mining.clone();
|
||||
let blocks = self.blocks.clone();
|
||||
let blocks = self.jobs.clone();
|
||||
let cond_var = self.cond_var.clone();
|
||||
self.context.lock().unwrap().bus.register(move |_uuid, e| {
|
||||
match e {
|
||||
@ -82,11 +83,11 @@ impl Miner {
|
||||
Event::ActionStopMining => {
|
||||
mining.store(false, Ordering::SeqCst);
|
||||
}
|
||||
Event::ActionMineLocker { index, hash } => {
|
||||
Event::ActionMineLocker { index, hash, keystore } => {
|
||||
if !mining.load(Ordering::SeqCst) {
|
||||
let mut block = Block::new(None, Bytes::default(), hash, LOCKER_DIFFICULTY);
|
||||
block.index = index;
|
||||
blocks.lock().unwrap().push(block);
|
||||
blocks.lock().unwrap().push(MineJob { block, keystore: keystore.deref().clone() });
|
||||
cond_var.notify_all();
|
||||
info!("Added a locker block to mine");
|
||||
}
|
||||
@ -101,16 +102,16 @@ impl Miner {
|
||||
self.running.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn mine_internal(context: Arc<Mutex<Context>>, mut block: Block, mining: Arc<AtomicBool>) {
|
||||
fn mine_internal(context: Arc<Mutex<Context>>, mut job: MineJob, mining: Arc<AtomicBool>) {
|
||||
// Clear signature and hash just in case
|
||||
block.signature = Bytes::default();
|
||||
block.hash = Bytes::default();
|
||||
block.version = CHAIN_VERSION;
|
||||
job.block.signature = Bytes::default();
|
||||
job.block.hash = Bytes::default();
|
||||
job.block.version = CHAIN_VERSION;
|
||||
// If this block needs to be a locker
|
||||
if block.index > 0 && !block.prev_block_hash.is_empty() {
|
||||
if job.block.index > 0 && !job.block.prev_block_hash.is_empty() {
|
||||
info!("Mining locker block");
|
||||
block.pub_key = context.lock().unwrap().keystore.get_public();
|
||||
if !check_public_key_strength(&block.pub_key, KEYSTORE_DIFFICULTY) {
|
||||
job.block.pub_key = job.keystore.get_public();
|
||||
if !check_public_key_strength(&job.block.pub_key, KEYSTORE_DIFFICULTY) {
|
||||
warn!("Can not mine block with weak public key!");
|
||||
context.lock().unwrap().bus.post(Event::MinerStopped);
|
||||
mining.store(false, Ordering::SeqCst);
|
||||
@ -121,7 +122,7 @@ impl Miner {
|
||||
Some(last_block) => {
|
||||
info!("Last block found");
|
||||
// If we were doing something else and got new block before we could mine this block
|
||||
if last_block.index > block.index || last_block.hash != block.prev_block_hash {
|
||||
if last_block.index > job.block.index || last_block.hash != job.block.prev_block_hash {
|
||||
warn!("We missed block to lock");
|
||||
context.lock().unwrap().bus.post(Event::MinerStopped);
|
||||
mining.store(false, Ordering::SeqCst);
|
||||
@ -130,8 +131,8 @@ impl Miner {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
block.index = context.lock().unwrap().chain.height() + 1;
|
||||
block.prev_block_hash = match context.lock().unwrap().chain.last_block() {
|
||||
job.block.index = context.lock().unwrap().chain.height() + 1;
|
||||
job.block.prev_block_hash = match context.lock().unwrap().chain.last_block() {
|
||||
None => { Bytes::default() }
|
||||
Some(block) => { block.hash }
|
||||
};
|
||||
@ -144,12 +145,12 @@ impl Miner {
|
||||
debug!("Starting {} threads for mining", cpus);
|
||||
for _cpu in 0..cpus {
|
||||
let context = Arc::clone(&context);
|
||||
let block = block.clone();
|
||||
let job = job.clone();
|
||||
let mining = Arc::clone(&mining);
|
||||
let live_threads = Arc::clone(&live_threads);
|
||||
thread::spawn(move || {
|
||||
live_threads.fetch_add(1, Ordering::SeqCst);
|
||||
match find_hash(Arc::clone(&context), block, Arc::clone(&mining)) {
|
||||
match find_hash(Arc::clone(&context), job.block, Arc::clone(&mining)) {
|
||||
None => {
|
||||
debug!("Mining was cancelled");
|
||||
let count = live_threads.fetch_sub(1, Ordering::SeqCst);
|
||||
@ -162,7 +163,7 @@ impl Miner {
|
||||
Some(mut block) => {
|
||||
let index = block.index;
|
||||
let mut context = context.lock().unwrap();
|
||||
block.signature = Bytes::from_bytes(&context.keystore.sign(&block.as_bytes()));
|
||||
block.signature = Bytes::from_bytes(&job.keystore.sign(&block.as_bytes()));
|
||||
if context.chain.check_new_block(&block) != BlockQuality::Good {
|
||||
warn!("Error adding mined block!");
|
||||
if index == 0 {
|
||||
@ -184,6 +185,12 @@ impl Miner {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MineJob {
|
||||
block: Block,
|
||||
keystore: Keystore
|
||||
}
|
||||
|
||||
fn find_hash(context: Arc<Mutex<Context>>, mut block: Block, running: Arc<AtomicBool>) -> Option<Block> {
|
||||
let difficulty = block.difficulty as usize;
|
||||
let full = block.transaction.is_some();
|
||||
|
@ -18,6 +18,7 @@ use std::collections::HashSet;
|
||||
use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers, Bytes};
|
||||
use crate::blockchain::enums::BlockQuality;
|
||||
use crate::commons::CHAIN_VERSION;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
const SERVER: Token = Token(0);
|
||||
const POLL_TIMEOUT: Option<Duration> = Some(Duration::from_millis(3000));
|
||||
@ -40,6 +41,9 @@ impl Network {
|
||||
(c.settings.listen.clone(), c.settings.peers.clone())
|
||||
};
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
subscribe_to_bus(&mut self.context, Arc::clone(&running));
|
||||
|
||||
// Starting server socket
|
||||
let addr = listen_addr.parse().expect("Error parsing listen address");
|
||||
let mut server = TcpListener::bind(addr).expect("Can't bind to address");
|
||||
@ -62,6 +66,9 @@ impl Network {
|
||||
loop {
|
||||
// Poll Mio for events, blocking until we get an event.
|
||||
poll.poll(&mut events, POLL_TIMEOUT).expect("Error polling sockets");
|
||||
if !running.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Process each event.
|
||||
for event in events.iter() {
|
||||
@ -125,11 +132,26 @@ impl Network {
|
||||
peers.send_pings(poll.registry(), height, hash);
|
||||
peers.connect_new_peers(poll.registry(), &mut unique_token);
|
||||
}
|
||||
info!("Network loop finished");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn subscribe_to_bus(context: &mut Arc<Mutex<Context>>, running: Arc<AtomicBool>) {
|
||||
use crate::event::Event;
|
||||
context.lock().unwrap().bus.register(move |_uuid, e| {
|
||||
match e {
|
||||
Event::ActionQuit => {
|
||||
running.store(false, Ordering::SeqCst);
|
||||
return false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, registry: &Registry, event: &Event) -> bool {
|
||||
if event.is_error() || (event.is_read_closed() && event.is_write_closed()) {
|
||||
return false;
|
||||
@ -415,16 +437,19 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
||||
fn mine_locker_block(context: Arc<Mutex<Context>>) {
|
||||
let mut context = context.lock().unwrap();
|
||||
if let Some(block) = context.chain.last_block() {
|
||||
if block.index < context.chain.max_height() {
|
||||
info!("No locker mining while syncing");
|
||||
return;
|
||||
}
|
||||
let lockers: HashSet<Bytes> = context.chain.get_block_lockers(&block).into_iter().collect();
|
||||
if lockers.contains(&context.keystore.get_public()) {
|
||||
info!("We have an honor to mine locker block!");
|
||||
context.bus.post(crate::event::Event::ActionMineLocker { index: block.index + 1, hash: block.hash });
|
||||
} else if !lockers.is_empty() {
|
||||
info!("Locker block must be mined by other nodes");
|
||||
if let Some(keystore) = &context.keystore {
|
||||
if block.index < context.chain.max_height() {
|
||||
info!("No locker mining while syncing");
|
||||
return;
|
||||
}
|
||||
let lockers: HashSet<Bytes> = context.chain.get_block_lockers(&block).into_iter().collect();
|
||||
if lockers.contains(&keystore.get_public()) {
|
||||
info!("We have an honor to mine locker block!");
|
||||
let keystore = Box::new(keystore.clone());
|
||||
context.bus.post(crate::event::Event::ActionMineLocker { index: block.index + 1, hash: block.hash, keystore });
|
||||
} else if !lockers.is_empty() {
|
||||
info!("Locker block must be mined by other nodes");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,13 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
||||
.build()
|
||||
.expect("Error building GUI");
|
||||
|
||||
run_interface_loop(&mut interface);
|
||||
let mut context = Arc::clone(&context);
|
||||
run_interface_loop(&mut context, &mut interface);
|
||||
interface.exit();
|
||||
}
|
||||
|
||||
/// Indefinitely loops through WebView steps
|
||||
fn run_interface_loop(interface: &mut WebView<()>) {
|
||||
fn run_interface_loop(context: &mut Arc<Mutex<Context>>, interface: &mut WebView<()>) {
|
||||
// We use this ugly loop to lower CPU usage a lot.
|
||||
// If we use .run() or only .step() in a loop without sleeps it will try
|
||||
// to support 60FPS and uses more CPU than it should.
|
||||
@ -76,6 +77,8 @@ fn run_interface_loop(interface: &mut WebView<()>) {
|
||||
match interface.step() {
|
||||
None => {
|
||||
info!("Interface closed, exiting");
|
||||
context.lock().unwrap().bus.post(Event::ActionQuit);
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
break;
|
||||
}
|
||||
Some(result) => {
|
||||
@ -101,8 +104,10 @@ fn action_check_zone(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>,
|
||||
web_view.eval("zoneAvailable(false)").expect("Error evaluating!");
|
||||
} else {
|
||||
let c = context.lock().unwrap();
|
||||
let available = c.get_chain().is_domain_available(&name, &c.get_keystore());
|
||||
web_view.eval(&format!("zoneAvailable({})", available)).expect("Error evaluating!");
|
||||
if let Some(keystore) = c.get_keystore() {
|
||||
let available = c.get_chain().is_domain_available(&name, &keystore);
|
||||
web_view.eval(&format!("zoneAvailable({})", available)).expect("Error evaluating!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,24 +119,31 @@ fn action_check_record(web_view: &mut WebView<()>, data: String) {
|
||||
}
|
||||
|
||||
fn action_check_domain(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>, name: String) {
|
||||
let name = name.to_lowercase();
|
||||
let c = context.lock().unwrap();
|
||||
let available = c.get_chain().is_domain_available(&name, &c.get_keystore());
|
||||
web_view.eval(&format!("domainAvailable({})", available)).expect("Error evaluating!");
|
||||
if let Some(keystore) = c.get_keystore() {
|
||||
let name = name.to_lowercase();
|
||||
let available = c.get_chain().is_domain_available(&name, &keystore);
|
||||
web_view.eval(&format!("domainAvailable({})", available)).expect("Error evaluating!");
|
||||
}
|
||||
}
|
||||
|
||||
fn action_save_key(context: &Arc<Mutex<Context>>) {
|
||||
if context.lock().unwrap().get_keystore().is_none() {
|
||||
return;
|
||||
}
|
||||
let result = tfd::save_file_dialog_with_filter("Save keys file", "", &["*.key"], "Key files (*.key)");
|
||||
match result {
|
||||
None => {}
|
||||
Some(new_path) => {
|
||||
let mut context = context.lock().unwrap();
|
||||
let path = new_path.clone();
|
||||
let public = context.keystore.get_public().to_string();
|
||||
let hash = context.keystore.get_hash().to_string();
|
||||
context.keystore.save(&new_path, "");
|
||||
info!("Key file saved to {}", &path);
|
||||
context.bus.post(Event::KeySaved { path, public, hash });
|
||||
if let Some(mut keystore) = context.get_keystore() {
|
||||
let public = keystore.get_public().to_string();
|
||||
let hash = keystore.get_hash().to_string();
|
||||
keystore.save(&new_path, "");
|
||||
info!("Key file saved to {}", &path);
|
||||
context.bus.post(Event::KeySaved { path, public, hash });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +164,7 @@ fn action_load_key(context: &Arc<Mutex<Context>>, _web_view: &mut WebView<()>) {
|
||||
let public = keystore.get_public().to_string();
|
||||
let hash = keystore.get_hash().to_string();
|
||||
c.bus.post(Event::KeyLoaded { path, public, hash });
|
||||
c.set_keystore(keystore);
|
||||
c.set_keystore(Some(keystore));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,23 +225,32 @@ fn action_loaded(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>) {
|
||||
};
|
||||
|
||||
if !eval.is_empty() {
|
||||
//debug!("Evaluating {}", &eval);
|
||||
handle.dispatch(move |web_view| {
|
||||
web_view.eval(&eval.replace("\\", "\\\\"))
|
||||
}).expect("Error dispatching!");
|
||||
}
|
||||
true
|
||||
});
|
||||
let eval = format!("keystoreChanged('{}', '{}', '{}');", c.keystore.get_path(), &c.keystore.get_public().to_string(), &c.keystore.get_hash().to_string());
|
||||
debug!("Evaluating {}", &eval);
|
||||
web_view.eval(&eval.replace("\\", "\\\\")).expect("Error evaluating!");
|
||||
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!");
|
||||
}
|
||||
}
|
||||
|
||||
fn action_create_domain(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>, web_view: &mut WebView<()>, name: String, records: &String) {
|
||||
debug!("Creating domain with records: {}", records);
|
||||
let c = Arc::clone(&context);
|
||||
let context = context.lock().unwrap();
|
||||
let pub_key = context.keystore.get_public();
|
||||
if context.get_keystore().is_none() {
|
||||
show_warning(web_view, "You don't have keys loaded!\nLoad or mine the keys and try again.");
|
||||
return;
|
||||
}
|
||||
let keystore = context.get_keystore().unwrap();
|
||||
let pub_key = keystore.get_public();
|
||||
match context.chain.can_mine_domain(&name, &records, &pub_key) {
|
||||
MineResult::Fine => {
|
||||
let zone = get_domain_zone(&name);
|
||||
@ -237,7 +258,6 @@ fn action_create_domain(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>,
|
||||
if let Ok(records) = serde_json::from_str::<Vec<DnsRecord>>(&records) {
|
||||
let data = DomainData::new(zone.clone(), records);
|
||||
let data = serde_json::to_string(&data).unwrap();
|
||||
let keystore = context.keystore.clone();
|
||||
std::mem::drop(context);
|
||||
create_domain(c, miner, &name, &data, difficulty, &keystore);
|
||||
let _ = web_view.eval("domainMiningStarted()");
|
||||
@ -271,18 +291,23 @@ fn action_create_zone(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>, we
|
||||
let context = context.lock().unwrap();
|
||||
(context.get_keystore(), context.chain.get_domain_transaction(&name))
|
||||
};
|
||||
match transaction {
|
||||
None => {
|
||||
create_domain(Arc::clone(&context), miner.clone(), &name, &data, ZONE_DIFFICULTY, &keystore);
|
||||
}
|
||||
Some(transaction) => {
|
||||
if transaction.pub_key == keystore.get_public() {
|
||||
if let Some(keystore) = keystore {
|
||||
match transaction {
|
||||
None => {
|
||||
create_domain(Arc::clone(&context), miner.clone(), &name, &data, ZONE_DIFFICULTY, &keystore);
|
||||
} else {
|
||||
warn!("Tried to mine not owned domain!");
|
||||
show_warning(web_view, "You cannot change domain that you don't own!");
|
||||
}
|
||||
Some(transaction) => {
|
||||
if transaction.pub_key == keystore.get_public() {
|
||||
create_domain(Arc::clone(&context), miner.clone(), &name, &data, ZONE_DIFFICULTY, &keystore);
|
||||
} else {
|
||||
warn!("Tried to mine not owned domain!");
|
||||
show_warning(web_view, "You cannot change domain that you don't own!");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Can not mine without keys!");
|
||||
show_warning(web_view, "You don't have keys loaded!\nLoad or mine the keys and try again.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +328,7 @@ fn create_domain(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>, name: &
|
||||
//let tags_vector: Vec<String> = 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(), difficulty);
|
||||
miner.lock().unwrap().add_block(block);
|
||||
miner.lock().unwrap().add_block(block, keystore.clone());
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -154,7 +154,7 @@
|
||||
<div class="content is-hidden" id="key_load">
|
||||
<div class="field">
|
||||
<label class="label">Key path</label>
|
||||
<p id="key_file_name">Key not saved</p>
|
||||
<p id="key_file_name">Not loaded</p>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
@ -169,16 +169,16 @@
|
||||
|
||||
<br>
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-success" onclick="loadKey();">Load key</button>
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
<button class="button is-warning" onclick="createKey();">Mine new key</button>
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
<button class="button is-primary" onclick="saveKey();">Save key</button>
|
||||
<button class="button is-light" onclick="loadKey();">Load key</button>
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
<button id="save_key" class="button is-light" onclick="saveKey();" disabled>Save key</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -190,7 +190,7 @@
|
||||
<div class="field">
|
||||
<label class="label">Domain name</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="example.ygg" id="new_domain" oninput="onDomainChange(this)">
|
||||
<input class="input" type="text" placeholder="example.ygg" id="new_domain" oninput="onDomainChange(this)" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -198,7 +198,7 @@
|
||||
<div class="field">
|
||||
<label class="label">Domain tags (will be used for search)</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="blog, community, friendship" id="new_domain_tags">
|
||||
<input class="input" type="text" placeholder="blog, community, friendship" id="new_domain_tags" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -210,10 +210,10 @@
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-success" id="add_record_button" onclick="showNewRecordDialog();">Add record</button>
|
||||
<button id="new_domain_button" class="button is-warning" onclick="createDomain();" disabled>Mine domain</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-link" id="new_domain_button" onclick="createDomain();" disabled>Mine domain</button>
|
||||
<button id="add_record_button" class="button is-light" onclick="showNewRecordDialog();" disabled>Add record</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -225,7 +225,7 @@
|
||||
<div class="field">
|
||||
<label class="label">Zone name</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="ygg" id="new_zone" oninput="onZoneChange()">
|
||||
<input class="input" type="text" placeholder="ygg" id="new_zone" oninput="onZoneChange()" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -233,7 +233,7 @@
|
||||
<div class="field">
|
||||
<label class="label">Difficulty (for all domains in zone)</label>
|
||||
<div class="control">
|
||||
<input class="input" type="number" placeholder="20" id="new_zone_difficulty" oninput="onZoneChange()">
|
||||
<input class="input" type="number" placeholder="20" id="new_zone_difficulty" oninput="onZoneChange()" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -241,7 +241,7 @@
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-link" id="new_zone_button" onclick="createZone();" disabled>Mine zone</button>
|
||||
<button class="button is-warning" id="new_zone_button" onclick="createZone();" disabled>Mine zone</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -189,12 +189,15 @@ function onDomainChange(element) {
|
||||
function domainAvailable(available) {
|
||||
input = document.getElementById("new_domain");
|
||||
button = document.getElementById("new_domain_button");
|
||||
button2 = document.getElementById("add_record_button");
|
||||
if (available) {
|
||||
input.className = "input";
|
||||
button.disabled = false
|
||||
button2.disabled = false
|
||||
} else {
|
||||
input.className = "input is-danger";
|
||||
button.disabled = true
|
||||
button2.disabled = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,4 +312,15 @@ function keystoreChanged(path, pub_key, hash) {
|
||||
key_public_key.innerHTML = pub_key;
|
||||
var key_public_hash = document.getElementById("key_public_hash");
|
||||
key_public_hash.innerHTML = hash;
|
||||
var save_key = document.getElementById("save_key");
|
||||
save_key.disabled = false;
|
||||
|
||||
var new_domain = document.getElementById("new_domain");
|
||||
new_domain.disabled = false;
|
||||
var new_domain_tags = document.getElementById("new_domain_tags");
|
||||
new_domain_tags.disabled = false;
|
||||
var new_zone = document.getElementById("new_zone");
|
||||
new_zone.disabled = false;
|
||||
var new_zone_difficulty = document.getElementById("new_zone_difficulty");
|
||||
new_zone_difficulty.disabled = false;
|
||||
}
|
Loading…
Reference in New Issue
Block a user