diff --git a/Cargo.lock b/Cargo.lock index e1f9b01..56f66b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,7 +84,7 @@ dependencies = [ [[package]] name = "alfis" -version = "0.7.0" +version = "0.7.1" dependencies = [ "base64", "bincode", @@ -759,34 +759,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -911,9 +891,9 @@ checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" [[package]] name = "proc-macro2" -version = "1.0.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] @@ -1058,18 +1038,18 @@ checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" dependencies = [ "serde", ] @@ -1086,9 +1066,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1224,9 +1204,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.80" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ "proc-macro2", "quote", @@ -1339,9 +1319,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] @@ -1438,9 +1418,9 @@ checksum = "5a1f0175e03a0973cf4afd476bef05c26e228520400eb1fd473ad417b1c00ffb" [[package]] name = "uuid" -version = "0.8.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0" dependencies = [ "getrandom 0.2.3", "serde", @@ -1642,6 +1622,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winres" version = "0.1.12" diff --git a/Cargo.toml b/Cargo.toml index dec9cf1..aa8c7fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alfis" -version = "0.7.0" +version = "0.7.1" authors = ["Revertron "] edition = "2021" build = "build.rs" @@ -14,7 +14,7 @@ exclude = ["blockchain.db", "alfis.toml"] getopts = "0.2.21" log = "0.4.16" simplelog = "0.11.2" -toml = "0.5.8" +toml = "0.5.9" digest = "0.10.2" sha2 = "0.10.2" ed25519-dalek = "1.0" @@ -25,7 +25,7 @@ signature = "1.5" blakeout = "0.3.0" num_cpus = "1.13.1" byteorder = "1.4.3" -serde = { version = "1.0.136", features = ["derive"] } +serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.79" bincode = "1.3.3" serde_cbor = "0.11.2" @@ -36,8 +36,8 @@ chrono = { version = "0.4.19", features = ["serde"] } rand = { version = "0.8.5", package = "rand" } rand-old = { package = "rand", version = "0.7.0" } # For ed25519-dalek sqlite = "0.26.0" -uuid = { version = "0.8.2", features = ["serde", "v4"] } -mio = { version = "0.8.2", features = ["os-poll", "net"] } +uuid = { version = "1.0.0", features = ["serde", "v4"] } +mio = { version = "0.8.3", features = ["os-poll", "net"] } ureq = { version = "2.4", optional = true } lru = "0.7.5" derive_more = "0.99.17" @@ -59,7 +59,7 @@ thread-priority = "0.8.2" winres = "0.1.12" [dev-dependencies] -serde_bytes = "0.11.5" +serde_bytes = "0.11.6" serde_derive = "1.0.126" [profile.release] diff --git a/src/blockchain/chain.rs b/src/blockchain/chain.rs index 67fd74f..bdeee1a 100644 --- a/src/blockchain/chain.rs +++ b/src/blockchain/chain.rs @@ -36,7 +36,7 @@ const SQL_GET_BLOCK_BY_ID: &str = "SELECT * FROM blocks WHERE id=? LIMIT 1;"; const SQL_GET_LAST_FULL_BLOCK: &str = "SELECT * FROM blocks WHERE id < ? AND `transaction`<>'' ORDER BY id DESC LIMIT 1;"; const SQL_GET_LAST_FULL_BLOCK_FOR_KEY: &str = "SELECT * FROM blocks WHERE id < ? AND `transaction`<>'' AND pub_key = ? ORDER BY id DESC LIMIT 1;"; const SQL_GET_DOMAIN_OWNER_BY_ID: &str = "SELECT signing FROM domains WHERE id < ? AND identity = ? ORDER BY id DESC LIMIT 1;"; -const SQL_GET_DOMAIN_BY_ID: &str = "SELECT * FROM domains WHERE identity = ? ORDER BY id DESC LIMIT 1;"; +const SQL_GET_DOMAIN_BY_ID: &str = "SELECT * FROM domains WHERE identity = ? AND id < ? ORDER BY id DESC LIMIT 1;"; const SQL_GET_DOMAINS_BY_KEY: &str = "SELECT timestamp, identity, data, signing FROM domains WHERE signing = ? ORDER BY id;"; const SQL_GET_DOMAINS_COUNT: &str = "SELECT count(DISTINCT identity) FROM domains;"; const SQL_GET_USERS_COUNT: &str = "SELECT count(DISTINCT pub_key) FROM blocks;"; @@ -606,12 +606,13 @@ impl Chain { None } - pub fn get_domain_update_time(&self, identity_hash: &Bytes) -> Option { + pub fn get_domain_update_time(&self, identity_hash: &Bytes, height: u64, time: i64) -> Option { let mut statement = self.db.prepare(SQL_GET_DOMAIN_BY_ID).unwrap(); statement.bind(1, identity_hash.as_slice()).expect("Error in bind"); + statement.bind(2, height as i64 ).expect("Error in bind"); if let State::Row = statement.next().unwrap() { let timestamp = statement.read::(1).unwrap(); - if timestamp < Utc::now().timestamp() - DOMAIN_LIFETIME { + if timestamp < time - DOMAIN_LIFETIME { // This domain is too old return None; } @@ -620,7 +621,7 @@ impl Chain { None } - pub fn get_domain_transaction_by_id(&self, identity_hash: &Bytes) -> Option { + pub fn get_domain_transaction_by_id(&self, identity_hash: &Bytes, height: u64) -> Option { if self.get_domain_renewal_time(identity_hash).is_none() { // Domain has expired return None; @@ -628,6 +629,7 @@ impl Chain { let mut statement = self.db.prepare(SQL_GET_DOMAIN_BY_ID).unwrap(); statement.bind(1, identity_hash.as_slice()).expect("Error in bind"); + statement.bind(2, height as i64).expect("Error in bind"); if let State::Row = statement.next().unwrap() { let timestamp = statement.read::(1).unwrap(); if timestamp < Utc::now().timestamp() - DOMAIN_LIFETIME { @@ -652,7 +654,7 @@ impl Chain { return None; } let identity_hash = hash_identity(domain, None); - if let Some(transaction) = self.get_domain_transaction_by_id(&identity_hash) { + if let Some(transaction) = self.get_domain_transaction_by_id(&identity_hash, self.get_height()) { debug!("Found transaction for domain {}: {:?}", domain, &transaction); if transaction.check_identity(domain) { return Some(transaction); @@ -704,6 +706,7 @@ impl Chain { let pub_key = keystore.get_public(); let mut statement = self.db.prepare(SQL_GET_DOMAINS_BY_KEY).unwrap(); statement.bind(1, &**pub_key).expect("Error in bind"); + let height = self.get_height(); while let State::Row = statement.next().unwrap() { let timestamp = statement.read::(0).unwrap(); let identity = Bytes::from_bytes(&statement.read::>(1).unwrap()); @@ -711,7 +714,7 @@ impl Chain { let signing = Bytes::from_bytes(&statement.read::>(3).unwrap()); // Get the last transaction for this id and check if it is still ours - if let Some(transaction) = self.get_domain_transaction_by_id(&identity) { + if let Some(transaction) = self.get_domain_transaction_by_id(&identity, height) { if transaction.signing != signing { trace!("Identity {:?} is not ours anymore, skipping", &identity); continue; @@ -818,10 +821,10 @@ impl Chain { SIGNER_DIFFICULTY } } - Some(t) => self.get_difficulty_for_transaction(t) + Some(t) => self.get_difficulty_for_transaction(t, block.index, block.timestamp) }; if block.difficulty < difficulty { - warn!("Block difficulty is lower than needed"); + warn!("Block difficulty is lower than needed: {} < {}", block.difficulty, difficulty); return Bad; } if hash_difficulty(&block.hash) < block.difficulty { @@ -987,11 +990,11 @@ impl Chain { true } - fn get_difficulty_for_transaction(&self, transaction: &Transaction) -> u32 { + fn get_difficulty_for_transaction(&self, transaction: &Transaction, height: u64, time: i64) -> u32 { match transaction.class.as_ref() { CLASS_DOMAIN => { // If this domain is already in blockchain we approve slightly smaller difficulty - let discount = self.get_identity_discount(&transaction.identity, false); + let discount = self.get_identity_discount(&transaction.identity, false, height, time); // TODO move this check somewhere appropriate return match serde_json::from_str::(&transaction.data) { Ok(_) => DOMAIN_DIFFICULTY - discount, @@ -1006,8 +1009,8 @@ impl Chain { } } - pub fn get_identity_discount(&self, identity: &Bytes, renewal: bool) -> u32 { - match self.get_domain_update_time(identity) { + pub fn get_identity_discount(&self, identity: &Bytes, renewal: bool, height: u64, time: i64) -> u32 { + match self.get_domain_update_time(identity, height, time) { None => 0u32, Some(timestamp) => { if renewal || self.get_height() < BLOCKS_WITHOUT_DISCOUNT { @@ -1039,9 +1042,11 @@ impl Chain { } let mut set = HashSet::new(); - let tail = block.signature.get_tail_u64(); + let mut tail = block.signature.get_tail_u64(); let mut count = 1; + let mut mitigated = false; let window = block.index - 1; // Without the last block + trace!("Calculating signers, tail: {}, window: {}", tail, window); while set.len() < BLOCK_SIGNERS_ALL as usize { let index = (tail.wrapping_mul(count) % window) + 1; // We want it to start from 1 if let Some(b) = self.get_block(index) { @@ -1057,8 +1062,12 @@ impl Chain { } } count += 1; + if !mitigated && count > 25 { + tail = tail / 13; + mitigated = true; + } } - trace!("Got signers for block {}: {:?}", block.index, &result); + debug!("Got signers for block {}: {:?}, loop count {}", block.index, &result, count); let mut signers = self.signers.borrow_mut(); signers.index = block.index; signers.signers = result.clone(); diff --git a/src/commons/constants.rs b/src/commons/constants.rs index f4623e6..29851fb 100644 --- a/src/commons/constants.rs +++ b/src/commons/constants.rs @@ -35,6 +35,7 @@ pub const DB_NAME: &str = "blockchain.db"; pub const CLASS_ORIGIN: &str = "origin"; pub const CLASS_DOMAIN: &str = "domain"; pub const ALFIS_DEBUG: &str = "ALFIS_DEBUG"; +pub const ALFIS_TRACE: &str = "ALFIS_TRACE"; /// Public nodes listen port pub const LISTEN_PORT: u16 = 4244; @@ -48,4 +49,4 @@ pub const MIN_CONNECTED_NODES_START_SYNC: usize = 4; pub const MAX_READ_BLOCK_TIME: u128 = 100; pub const MAX_RECONNECTS: u32 = 5; pub const MAX_IDLE_SECONDS: u64 = 180; -pub const MAX_NODES: usize = 15; +pub const MAX_NODES: usize = 25; diff --git a/src/main.rs b/src/main.rs index 11d38b7..dafe6e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,9 +24,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use alfis::event::Event; use alfis::eventbus::{post, register}; use alfis::keystore::create_key; -use alfis::{ - dns_utils, Block, Bytes, Chain, Context, Keystore, Miner, Network, Settings, Transaction, ALFIS_DEBUG, DB_NAME, ORIGIN_DIFFICULTY -}; +use alfis::{dns_utils, Block, Bytes, Chain, Context, Keystore, Miner, Network, Settings, Transaction, ALFIS_DEBUG, ALFIS_TRACE, DB_NAME, ORIGIN_DIFFICULTY}; #[cfg(feature = "webgui")] mod web_ui; @@ -53,7 +51,8 @@ fn main() { opts.optflag("h", "help", "Print this help menu"); opts.optflag("n", "nogui", "Run without graphic user interface (default for no gui builds)"); opts.optflag("v", "version", "Print version and exit"); - opts.optflag("d", "debug", "Show trace messages, more than debug"); + opts.optflag("d", "debug", "Show debug messages, more than usual"); + opts.optflag("t", "trace", "Show trace messages, more than debug"); opts.optflag("b", "blocks", "List blocks from DB and exit"); opts.optflag("g", "generate", "Generate new config file. Generated config will be printed to console."); opts.optopt("k", "gen-key", "Generate new keys and save them to file.", "FILE"); @@ -248,6 +247,9 @@ fn main() { fn setup_logger(opt_matches: &Matches, console_attached: bool) { let mut level = LevelFilter::Info; if opt_matches.opt_present("d") || env::var(ALFIS_DEBUG).is_ok() { + level = LevelFilter::Debug; + } + if opt_matches.opt_present("t") || env::var(ALFIS_TRACE).is_ok() { level = LevelFilter::Trace; } let config = ConfigBuilder::new() diff --git a/src/miner.rs b/src/miner.rs index 0dc78ae..43509ab 100644 --- a/src/miner.rs +++ b/src/miner.rs @@ -132,7 +132,7 @@ impl Miner { info!("Replacing current mining job with signing job!"); // We cancel current job, waiting for threads to finish mining.store(false, Ordering::SeqCst); - thread::sleep(Duration::from_millis(100)); + sleep(Duration::from_millis(100)); // Return current job to queue jobs.insert(0, current_job.take().unwrap()); diff --git a/src/web_ui.rs b/src/web_ui.rs index 2787636..056346b 100644 --- a/src/web_ui.rs +++ b/src/web_ui.rs @@ -17,7 +17,7 @@ use alfis::event::Event; use alfis::eventbus::{post, register}; use alfis::miner::Miner; use alfis::{keystore, Block, Bytes, Context, Keystore, Transaction}; -use chrono::{DateTime, Local}; +use chrono::{DateTime, Local, Utc}; #[allow(unused_imports)] use log::{debug, error, info, trace, warn, LevelFilter}; use serde::{Deserialize, Serialize}; @@ -574,7 +574,8 @@ fn create_domain(context: Arc>, miner: Arc>, class: }; let transaction = Transaction::from_str(name, class.to_owned(), data, signing, encryption); // If this domain is already in blockchain we approve slightly smaller difficulty - let discount = context.lock().unwrap().chain.get_identity_discount(&transaction.identity, renewal); + let height = context.lock().unwrap().chain.get_height(); + let discount = context.lock().unwrap().chain.get_identity_discount(&transaction.identity, renewal, height, Utc::now().timestamp()); let block = Block::new(Some(transaction), keystore.get_public(), Bytes::default(), difficulty - discount); miner.lock().unwrap().add_block(block, keystore.clone()); }