Implemented mining zone screen. Added a lot of user input checks.

This commit is contained in:
Revertron
2021-02-22 21:45:32 +01:00
parent 2766cc4a05
commit d7911dfe04
6 changed files with 180 additions and 12 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "alfis" name = "alfis"
version = "0.1.0" version = "0.1.1"
authors = ["Revertron <alfis@revertron.com>"] authors = ["Revertron <alfis@revertron.com>"]
edition = "2018" edition = "2018"
build = "build.rs" build = "build.rs"
+48 -8
View File
@@ -22,7 +22,7 @@ use simple_logger::{SimpleLogger};
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{trace, debug, info, warn, error, LevelFilter}; use log::{trace, debug, info, warn, error, LevelFilter};
use alfis::{Blockchain, Bytes, Context, Keystore, Transaction}; use alfis::{Blockchain, Bytes, Context, Keystore, Transaction, check_domain};
use alfis::event::Event; use alfis::event::Event;
use alfis::miner::Miner; use alfis::miner::Miner;
use alfis::p2p::Network; use alfis::p2p::Network;
@@ -50,7 +50,8 @@ fn main() {
AttachConsole(ATTACH_PARENT_PROCESS); AttachConsole(ATTACH_PARENT_PROCESS);
} }
println!("Starting ALFIS 0.1.0"); let version = env!("CARGO_PKG_VERSION");
println!("Starting ALFIS {}", version);
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let program = args[0].clone(); let program = args[0].clone();
@@ -165,10 +166,12 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
let scripts = inline_script(include_str!("webview/scripts.js")); let scripts = inline_script(include_str!("webview/scripts.js"));
let html = Content::Html(file_content.to_owned().replace("{styles}", &styles).replace("{scripts}", &scripts)); let html = Content::Html(file_content.to_owned().replace("{styles}", &styles).replace("{scripts}", &scripts));
let title = format!("ALFIS {}", env!("CARGO_PKG_VERSION"));
let mut interface = web_view::builder() let mut interface = web_view::builder()
.title("ALFIS 0.1.0") .title(&title)
.content(html) .content(html)
.size(1024, 720) .size(1023, 720)
.min_size(895, 350)
.resizable(true) .resizable(true)
.debug(false) .debug(false)
.user_data(()) .user_data(())
@@ -242,18 +245,22 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
} }
} }
CheckDomain { name} => { CheckDomain { name} => {
let name = name.to_lowercase();
let c = context.lock().unwrap(); let c = context.lock().unwrap();
let available = c.get_blockchain().is_domain_available(&name, &c.get_keystore()); let available = c.get_blockchain().is_domain_available(&name, &c.get_keystore());
web_view.eval(&format!("domainAvailable({})", available)).expect("Error evaluating!"); web_view.eval(&format!("domainAvailable({})", available)).expect("Error evaluating!");
} }
CreateDomain { name, records, .. } => { CreateDomain { name, records, .. } => {
debug!("Got records: {}", records); debug!("Got records: {}", records);
let name = name.to_lowercase();
if !check_domain(&name, true) {
return Ok(());
}
if serde_json::from_str::<Vec<DnsRecord>>(&records).is_ok() { if serde_json::from_str::<Vec<DnsRecord>>(&records).is_ok() {
let keystore = { let (keystore, transaction) = {
let guard = context.lock().unwrap(); let context = context.lock().unwrap();
guard.get_keystore() (context.get_keystore(), context.blockchain.get_domain_transaction(&name))
}; };
let transaction = { context.lock().unwrap().blockchain.get_domain_transaction(&name) };
match transaction { match transaction {
None => { None => {
create_domain(miner.clone(), name, records, &keystore); create_domain(miner.clone(), name, records, &keystore);
@@ -275,6 +282,37 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
ChangeDomain { .. } => {} ChangeDomain { .. } => {}
RenewDomain { .. } => {} RenewDomain { .. } => {}
TransferDomain { .. } => {} TransferDomain { .. } => {}
CheckZone { name} => {
let name = name.to_lowercase();
if !check_domain(&name, false) {
web_view.eval("zoneAvailable(false)").expect("Error evaluating!");
} else {
let c = context.lock().unwrap();
let available = c.get_blockchain().is_domain_available(&name, &c.get_keystore());
web_view.eval(&format!("zoneAvailable({})", available)).expect("Error evaluating!");
}
}
CreateZone { name, data } => {
let name = name.to_lowercase();
let data = data.to_lowercase();
let (keystore, transaction) = {
let context = context.lock().unwrap();
(context.get_keystore(), context.blockchain.get_domain_transaction(&name))
};
match transaction {
None => {
create_domain(miner.clone(), name, data, &keystore);
}
Some(transaction) => {
if transaction.pub_key == keystore.get_public() {
create_domain(miner.clone(), name, data, &keystore);
} else {
warn!("Tried to mine not owned domain!");
let _ = web_view.eval(&format!("showWarning('{}');", "You cannot change domain that you don't own!"));
}
}
}
}
StopMining => { StopMining => {
context.lock().unwrap().bus.post(Event::ActionStopMining); context.lock().unwrap().bus.post(Event::ActionStopMining);
} }
@@ -419,6 +457,8 @@ pub enum Cmd {
LoadKey{}, LoadKey{},
CreateKey{}, CreateKey{},
SaveKey{}, SaveKey{},
CheckZone{name: String},
CreateZone{name: String, data: String},
CheckDomain{name: String}, CheckDomain{name: String},
CreateDomain{name: String, records: String, tags: String}, CreateDomain{name: String, records: String, tags: String},
ChangeDomain{name: String, records: String, tags: String}, ChangeDomain{name: String, records: String, tags: String},
+1 -1
View File
@@ -67,7 +67,7 @@ impl Peers {
if self.peers if self.peers
.iter() .iter()
.find(|(token, peer)| peer.get_addr() == addr) .find(|(_token, peer)| peer.get_addr() == addr)
.is_some() { .is_some() {
debug!("Skipping address from exchange: {}", &addr); debug!("Skipping address from exchange: {}", &addr);
continue; continue;
+52
View File
@@ -19,6 +19,38 @@ pub fn from_hex(string: &str) -> Result<Vec<u8>, num::ParseIntError> {
.collect() .collect()
} }
pub fn check_domain(name: &str, allow_dots: bool) -> bool {
if name.starts_with('.') || name.starts_with('-') || name.ends_with('.') || name.ends_with('-') {
return false;
}
let mut last_dot = false;
let mut last_hyphen = false;
for char in name.chars() {
if allow_dots && char == '.' {
if last_dot {
return false;
} else {
last_dot = true;
continue;
}
}
if char == '-' {
if last_hyphen {
return false;
} else {
last_hyphen = true;
continue;
}
}
last_dot = false;
last_hyphen = false;
if !char.is_alphanumeric() {
return false;
}
}
true
}
fn split_n(s: &str, n: usize) -> Vec<&str> { fn split_n(s: &str, n: usize) -> Vec<&str> {
(0..=(s.len() - n + 1) / 2) (0..=(s.len() - n + 1) / 2)
.map(|i| &s[2 * i..2 * i + n]) .map(|i| &s[2 * i..2 * i + n])
@@ -54,3 +86,23 @@ pub fn random_string(length: usize) -> String {
} }
result result
} }
#[cfg(test)]
mod test {
use crate::check_domain;
#[test]
fn test_check_domain() {
assert!(check_domain("abc0", false));
assert!(!check_domain("ab.c", false));
assert!(check_domain("a.b.c", true));
assert!(!check_domain("ab..c", true));
assert!(check_domain("a-b.c", true));
assert!(!check_domain("a--b.c", true));
assert!(check_domain("a-0-b.c", true));
assert!(!check_domain("-ab.c", true));
assert!(!check_domain("ab.c-", true));
assert!(!check_domain(".ab.c", true));
assert!(!check_domain("ab.c-", true));
}
}
+32
View File
@@ -128,6 +128,7 @@
<p class="menu-label">Domain management</p> <p class="menu-label">Domain management</p>
<ul class="menu-list"> <ul class="menu-list">
<li><a onclick="openTab(this, 'dom_new')">Mine domain</a></li> <li><a onclick="openTab(this, 'dom_new')">Mine domain</a></li>
<li><a onclick="openTab(this, 'zone_new')">Mine zone</a></li>
<!--<li><a onclick="openTab(this, 'dom_edit')">Manage domain</a></li> <!--<li><a onclick="openTab(this, 'dom_edit')">Manage domain</a></li>
<li><a onclick="openTab(this, 'dom_renew')">Renew domain</a></li> <li><a onclick="openTab(this, 'dom_renew')">Renew domain</a></li>
<li><a onclick="openTab(this, 'dom_transfer')">Transfer domain</a></li>--> <li><a onclick="openTab(this, 'dom_transfer')">Transfer domain</a></li>-->
@@ -209,6 +210,37 @@
</div> </div>
<div class="content is-hidden" id="zone_new">
<form action="#">
<div class="columns">
<div class="column">
<div class="field">
<label class="label">Zone name</label>
<div class="control">
<input class="input" type="text" placeholder="ygg" id="new_zone" oninput="onZoneChange()">
</div>
</div>
</div>
<div class="column">
<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()">
</div>
</div>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link" id="new_zone_button" onclick="createZone();" disabled>Mine zone</button>
</div>
</div>
</form>
</div>
<div class="content is-hidden" id="dom_edit"> <div class="content is-hidden" id="dom_edit">
<form action="#"> <form action="#">
<div class="field"> <div class="field">
+46 -2
View File
@@ -131,7 +131,17 @@ function createDomain() {
recordsBuffer = []; recordsBuffer = [];
} }
function changeDomain() { function createZone() {
new_zone = document.getElementById("new_zone").value;
difficulty = document.getElementById("new_zone_difficulty").value;
obj = {};
obj.name = new_zone;
obj.difficulty = difficulty;
data = JSON.stringify(obj);
external.invoke(JSON.stringify({cmd: 'createZone', name: new_zone, data: data}));
}
/*function changeDomain() {
domain = document.getElementById("change_domain").value; domain = document.getElementById("change_domain").value;
dom_records = document.getElementById("change_domain_records").value; dom_records = document.getElementById("change_domain_records").value;
dom_tags = document.getElementById("change_domain_records").value; dom_tags = document.getElementById("change_domain_records").value;
@@ -148,7 +158,7 @@ function transferDomain() {
domain = document.getElementById("transfer_domain").value; domain = document.getElementById("transfer_domain").value;
new_owner = document.getElementById("transfer_domain_transfer_owner").value; new_owner = document.getElementById("transfer_domain_transfer_owner").value;
external.invoke(JSON.stringify({cmd: 'transferDomain', name: domain, owner: new_owner})); external.invoke(JSON.stringify({cmd: 'transferDomain', name: domain, owner: new_owner}));
} }*/
function sendAction(param) { function sendAction(param) {
external.invoke(JSON.stringify(param)); external.invoke(JSON.stringify(param));
@@ -170,6 +180,40 @@ function domainAvailable(available) {
} }
} }
function onZoneChange() {
button = document.getElementById("new_zone_button");
diff = document.getElementById("new_zone_difficulty");
d = parseInt(diff.value);
// Checking for NaN first
if (d != d || d < 20 || d > 50) {
button.disabled = true;
diff.className = "input is-danger";
} else {
diff.className = "input";
input = document.getElementById("new_zone");
external.invoke(JSON.stringify({cmd: 'checkZone', name: input.value}));
}
}
function zoneAvailable(available) {
input = document.getElementById("new_zone");
button = document.getElementById("new_zone_button");
if (available) {
input.className = "input";
button.disabled = false;
diff = document.getElementById("new_zone_difficulty");
d = parseInt(diff.value);
// Checking for NaN first
if (d != d || d < 20 || d > 50) {
button.disabled = true;
diff.className = "input is-danger";
}
} else {
input.className = "input is-danger";
button.disabled = true;
}
}
function showModalDialog(text, callback) { function showModalDialog(text, callback) {
message = document.getElementById("modal_text"); message = document.getElementById("modal_text");
message.textContent = text; message.textContent = text;