diff --git a/Cargo.lock b/Cargo.lock index d36ea327c769176277a2048a22c802886ab28153..072734445face7a5adf2cca89ffb99c580498f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,7 +132,6 @@ dependencies = [ "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -228,7 +227,6 @@ dependencies = [ name = "duniter-core" version = "0.1.0-a0.1" dependencies = [ - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "duniter-blockchain 0.1.0-a0.1", "duniter-conf 0.1.0-a0.1", @@ -236,17 +234,13 @@ dependencies = [ "duniter-message 0.1.0-a0.1", "duniter-module 0.1.0-a0.1", "duniter-network 0.1.0-a0.1", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "simplelog 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sqlite 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -322,6 +316,7 @@ dependencies = [ "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -358,6 +353,7 @@ dependencies = [ "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -380,6 +376,7 @@ dependencies = [ "duniter-tui 0.1.0-a0.1", "durs-ws2p 0.1.0-a0.1", "durs-ws2p-v1-legacy 0.1.0-a0.1", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -395,6 +392,7 @@ dependencies = [ "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -437,6 +435,7 @@ dependencies = [ "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "sqlite 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -958,6 +957,25 @@ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "structopt" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.11.11" @@ -1177,11 +1195,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" @@ -1272,6 +1285,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sqlite3-src 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "46e0bc115b563b1ee6c665ef895b56bf488522f57d1c6571887547c57c8f5a88" "checksum sqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8e9ad6a11096cbecdcca0cc6aa403fdfdbaeda2fb3323a39c98e6a166a1e45a" +"checksum structopt-derive 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4cbce8ccdc62166bd594c14396a3242bf94c337a51dbfa9be1076dd74b3db2af" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" @@ -1301,4 +1316,3 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ccf752fee5350ca505fdb0b34d503b17d1528bd867561b7aa91d6ea750d5e972" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/Cargo.toml b/Cargo.toml index 8e8d7b437b3f4ff8074a889a640bc17f4c31e09f..60a612ea17bcba1f4ea104e8e468a896ec7ab306 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,14 +7,16 @@ license = "AGPL-3.0" [dependencies] duniter-core = { path = "./core" } -duniter-tui = { path = "./tui", optional = true } durs-ws2p = { path = "./ws2p" } durs-ws2p-v1-legacy = { path = "./ws2p-v1-legacy" } +structopt= "0.2.*" + +[target.'cfg(unix)'.dependencies] +duniter-tui = { path = "./tui" } [features] -default = ["tui","ssl"] +default = ["ssl"] ssl = ["durs-ws2p-v1-legacy/ssl"] -tui = ["duniter-tui"] # Treat warnings as a build error. strict = [] diff --git a/blockchain/apply_valid_block.rs b/blockchain/apply_valid_block.rs index 32f477adb347eda1c8704086ae9624cc0c2ad6a5..f731e93a41da8ffc6e86621cc5333ea33e1b0066 100644 --- a/blockchain/apply_valid_block.rs +++ b/blockchain/apply_valid_block.rs @@ -71,7 +71,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wot_db .write(|db| { db.add_node(); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_index.insert(pubkey, wotb_id); wot_dbs_requests.push(WotsDBsWriteQuery::CreateIdentity( wotb_id, @@ -86,7 +87,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(wotb_id, true); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( joiner.issuers()[0], wotb_id, @@ -102,7 +104,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(wotb_id, true); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( pubkey, wotb_id, @@ -120,7 +123,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(*wot_id, false); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::ExcludeIdentity( exclusion, block.blockstamp(), @@ -136,7 +140,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(*wot_id, false); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevokeIdentity( compact_revoc.issuer, block.blockstamp(), @@ -158,7 +163,8 @@ pub fn apply_valid_block<W: WebOfTrust>( wotb_node_from.0, wotb_node_to.0, result ), } - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::CreateCert( compact_cert.issuer, wotb_node_from, @@ -182,7 +188,8 @@ pub fn apply_valid_block<W: WebOfTrust>( RemLinkResult::Removed(_) => {} _ => panic!("Fail to rem_link {}->{} : {:?}", source.0, target.0, result), } - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); } } if let Some(du_amount) = block.dividend { @@ -208,53 +215,53 @@ pub fn apply_valid_block<W: WebOfTrust>( } /*// Calculate the state of the wot - if !wot_events.is_empty() && verif_level != SyncVerificationLevel::FastSync() { - // Calculate sentries_count - let sentries_count = wot.get_sentries(3).len(); - // Calculate average_density - let average_density = calculate_average_density::<W>(&wot); - let sentry_requirement = - get_sentry_requirement(block.members_count, G1_PARAMS.step_max); - // Calculate distances and connectivities - let (average_distance, distances, average_connectivity, connectivities) = - compute_distances::<W>( - &wot, - sentry_requirement, - G1_PARAMS.step_max, - G1_PARAMS.x_percent, - ); - // Calculate centralities and average_centrality - let centralities = - calculate_distance_stress_centralities::<W>(&wot, G1_PARAMS.step_max); - let average_centrality = - (centralities.iter().sum::<u64>() as f64 / centralities.len() as f64) as usize; - // Register the state of the wot - let max_connectivity = currency_params.max_connectivity(); - duniter_dal::register_wot_state( - db, - &WotState { - block_number: block.number.0, - block_hash: block.hash.expect("Fail to get block hash").to_string(), - sentries_count, - average_density, - average_distance, - distances, - average_connectivity, - connectivities: connectivities - .iter() - .map(|c| { - if *c > max_connectivity { - max_connectivity - } else { - *c - } - }) - .collect(), - average_centrality, - centralities, - }, + if !wot_events.is_empty() && verif_level != SyncVerificationLevel::FastSync() { + // Calculate sentries_count + let sentries_count = wot.get_sentries(3).len(); + // Calculate average_density + let average_density = calculate_average_density::<W>(&wot); + let sentry_requirement = + get_sentry_requirement(block.members_count, G1_PARAMS.step_max); + // Calculate distances and connectivities + let (average_distance, distances, average_connectivity, connectivities) = + compute_distances::<W>( + &wot, + sentry_requirement, + G1_PARAMS.step_max, + G1_PARAMS.x_percent, ); - }*/ + // Calculate centralities and average_centrality + let centralities = + calculate_distance_stress_centralities::<W>(&wot, G1_PARAMS.step_max); + let average_centrality = + (centralities.iter().sum::<u64>() as f64 / centralities.len() as f64) as usize; + // Register the state of the wot + let max_connectivity = currency_params.max_connectivity(); + duniter_dal::register_wot_state( + db, + &WotState { + block_number: block.number.0, + block_hash: block.hash.expect("Fail to get block hash").to_string(), + sentries_count, + average_density, + average_distance, + distances, + average_connectivity, + connectivities: connectivities + .iter() + .map(|c| { + if *c > max_connectivity { + max_connectivity + } else { + *c + } + }) + .collect(), + average_centrality, + centralities, + }, + ); + }*/ // Create DALBlock let mut block = block.clone(); let previous_blockcstamp = block.previous_blockstamp(); diff --git a/blockchain/check_and_apply_block.rs b/blockchain/check_and_apply_block.rs index 62366dd6548a25fbd6b6d7e8b4e44cafb7662834..9851bf29fcd754eb51ad09e17e4948eb86e45eff 100644 --- a/blockchain/check_and_apply_block.rs +++ b/blockchain/check_and_apply_block.rs @@ -155,7 +155,8 @@ pub fn check_and_apply_block<W: WebOfTrust>( None, false, false, - ).expect("duniter_dal::writers::block::write() : DALError") + ) + .expect("duniter_dal::writers::block::write() : DALError") } Block::LocalBlock(block_doc) => { let old_fork_id = None; @@ -173,7 +174,8 @@ pub fn check_and_apply_block<W: WebOfTrust>( old_fork_id, false, false, - ).expect("duniter_dal::writers::block::write() : DALError") + ) + .expect("duniter_dal::writers::block::write() : DALError") } }; } else { diff --git a/blockchain/dbex.rs b/blockchain/dbex.rs index 9c09b6aa80fe02dd308d7f103f8dcc5e920e0af8..5ee9908efa21706be19c766f7133d724c608710e 100644 --- a/blockchain/dbex.rs +++ b/blockchain/dbex.rs @@ -73,7 +73,7 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB println!( "Databases loaded in {}.{:03} seconds.", load_dbs_duration.as_secs(), - load_dbs_duration.subsec_nanos() / 1_000_000 + load_dbs_duration.subsec_millis() ); let req_process_begin = SystemTime::now(); match *query { @@ -83,7 +83,8 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB } else if let Some(pubkey) = duniter_dal::identity::get_pubkey_from_uid( &wot_databases.identities_db, address_str, - ).expect("get_uid : DALError") + ) + .expect("get_uid : DALError") { pubkey } else { @@ -94,7 +95,8 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB let address_balance = duniter_dal::balance::get_address_balance( ¤cy_databases.balances_db, &address, - ).expect("get_address_balance : DALError") + ) + .expect("get_address_balance : DALError") .expect("Address not found in balances DB."); println!( "Balance={},{} Ğ1", @@ -110,7 +112,7 @@ pub fn dbex_tx<DC: DuniterConf>(profile: &str, conf: &DC, _csv: bool, query: &DB println!( "Request processed in {}.{:06} seconds.", req_process_duration.as_secs(), - req_process_duration.subsec_nanos() / 1_000 + req_process_duration.subsec_micros() ); } @@ -129,7 +131,7 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB println!( "Databases loaded in {}.{:03} seconds.", load_dbs_duration.as_secs(), - load_dbs_duration.subsec_nanos() / 1_000_000 + load_dbs_duration.subsec_millis() ); // Get currency parameters @@ -151,7 +153,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB db.iter() .map(|(_, idty)| (idty.wot_id, String::from(idty.idty_doc.username()))) .collect() - }).expect("Fail to read IdentitiesDB !"); + }) + .expect("Fail to read IdentitiesDB !"); // Open wot db let wot_db = open_wot_db::<RustyWebOfTrust>(Some(&db_path)).expect("Fail to open WotDB !"); @@ -185,10 +188,13 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB step_max: currency_params.step_max as u32, x_percent: currency_params.x_percent, }, - ).expect("Fail to get distance !"), + ) + .expect("Fail to get distance !"), ) - }).collect() - }).expect("Fail to read WotDB"); + }) + .collect() + }) + .expect("Fail to read WotDB"); let compute_distances_duration = SystemTime::now() .duration_since(compute_distances_begin) .expect("duration_since error"); @@ -215,7 +221,7 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB println!( "compute_distances_duration = {},{:03}.", compute_distances_duration.as_secs(), - compute_distances_duration.subsec_nanos() / 1_000_000 + compute_distances_duration.subsec_millis() ); } DBExWotQuery::ExpireMembers(ref reverse) => { @@ -231,7 +237,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB .map(|(block_id, dal_block)| (*block_id, dal_block.block.median_time)) .collect(), ) - }).expect("Fail to read blockchain db"); + }) + .expect("Fail to read blockchain db"); // Get expire_dates let min_created_ms_time = current_bc_time - currency_params.ms_validity; let mut expire_dates: Vec<(NodeId, u64)> = wot_databases @@ -250,7 +257,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB } } expire_dates - }).expect("Fail to read ms db"); + }) + .expect("Fail to read ms db"); if *reverse { expire_dates.sort_unstable_by(|(_, d1), (_, d2)| d1.cmp(&d2)); } else { @@ -284,7 +292,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB x_percent: currency_params.x_percent, }, ) - }).expect("Fail to read WotDB") + }) + .expect("Fail to read WotDB") .expect("Fail to get distance !"); let distance_percent: f64 = f64::from(distance_datas.success) / f64::from(distance_datas.sentries) * 100.0; @@ -301,7 +310,8 @@ pub fn dbex_wot<DC: DuniterConf>(profile: &str, conf: &DC, csv: bool, query: &DB let source_uid = duniter_dal::identity::get_uid( &wot_databases.identities_db, *(wot_reverse_index[&source]), - ).expect("get_uid() : DALError") + ) + .expect("get_uid() : DALError") .expect("Not found source_uid !"); println!("{}: {}", i + 1, source_uid); } diff --git a/blockchain/lib.rs b/blockchain/lib.rs index 8bf1fc90f9d549f8b1cc3c6242d019277fab2c0c..82d44187b27d3de253e29bb74e21e4736c33b9a8 100644 --- a/blockchain/lib.rs +++ b/blockchain/lib.rs @@ -16,7 +16,7 @@ //! Module managing the Duniter blockchain. #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(duration_subsec))] +//#![cfg_attr(feature = "cargo-clippy", allow(duration_subsec))] #![deny( missing_docs, missing_debug_implementations, @@ -73,10 +73,10 @@ use duniter_dal::*; use duniter_documents::blockchain::v10::documents::{BlockDocument, V10Document}; use duniter_documents::blockchain::{BlockchainProtocol, Document}; use duniter_documents::*; -use duniter_message::DuniterMessage; +use duniter_message::*; use duniter_module::*; use duniter_network::{ - NetworkBlock, NetworkDocument, NetworkEvent, NetworkRequest, NetworkResponse, NodeFullId, + NetworkBlock, NetworkDocument, NetworkEvent, NetworkResponse, NodeFullId, OldNetworkRequest, }; use duniter_wotb::data::rusty::RustyWebOfTrust; use duniter_wotb::operations::distance::RustyDistanceCalculator; @@ -94,8 +94,8 @@ pub static DISTANCE_CALCULATOR: &'static RustyDistanceCalculator = &RustyDistanc /// Blockchain Module #[derive(Debug)] pub struct BlockchainModule { - /// Subscribers - pub followers: Vec<mpsc::Sender<DuniterMessage>>, + /// Rooter sender + pub rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, /// Name of the user datas profile pub profile: String, /// Currency @@ -146,11 +146,12 @@ pub enum CompletedBlockError { impl BlockchainModule { /// Return module identifier - pub fn id() -> ModuleId { - ModuleId(String::from("blockchain")) + pub fn name() -> ModuleStaticName { + ModuleStaticName("blockchain") } /// Loading blockchain configuration pub fn load_blockchain_conf<DC: DuniterConf>( + rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, profile: &str, conf: &DC, _keys: RequiredKeysContent, @@ -183,7 +184,7 @@ impl BlockchainModule { // Instanciate BlockchainModule BlockchainModule { - followers: Vec::new(), + rooter_sender, profile: profile.to_string(), currency: conf.currency(), currency_params, @@ -220,22 +221,22 @@ impl BlockchainModule { sync::sync_ts(profile, conf, db_ts_path, cautious, verif_inner_hash); } /// Request chunk from network (chunk = group of blocks) - fn request_chunk(&self, req_id: ModuleReqId, from: u32) -> (ModuleReqId, NetworkRequest) { - let req = NetworkRequest::GetBlocks( - ModuleReqFullId(BlockchainModule::id(), req_id), + fn request_chunk(&self, req_id: ModuleReqId, from: u32) -> (ModuleReqId, OldNetworkRequest) { + let req = OldNetworkRequest::GetBlocks( + ModuleReqFullId(BlockchainModule::name(), req_id), NodeFullId::default(), *CHUNK_SIZE, from, ); - (self.request_network(&req), req) + (self.request_network(req_id, &req), req) } /// Requests blocks from current to `to` fn request_blocks_to( &self, - pending_network_requests: &HashMap<ModuleReqId, NetworkRequest>, + pending_network_requests: &HashMap<ModuleReqId, OldNetworkRequest>, current_blockstamp: &Blockstamp, to: BlockId, - ) -> HashMap<ModuleReqId, NetworkRequest> { + ) -> HashMap<ModuleReqId, OldNetworkRequest> { let mut from = if *current_blockstamp == Blockstamp::default() { 0 } else { @@ -268,37 +269,36 @@ impl BlockchainModule { requests_ids } /// Send network request - fn request_network(&self, request: &NetworkRequest) -> ModuleReqId { - for follower in &self.followers { - if follower - .send(DuniterMessage::NetworkRequest(request.clone())) - .is_err() - { - debug!("BlockchainModule : one follower is unreachable !"); - } - } + fn request_network(&self, _req_id: ModuleReqId, request: &OldNetworkRequest) -> ModuleReqId { + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::Role(ModuleRole::InterNodesNetwork), + DursMsgContent::OldNetworkRequest(*request), + ))) + .unwrap_or_else(|_| panic!("Fail to send OldNetworkRequest to rooter")); request.get_req_id() } /// Send blockchain event fn send_event(&self, event: &DALEvent) { - for follower in &self.followers { - if follower - .send(DuniterMessage::DALEvent(event.clone())) - .is_err() - { - // Handle error - } - } + let module_event = match event { + DALEvent::StackUpValidBlock(_, _) => ModuleEvent::NewValidBlock, + DALEvent::RevertBlocks(_) => ModuleEvent::RevertBlocks, + _ => return, + }; + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::Event(module_event), + DursMsgContent::DALEvent(event.clone()), + ))) + .unwrap_or_else(|_| panic!("Fail to send DalEvent to rooter")); } - fn send_req_response(&self, response: &DALResponse) { - for follower in &self.followers { - if follower - .send(DuniterMessage::DALResponse(Box::new(response.clone()))) - .is_err() - { - // Handle error - } - } + fn send_req_response(&self, requester: DursMsgReceiver, response: &DALResponse) { + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + requester, + DursMsgContent::DALResponse(Box::new(response.clone())), + ))) + .unwrap_or_else(|_| panic!("Fail to send ReqRes to rooter")); } fn receive_network_documents<W: WebOfTrust>( &mut self, @@ -359,7 +359,8 @@ impl BlockchainModule { self.forks_states = duniter_dal::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, - ).expect("get_forks() : DALError"); + ) + .expect("get_forks() : DALError"); save_blocks_dbs = true; if !wot_dbs_reqs.is_empty() { save_wots_dbs = true; @@ -463,7 +464,8 @@ impl BlockchainModule { self.forks_states = duniter_dal::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, - ).expect("get_forks() : DALError"); + ) + .expect("get_forks() : DALError"); // Apply db requests bc_db_query .apply(&self.blocks_databases, false) @@ -500,7 +502,7 @@ impl BlockchainModule { current_blockstamp } /// Start blockchain module. - pub fn start_blockchain(&mut self, blockchain_receiver: &mpsc::Receiver<DuniterMessage>) -> () { + pub fn start_blockchain(&mut self, blockchain_receiver: &mpsc::Receiver<DursMsg>) -> () { info!("BlockchainModule::start_blockchain()"); // Get dbs path @@ -523,16 +525,17 @@ impl BlockchainModule { // Init datas let mut last_get_stackables_blocks = UNIX_EPOCH; let mut last_request_blocks = UNIX_EPOCH; - let mut pending_network_requests: HashMap<ModuleReqId, NetworkRequest> = HashMap::new(); + let mut pending_network_requests: HashMap<ModuleReqId, OldNetworkRequest> = HashMap::new(); let mut consensus = Blockstamp::default(); loop { // Request Consensus - let req = NetworkRequest::GetConsensus(ModuleReqFullId( - BlockchainModule::id(), + let req = OldNetworkRequest::GetConsensus(ModuleReqFullId( + BlockchainModule::name(), ModuleReqId(pending_network_requests.len() as u32), )); - let req_id = self.request_network(&req); + let req_id = + self.request_network(ModuleReqId(pending_network_requests.len() as u32), &req); pending_network_requests.insert(req_id, req); // Request Blocks let now = SystemTime::now(); @@ -567,77 +570,80 @@ impl BlockchainModule { } } match blockchain_receiver.recv_timeout(Duration::from_millis(1000)) { - Ok(ref message) => match *message { - DuniterMessage::Followers(ref new_followers) => { - info!("Blockchain module receive followers !"); - for new_follower in new_followers { - self.followers.push(new_follower.clone()); - } - } - DuniterMessage::DALRequest(ref dal_request) => match *dal_request { - DALRequest::BlockchainRequest(ref blockchain_req) => { - match *blockchain_req { - DALReqBlockchain::CurrentBlock(ref requester_full_id) => { - debug!("BlockchainModule : receive DALReqBc::CurrentBlock()"); + Ok(ref message) => { + match (*message).1 { + DursMsgContent::Request(ref request) => { + if let DursReqContent::DALRequest(ref dal_request) = request.content { + match dal_request { + DALRequest::BlockchainRequest(ref blockchain_req) => { + match *blockchain_req { + DALReqBlockchain::CurrentBlock() => { + debug!("BlockchainModule : receive DALReqBc::CurrentBlock()"); - if let Some(current_block) = - DALBlock::get_block( - &self.blocks_databases.blockchain_db, - None, - ¤t_blockstamp, - ).expect( - "Fatal error : get_block : fail to read LocalBlockchainV10DB !", - ) { - debug!("BlockchainModule : send_req_response(CurrentBlock({}))", current_blockstamp); - self.send_req_response(&DALResponse::Blockchain(Box::new( - DALResBlockchain::CurrentBlock( - requester_full_id.clone(), - Box::new(current_block.block), - current_blockstamp, + if let Some(current_block) = + DALBlock::get_block( + &self.blocks_databases.blockchain_db, + None, + ¤t_blockstamp, + ).expect( + "Fatal error : get_block : fail to read LocalBlockchainV10DB !", + ) { + debug!("BlockchainModule : send_req_response(CurrentBlock({}))", current_blockstamp); + self.send_req_response(DursMsgReceiver::One(request.requester), &DALResponse::Blockchain(Box::new( + DALResBlockchain::CurrentBlock( + request.id, + Box::new(current_block.block), + current_blockstamp, + ), + ))); + } else { + warn!("BlockchainModule : Req : fail to get current_block in bdd !"); + } + } + DALReqBlockchain::UIDs(ref pubkeys) => { + self.send_req_response(DursMsgReceiver::One(request.requester), &DALResponse::Blockchain(Box::new( + DALResBlockchain::UIDs( + request.id, + pubkeys + .iter() + .map(|p| { + ( + *p, + duniter_dal::identity::get_uid(&self.wot_databases.identities_db, *p) + .expect("Fatal error : get_uid : Fail to read WotV10DB !") + ) + }) + .collect(), ), ))); - } else { - warn!("BlockchainModule : Req : fail to get current_block in bdd !"); + } + _ => {} + } } + DALRequest::PendingsRequest(ref _pending_req) => {} } - DALReqBlockchain::UIDs(ref pubkeys) => { - self.send_req_response(&DALResponse::Blockchain(Box::new( - DALResBlockchain::UIDs( - pubkeys - .iter() - .map(|p| { - ( - *p, - duniter_dal::identity::get_uid(&self.wot_databases.identities_db, *p) - .expect("Fatal error : get_uid : Fail to read WotV10DB !") - ) - }) - .collect(), - ), - ))); - } - _ => {} } } - DALRequest::PendingsRequest(ref _pending_req) => {} - }, - DuniterMessage::NetworkEvent(ref network_event) => match *network_event { - NetworkEvent::ReceiveDocuments(ref network_docs) => { - let new_current_blockstamp = self.receive_network_documents( - network_docs, - ¤t_blockstamp, - &mut wotb_index, - &wot_db, - ); - current_blockstamp = new_current_blockstamp; - } - NetworkEvent::ReqResponse(ref network_response) => { + DursMsgContent::NetworkEvent(ref network_event) => match *network_event { + NetworkEvent::ReceiveDocuments(ref network_docs) => { + let new_current_blockstamp = self.receive_network_documents( + network_docs, + ¤t_blockstamp, + &mut wotb_index, + &wot_db, + ); + current_blockstamp = new_current_blockstamp; + } + NetworkEvent::ReceiveHeads(_) => {} + _ => {} + }, + DursMsgContent::NetworkResponse(ref network_response) => { debug!("BlockchainModule : receive NetworkEvent::ReqResponse() !"); if let Some(request) = pending_network_requests.remove(&network_response.get_req_id()) { match request { - NetworkRequest::GetConsensus(_) => { + OldNetworkRequest::GetConsensus(_) => { if let NetworkResponse::Consensus(_, response) = *network_response.deref() { @@ -650,11 +656,13 @@ impl BlockchainModule { let last_dal_block_id = BlockId(current_blockstamp.id.0 - 1); let last_dal_block = self - .blocks_databases - .blockchain_db - .read(|db| db.get(&last_dal_block_id).cloned()) - .expect("Fail to read blockchain DB.") - .expect("Fatal error : not foutn last dal block !"); + .blocks_databases + .blockchain_db + .read(|db| db.get(&last_dal_block_id).cloned()) + .expect("Fail to read blockchain DB.") + .expect( + "Fatal error : not foutn last dal block !", + ); revert_block::revert_block( &last_dal_block, &mut wotb_index, @@ -665,12 +673,13 @@ impl BlockchainModule { .tx_db .read(|db| db.clone()) .expect("Fail to read TxDB."), - ).expect("Fail to revert block"); + ) + .expect("Fail to revert block"); } } } } - NetworkRequest::GetBlocks(_, _, _, _) => { + OldNetworkRequest::GetBlocks(_, _, _, _) => { if let NetworkResponse::Chunk(_, _, ref blocks) = *network_response.deref() { @@ -686,7 +695,8 @@ impl BlockchainModule { self.forks_states = duniter_dal::block::get_forks( &self.blocks_databases.forks_db, current_blockstamp, - ).expect("get_forks() : DALError"); + ) + .expect("get_forks() : DALError"); } } } @@ -694,14 +704,13 @@ impl BlockchainModule { } } } + DursMsgContent::ReceiveDocsFromClient(ref docs) => { + self.receive_documents(docs); + } + DursMsgContent::Stop() => break, _ => {} - }, - DuniterMessage::ReceiveDocsFromClient(ref docs) => { - self.receive_documents(docs); } - DuniterMessage::Stop() => break, - _ => {} - }, + } Err(e) => match e { mpsc::RecvTimeoutError::Disconnected => { panic!("Disconnected blockchain module !"); @@ -722,7 +731,8 @@ impl BlockchainModule { &self.blocks_databases.forks_db, &self.blocks_databases.forks_blocks_db, ¤t_blockstamp, - ).expect("Fatal error : Fail to read ForksV10DB !"); + ) + .expect("Fatal error : Fail to read ForksV10DB !"); if stackable_blocks.is_empty() { break; } else { @@ -781,7 +791,8 @@ impl BlockchainModule { &self.blocks_databases.forks_db, &self.blocks_databases.forks_blocks_db, stackable_block.fork_id, - ).expect("delete_fork() : DALError"); + ) + .expect("delete_fork() : DALError"); // Update forks states self.forks_states[stackable_block.fork_id.0] = ForkStatus::Free(); } diff --git a/blockchain/revert_block.rs b/blockchain/revert_block.rs index eabcb9f5334fa6b22f858706fe7b6f8eba780888..4ac1e0f48bebd0cfdfc1ade1033dd60e41e271cc 100644 --- a/blockchain/revert_block.rs +++ b/blockchain/revert_block.rs @@ -62,7 +62,8 @@ pub fn revert_block<W: WebOfTrust>( .map(|tx_enum| match *tx_enum { TxDocOrTxHash::TxHash(ref tx_hash) => txs[tx_hash].clone(), TxDocOrTxHash::TxDoc(ref _dal_tx) => panic!("Try to revert not reduce block !"), - }).collect(); + }) + .collect(); // Revert reduce block block.compute_inner_hash(); @@ -108,7 +109,8 @@ pub fn revert_block<W: WebOfTrust>( NewLinkResult::Ok(_) => {} _ => panic!("Fail to add_link {}->{} : {:?}", source.0, target.0, result), } - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertExpireCert( source, target, @@ -132,7 +134,8 @@ pub fn revert_block<W: WebOfTrust>( wotb_node_from.0, wotb_node_to.0, result ), } - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertCert( compact_cert, wotb_node_from, @@ -151,7 +154,8 @@ pub fn revert_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(*wot_id, false); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertRevokeIdentity( compact_revoc.issuer, block.blockstamp(), @@ -168,7 +172,8 @@ pub fn revert_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(*wot_id, false); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertExcludeIdentity( exclusion, block.blockstamp(), @@ -187,7 +192,8 @@ pub fn revert_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(wotb_id, true); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertRenewalIdentity( pubkey, wotb_id, @@ -204,7 +210,8 @@ pub fn revert_block<W: WebOfTrust>( wot_db .write(|db| { db.rem_node(); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_index.remove(&pubkey); wot_dbs_requests.push(WotsDBsWriteQuery::RevertCreateIdentity(pubkey)); } else { @@ -213,7 +220,8 @@ pub fn revert_block<W: WebOfTrust>( wot_db .write(|db| { db.set_enabled(wotb_id, true); - }).expect("Fail to write in WotDB"); + }) + .expect("Fail to write in WotDB"); wot_dbs_requests.push(WotsDBsWriteQuery::RevertRenewalIdentity( joiner.issuers()[0], wotb_id, diff --git a/blockchain/sync.rs b/blockchain/sync.rs index 5fa7e31299119eb3e793738fc97f7a1a436ed07d..1bcd942b4a3c49c6809676b3f6c5474c38cc4471 100644 --- a/blockchain/sync.rs +++ b/blockchain/sync.rs @@ -234,7 +234,7 @@ pub fn sync_ts<DC: DuniterConf>( info!( "ts_job_duration={},{:03} seconds.", ts_job_duration.as_secs(), - ts_job_duration.subsec_nanos() / 1_000_000 + ts_job_duration.subsec_millis() ); }); @@ -263,6 +263,9 @@ pub fn sync_ts<DC: DuniterConf>( // Open blocks databases let databases = BlocksV10DBs::open(Some(&db_path)); + // Open wot databases + let wot_databases = WotsV10DBs::open(Some(&db_path)); + // Get local current blockstamp debug!("Get local current blockstamp..."); let mut current_blockstamp: Blockstamp = duniter_dal::block::get_current_blockstamp(&databases) @@ -270,10 +273,6 @@ pub fn sync_ts<DC: DuniterConf>( .unwrap_or_default(); debug!("Success to get local current blockstamp."); - // Instanciate blockchain module - let blockchain_module = - BlockchainModule::load_blockchain_conf(profile, &conf, RequiredKeysContent::None()); - // Node is already synchronized ? if target_blockstamp.id.0 < current_blockstamp.id.0 { println!("Your duniter-rs node is already synchronized."); @@ -282,7 +281,7 @@ pub fn sync_ts<DC: DuniterConf>( // Get wotb index let mut wotb_index: HashMap<PubKey, NodeId> = - DALIdentity::get_wotb_index(&blockchain_module.wot_databases.identities_db) + DALIdentity::get_wotb_index(&wot_databases.identities_db) .expect("Fatal eror : get_wotb_index : Fail to read blockchain databases"); // Start sync @@ -345,32 +344,33 @@ pub fn sync_ts<DC: DuniterConf>( // Indexing blockchain meta datas info!("Indexing blockchain meta datas..."); /*let blockchain_meta_datas: HashMap<PreviousBlockstamp, BlockHash> = databases - .blockchain_db - .read(|db| { - let mut blockchain_meta_datas: HashMap< - PreviousBlockstamp, - BlockHash, - > = HashMap::new(); - for dal_block in db.values() { - let block_previous_hash = if dal_block.block.number.0 == 0 { - PreviousBlockstamp::default() - } else { - PreviousBlockstamp { - id: BlockId(dal_block.block.number.0 - 1), - hash: BlockHash(dal_block.block.previous_hash), - } - }; - blockchain_meta_datas - .insert(block_previous_hash, dal_block.block.expect("Try to get hash of an uncompleted or reduce block !")); - } + .blockchain_db + .read(|db| { + let mut blockchain_meta_datas: HashMap< + PreviousBlockstamp, + BlockHash, + > = HashMap::new(); + for dal_block in db.values() { + let block_previous_hash = if dal_block.block.number.0 == 0 { + PreviousBlockstamp::default() + } else { + PreviousBlockstamp { + id: BlockId(dal_block.block.number.0 - 1), + hash: BlockHash(dal_block.block.previous_hash), + } + }; blockchain_meta_datas - }) - .expect("Indexing blockchain meta datas : DALError");*/ + .insert(block_previous_hash, dal_block.block.expect("Try to get hash of an uncompleted or reduce block !")); + } + blockchain_meta_datas + }) + .expect("Indexing blockchain meta datas : DALError");*/ databases .forks_db .write(|db| { db.insert(ForkId(0), blockchain_meta_datas); - }).expect("Indexing blockchain meta datas : DALError"); + }) + .expect("Indexing blockchain meta datas : DALError"); // Increment progress bar (last chunk) apply_pb.inc(); @@ -387,7 +387,7 @@ pub fn sync_ts<DC: DuniterConf>( info!( "blocks_job_duration={},{:03} seconds.", blocks_job_duration.as_secs(), - blocks_job_duration.subsec_nanos() / 1_000_000 + blocks_job_duration.subsec_millis() ); }); @@ -429,7 +429,7 @@ pub fn sync_ts<DC: DuniterConf>( info!( "wot_job_duration={},{:03} seconds.", wot_job_duration.as_secs(), - wot_job_duration.subsec_nanos() / 1_000_000 + wot_job_duration.subsec_millis() ); }); @@ -466,7 +466,7 @@ pub fn sync_ts<DC: DuniterConf>( info!( "tx_job_duration={},{:03} seconds.", tx_job_duration.as_secs(), - tx_job_duration.subsec_nanos() / 1_000_000 + tx_job_duration.subsec_millis() ); }); let main_job_begin = SystemTime::now(); @@ -505,7 +505,8 @@ pub fn sync_ts<DC: DuniterConf>( .write(|db| { db.0 = block_doc.currency.clone(); db.1 = block_doc.parameters.unwrap(); - }).expect("fail to write in params DB"); + }) + .expect("fail to write in params DB"); currency_params = CurrencyParameters::from(( block_doc.currency.clone(), block_doc.parameters.unwrap(), @@ -568,13 +569,15 @@ pub fn sync_ts<DC: DuniterConf>( db.get(&created_block_id).cloned().unwrap_or_default(); created_certs.insert((*source, *target)); db.insert(*created_block_id, created_certs); - }).expect("RustBreakError : please reset data and resync !"); + }) + .expect("RustBreakError : please reset data and resync !"); } sender_wot_thread .send(SyncJobsMess::WotsDBsWriteQuery( req.clone(), Box::new(currency_params), - )).expect( + )) + .expect( "Fail to communicate with tx worker thread, please reset data & resync !", ) } @@ -628,17 +631,17 @@ pub fn sync_ts<DC: DuniterConf>( info!( "main_job_duration={},{:03} seconds.", main_job_duration.as_secs(), - main_job_duration.subsec_nanos() / 1_000_000 + main_job_duration.subsec_millis() ); info!( "all_complete_block_duration={},{:03} seconds.", all_complete_block_duration.as_secs(), - all_complete_block_duration.subsec_nanos() / 1_000_000 + all_complete_block_duration.subsec_millis() ); info!( "all_apply_valid_block_duration={},{:03} seconds.", all_apply_valid_block_duration.as_secs(), - all_apply_valid_block_duration.subsec_nanos() / 1_000_000 + all_apply_valid_block_duration.subsec_millis() ); // Wait recv two finish signals @@ -659,12 +662,12 @@ pub fn sync_ts<DC: DuniterConf>( "Sync {} blocks in {}.{:03} seconds.", current_blockstamp.id.0 + 1, sync_duration.as_secs(), - sync_duration.subsec_nanos() / 1_000_000, + sync_duration.subsec_millis(), ); info!( "Sync {} blocks in {}.{:03} seconds.", current_blockstamp.id.0 + 1, sync_duration.as_secs(), - sync_duration.subsec_nanos() / 1_000_000, + sync_duration.subsec_millis(), ); } diff --git a/blockchain/ts_parsers.rs b/blockchain/ts_parsers.rs index 27782b1cbcbe1db3d066d8a8bc6f9ce5fb2376db..e41c1f009fd4b4bed8e0155f957e8acf4d5706f4 100644 --- a/blockchain/ts_parsers.rs +++ b/blockchain/ts_parsers.rs @@ -47,7 +47,8 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock { issuer: PubKey::Ed25519( ed25519::PublicKey::from_base58( row[4].as_string().expect("Fail to parse block issuer"), - ).expect("Failt to parse block issuer (2)"), + ) + .expect("Failt to parse block issuer (2)"), ), }; let previous_header = if current_header.number.0 > 0 { @@ -58,14 +59,16 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock { row[6] .as_string() .expect("Fail to parse block previous hash"), - ).expect("Fail to parse block previous hash (2)"), + ) + .expect("Fail to parse block previous hash (2)"), ), issuer: PubKey::Ed25519( ed25519::PublicKey::from_base58( row[7] .as_string() .expect("Fail to parse previous block issuer"), - ).expect("Fail to parse previous block issuer (2)"), + ) + .expect("Fail to parse previous block issuer (2)"), ), }) } else { @@ -157,17 +160,20 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock { currency, MembershipType::In(), row[21].as_string().expect("Fail to parse joiners"), - ).expect("Fail to parse joiners (2)"), + ) + .expect("Fail to parse joiners (2)"), actives: parse_memberships( currency, MembershipType::In(), row[22].as_string().expect("Fail to parse actives"), - ).expect("Fail to parse actives (2)"), + ) + .expect("Fail to parse actives (2)"), leavers: parse_memberships( currency, MembershipType::In(), row[23].as_string().expect("Fail to parse leavers"), - ).expect("Fail to parse leavers (2)"), + ) + .expect("Fail to parse leavers (2)"), revoked: Vec::new(), excluded: excluded .as_array() @@ -178,9 +184,11 @@ pub fn parse_ts_block(row: &[sqlite::Value]) -> NetworkBlock { PubKey::Ed25519( ed25519::PublicKey::from_base58( e.as_str().expect("Fail to parse excluded (4)"), - ).expect("Fail to parse excluded (5)"), + ) + .expect("Fail to parse excluded (5)"), ) - }).collect(), + }) + .collect(), certifications: Vec::new(), transactions, inner_hash_and_nonce_str: String::new(), @@ -250,11 +258,13 @@ pub fn parse_memberships( currency, membership_type, raw_memberships.as_array().unwrap(), - ).iter() + ) + .iter() .map(|m| { m.clone() .expect("Fatal error : Fail to parse membership from local DB !") - }).collect(), + }) + .collect(), ); } None @@ -288,7 +298,8 @@ pub fn parse_memberships_from_json_value( } else { Err(MembershipParseError::WrongFormat()) } - }).collect() + }) + .collect() } /// Parse transaction from json value @@ -343,7 +354,8 @@ pub fn parse_transaction( output .as_str() .unwrap_or_else(|| panic!("Fail to parse output : {:?}", output)), - ).unwrap_or_else(|_| panic!("Fail to parse output : {:?}", output)), + ) + .unwrap_or_else(|_| panic!("Fail to parse output : {:?}", output)), ); } let signatures_array = source.get("signatures")?.as_array()?; diff --git a/conf/lib.rs b/conf/lib.rs index c75889d29c18fcc4935722e5373c53c81800a859..3b3125380abbc4bef72cfc4c42f4d6c775e69d3c 100644 --- a/conf/lib.rs +++ b/conf/lib.rs @@ -42,7 +42,7 @@ extern crate rand; extern crate serde; use duniter_crypto::keys::*; use duniter_documents::CurrencyName; -use duniter_module::{DuniterConf, ModuleId, RequiredKeys, RequiredKeysContent}; +use duniter_module::{DuniterConf, ModuleName, RequiredKeys, RequiredKeysContent}; use rand::Rng; use serde::ser::{Serialize, SerializeStruct, Serializer}; use std::collections::HashSet; @@ -62,9 +62,9 @@ pub enum ChangeGlobalConf { /// Change currency ChangeCurrency(CurrencyName), /// Disable module - DisableModule(ModuleId), + DisableModule(ModuleName), /// Enable module - EnableModule(ModuleId), + EnableModule(ModuleName), /// None None(), } @@ -79,9 +79,9 @@ pub struct DuRsConfV1 { /// Configuration of modules in json format (obtained from the conf.json file) pub modules: serde_json::Value, /// Disabled modules - pub disabled: HashSet<ModuleId>, + pub disabled: HashSet<ModuleName>, /// Enabled modules - pub enabled: HashSet<ModuleId>, + pub enabled: HashSet<ModuleName>, } impl Default for DuRsConfV1 { @@ -136,7 +136,7 @@ impl DuniterConf for DuRsConf { _ => panic!("Fail to load duniter conf : conf version not supported !"), } } - fn disable(&mut self, module: ModuleId) { + fn disable(&mut self, module: ModuleName) { match *self { DuRsConf::V1(ref mut conf_v1) => { conf_v1.disabled.insert(module.clone()); @@ -145,7 +145,7 @@ impl DuniterConf for DuRsConf { _ => panic!("Fail to load duniter conf : conf version not supported !"), } } - fn enable(&mut self, module: ModuleId) { + fn enable(&mut self, module: ModuleName) { match *self { DuRsConf::V1(ref mut conf_v1) => { conf_v1.disabled.remove(&module); @@ -154,13 +154,13 @@ impl DuniterConf for DuRsConf { _ => panic!("Fail to load duniter conf : conf version not supported !"), } } - fn disabled_modules(&self) -> HashSet<ModuleId> { + fn disabled_modules(&self) -> HashSet<ModuleName> { match *self { DuRsConf::V1(ref conf_v1) => conf_v1.disabled.clone(), _ => panic!("Fail to load duniter conf : conf version not supported !"), } } - fn enabled_modules(&self) -> HashSet<ModuleId> { + fn enabled_modules(&self) -> HashSet<ModuleName> { match *self { DuRsConf::V1(ref conf_v1) => conf_v1.enabled.clone(), _ => panic!("Fail to load duniter conf : conf version not supported !"), @@ -172,6 +172,25 @@ impl DuniterConf for DuRsConf { _ => panic!("Fail to load duniter conf : conf version not supported !"), } } + fn set_module_conf(&mut self, module_id: String, new_module_conf: serde_json::Value) { + match *self { + DuRsConf::V1(ref mut conf_v1) => { + if conf_v1.modules.is_null() { + let mut new_modules_conf = serde_json::Map::with_capacity(1); + new_modules_conf.insert(module_id, new_module_conf); + conf_v1.modules = serde_json::value::to_value(new_modules_conf) + .expect("Fail to create map of new modules conf !"); + } else { + conf_v1 + .modules + .as_object_mut() + .expect("Conf file currupted !") + .insert(module_id, new_module_conf); + } + } + _ => panic!("Fail to set duniter conf : conf version not supported !"), + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/core/Cargo.toml b/core/Cargo.toml index 550ca8c00b9b808ddf00f82942006c66f00aa3c9..c811e362203ed761a5d50a51ac18a535304285ab 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -9,7 +9,6 @@ license = "AGPL-3.0" path = "lib.rs" [dependencies] -clap = {version = "2.31.2", features = ["yaml"]} dirs = "1.0.2" duniter-blockchain = { path = "../blockchain" } duniter-conf = { path = "../conf" } @@ -17,17 +16,13 @@ duniter-crypto = { path = "../crypto" } duniter-message = { path = "../message" } duniter-module = { path = "../module" } duniter-network = { path = "../network" } -lazy_static = "1.0.*" log = "0.4.*" log-panics = "2.0.*" -rand = "0.4.*" -regex = "1.0.*" -rust-crypto = "0.2.*" serde = "1.0.*" serde_derive = "1.0.*" serde_json = "1.0.*" simplelog = "0.5.*" -sqlite = "0.23.*" +structopt= "0.2.*" threadpool = "1.7.*" [features] diff --git a/core/cli/dbex.rs b/core/cli/dbex.rs new file mode 100644 index 0000000000000000000000000000000000000000..180f204dbed8bc55e9cc094d7a93dc00b865d7f8 --- /dev/null +++ b/core/cli/dbex.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Durs-core cli : dbex subcommands. + +extern crate structopt; + +#[derive(StructOpt, Debug, Clone)] +#[structopt( + name = "dbex", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// durs databases explorer +pub struct DbExOpt { + #[structopt(short = "c", long = "csv")] + /// csv output + pub csv: bool, + #[structopt(subcommand)] + /// DbExSubCommand + pub subcommand: DbExSubCommand, +} + +#[derive(StructOpt, Debug, Clone)] +/// dbex subcommands +pub enum DbExSubCommand { + #[structopt( + name = "distance", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + /// durs databases explorer (distances datas) + DistanceOpt(DistanceOpt), + #[structopt( + name = "members", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + /// durs databases explorer (members datas) + MembersOpt(MembersOpt), + #[structopt( + name = "member", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + /// durs databases explorer (member datas) + MemberOpt(MemberOpt), + #[structopt( + name = "balance", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + /// durs databases explorer (balances datas) + BalanceOpt(BalanceOpt), +} + +#[derive(StructOpt, Debug, Copy, Clone)] +/// DistanceOpt +pub struct DistanceOpt { + #[structopt(short = "r", long = "reverse")] + /// reverse order + pub reverse: bool, +} + +#[derive(StructOpt, Debug, Copy, Clone)] +/// MembersOpt +pub struct MembersOpt { + #[structopt(short = "r", long = "reverse")] + /// reverse order + pub reverse: bool, + #[structopt(short = "e", long = "expire")] + /// show members expire date + pub expire: bool, +} + +#[derive(StructOpt, Debug, Clone)] +/// MemberOpt +pub struct MemberOpt { + /// choose member uid + pub uid: String, +} + +#[derive(StructOpt, Debug, Clone)] +/// BalanceOpt +pub struct BalanceOpt { + /// public key or uid + pub address: String, +} diff --git a/core/cli/mod.rs b/core/cli/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..268211e6518df045c9577fe0135eef36c801fdc6 --- /dev/null +++ b/core/cli/mod.rs @@ -0,0 +1,109 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Define durs-core cli subcommands options. + +extern crate structopt; + +pub mod dbex; +pub mod modules; +pub mod reset; +pub mod start; +pub mod sync; + +pub use dbex::*; +use log::Level; +pub use modules::*; +pub use reset::*; +pub use start::*; +pub use sync::*; + +/*/// Inject core subcommands +pub fn inject_core_subcommands<'a, 'b>( + core_cli_conf_without_subcommands: App<'a, 'b>, +) -> App<'a, 'b> { + core_cli_conf_without_subcommands.subcommands(vec![ + EnableOpt::clap(), + DisableOpt::clap(), + ListModulesOpt::clap(), + StartOpt::clap(), + SyncOpt::clap(), + SyncTsOpt::clap(), + ]) +}*/ + +#[derive(StructOpt, Debug)] +#[structopt( + name = "durs", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// Rust implementation of Duniter +pub struct DursOpt { + #[structopt(short = "p", long = "profile")] + /// Set a custom user datas folder + profile_name: Option<String>, + #[structopt(short = "l", long = "logs", raw(next_line_help = "true"))] + /// Set the level of logs verbosity. (Default is INFO). + /// Possible values : [OFF, ERROR, WARN, INFO, DEBUG, TRACE] + logs_level: Option<Level>, + #[structopt(subcommand)] + /// CoreSubCommand + cmd: CoreSubCommand, +} + +#[derive(StructOpt, Debug)] +/// Core cli subcommands +pub enum CoreSubCommand { + #[structopt(name = "enable")] + /// Enable some module + EnableOpt(EnableOpt), + #[structopt(name = "disable")] + /// Disable some module + DisableOpt(DisableOpt), + #[structopt(name = "modules")] + /// list modules + ListModulesOpt(ListModulesOpt), + #[structopt(name = "start")] + /// start durs server + StartOpt(StartOpt), + #[structopt(name = "sync")] + /// synchronization from network + SyncOpt(SyncOpt), + #[structopt(name = "sync_ts")] + /// synchronization via a duniter-ts database + SyncTsOpt(SyncTsOpt), + /// reset data or conf or all + #[structopt( + name = "reset", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + ResetOpt(ResetOpt), + /// durs databases explorer + #[structopt( + name = "dbex", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") + )] + DbExOpt(DbExOpt), +} + +/// InvalidInput +#[derive(Debug, Copy, Clone)] +pub struct InvalidInput(&'static str); + +impl ToString for InvalidInput { + fn to_string(&self) -> String { + String::from(self.0) + } +} diff --git a/core/cli/modules.rs b/core/cli/modules.rs new file mode 100644 index 0000000000000000000000000000000000000000..258aad17657b4a019b6a392eae78b54575faaec1 --- /dev/null +++ b/core/cli/modules.rs @@ -0,0 +1,86 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Durs-core cli : modules manager subcommands. + +extern crate structopt; + +use duniter_module::*; +use std::collections::HashSet; + +#[derive(StructOpt, Debug)] +#[structopt( + name = "enable", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// Enable some module +pub struct EnableOpt { + #[structopt(parse(from_str))] + /// The module name to enable + pub module_name: ModuleName, +} + +#[derive(StructOpt, Debug)] +#[structopt( + name = "disable", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// Disable some module +pub struct DisableOpt { + #[structopt(parse(from_str))] + /// The module name to disable + pub module_name: ModuleName, +} + +#[derive(StructOpt, Debug, Copy, Clone)] +#[structopt( + name = "modules", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// list module +pub struct ListModulesOpt { + #[structopt(short = "d")] + /// list only disabled modules + pub disabled: bool, + #[structopt(short = "e")] + /// list only enabled modules + pub enabled: bool, + #[structopt(short = "n")] + /// list only network modules + pub network: bool, + #[structopt(short = "s")] + /// list only modules having access to the secret member key + pub secret: bool, +} + +impl ListModulesOpt { + /// Extract modules filters from cli options + pub fn get_filters(self) -> HashSet<ModulesFilter> { + let mut filters = HashSet::with_capacity(4); + if self.disabled { + filters.insert(ModulesFilter::Enabled(false)); + } + if self.enabled { + filters.insert(ModulesFilter::Enabled(true)); + } + if self.network { + filters.insert(ModulesFilter::Network()); + } + if self.secret { + filters.insert(ModulesFilter::RequireMemberPrivKey()); + } + filters + } +} diff --git a/core/cli/reset.rs b/core/cli/reset.rs new file mode 100644 index 0000000000000000000000000000000000000000..0b112cf2a72112f60ade1af1266667db84937fe5 --- /dev/null +++ b/core/cli/reset.rs @@ -0,0 +1,52 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Durs-core cli : reset subcommand. + +extern crate structopt; + +use cli::InvalidInput; +use std::str::FromStr; + +#[derive(StructOpt, Debug, Copy, Clone)] +/// start durs server +pub struct ResetOpt { + /// choose type datas to reset + pub reset_type: ResetType, +} + +#[derive(Debug, Copy, Clone)] +/// Reset type +pub enum ResetType { + /// Reset datas + Datas, + /// Reset configuration + Conf, + /// Reset all + All, +} + +impl FromStr for ResetType { + type Err = InvalidInput; + + fn from_str(source: &str) -> Result<Self, Self::Err> { + match source { + "data" => Ok(ResetType::Datas), + "conf" => Ok(ResetType::Conf), + "all" => Ok(ResetType::All), + _ => Err(InvalidInput("Values accepted are : data, conf, all.")), + } + } +} diff --git a/core/cli/start.rs b/core/cli/start.rs new file mode 100644 index 0000000000000000000000000000000000000000..4d9528594aaf0b7972093a23de7ed2672f162626 --- /dev/null +++ b/core/cli/start.rs @@ -0,0 +1,26 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Durs-core cli : start subcommands. + +extern crate structopt; + +#[derive(StructOpt, Debug, Copy, Clone)] +#[structopt( + name = "start", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// start durs server +pub struct StartOpt {} diff --git a/core/cli/sync.rs b/core/cli/sync.rs new file mode 100644 index 0000000000000000000000000000000000000000..d462e2d64705ee6af15fe07cccb2b886e2a38b61 --- /dev/null +++ b/core/cli/sync.rs @@ -0,0 +1,56 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Durs-core cli : sync subcommands. + +extern crate structopt; + +#[derive(StructOpt, Debug, Clone)] +#[structopt( + name = "sync", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// synchronization from network +pub struct SyncOpt { + /// The domain name or ip address of the node from which to synchronize. + pub host: String, + /// The port number of the node from which to synchronize. + pub port: u16, + /// The endpoint path of the node from which to synchronize. + pub path: Option<String>, + #[structopt(short = "c", long = "cautious")] + /// cautious mode (check all protocol rules, very slow) + pub cautious_mode: bool, + #[structopt(short = "u", long = "unsafe")] + /// unsafe mode (not check blocks inner hashs, very dangerous) + pub unsafe_mode: bool, +} + +#[derive(StructOpt, Debug, Clone)] +#[structopt( + name = "sync", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// synchronization via a duniter-ts database +pub struct SyncTsOpt { + /// Set the ts profile to use + pub ts_profile: Option<String>, + #[structopt(short = "c", long = "cautious")] + /// cautious mode (check all protocol rules, very slow) + pub cautious_mode: bool, + #[structopt(short = "u", long = "unsafe")] + /// unsafe mode (not check blocks inner hashs, very dangerous) + pub unsafe_mode: bool, +} diff --git a/core/lib.rs b/core/lib.rs index 783d34762d1bbe78099636f17dca01fa515aa140..9f46712eec87d3a2cc0820aeaaac14559dec2d6d 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -16,10 +16,9 @@ //! Crate containing Duniter-rust core. #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] +//#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] #![deny( missing_docs, - missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, @@ -29,11 +28,10 @@ unused_qualifications )] -#[macro_use] -extern crate clap; - #[macro_use] extern crate log; +#[macro_use] +extern crate structopt; extern crate dirs; extern crate duniter_blockchain; @@ -45,53 +43,74 @@ extern crate duniter_network; extern crate log_panics; extern crate serde_json; extern crate simplelog; -extern crate sqlite; extern crate threadpool; pub mod change_conf; +pub mod cli; +pub mod rooter; -use clap::{App, ArgMatches}; use duniter_blockchain::{BlockchainModule, DBExQuery, DBExTxQuery, DBExWotQuery}; pub use duniter_conf::{ChangeGlobalConf, DuRsConf, DuniterKeyPairs}; -use duniter_message::DuniterMessage; +use duniter_message::*; use duniter_module::*; -use duniter_network::{NetworkModule, SyncEndpoint}; +use duniter_network::{NetworkModule, SyncEndpoint, SyncParams}; use log::Level; use simplelog::*; -use std::collections::HashSet; +//use std::error::Error; +//use std::fmt::{Debug, Formatter}; +use cli::*; use std::fs; use std::fs::{File, OpenOptions}; use std::sync::mpsc; -use std::thread; -use std::time::Duration; +use structopt::clap::{App, ArgMatches}; +use structopt::StructOpt; use threadpool::ThreadPool; +/// Number of thread in plugins ThreadPool +pub static THREAD_POOL_SIZE: &'static usize = &2; + #[derive(Debug, Clone)] /// User command pub enum UserCommand { /// Start Start(), /// Sync (SyncEndpoint) - Sync(SyncEndpoint), + Sync(SyncParams), /// List modules - ListModules(HashSet<ModulesFilter>), - /// Other command - Other(), + ListModules(ListModulesOpt), + /// Unknow command + UnknowCommand(String), } -#[derive(Debug)] +/// TupleApp +#[derive(Clone)] +pub struct TupleApp<'b, 'a: 'b>(&'b App<'a, 'b>); + +/*impl<'b, 'a: 'b> Debug for TupleApp<'a, 'b> { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "TupleApp()") + } +}*/ + +#[derive(Clone)] /// Duniter Core Datas -pub struct DuniterCore<DC: DuniterConf> { +pub struct DuniterCore<'a, 'b: 'a, DC: DuniterConf> { + /// Command line configuration + pub cli_conf: TupleApp<'a, 'b>, + /// Command line arguments parsing by clap + pub cli_args: Option<ArgMatches<'a>>, + /// Plugins command line configuration + pub plugins_cli_conf: Vec<App<'b, 'a>>, /// Does the entered command require to launch server ? - pub user_command: UserCommand, + pub user_command: Option<UserCommand>, /// Software meta datas pub soft_meta_datas: SoftwareMetaDatas<DC>, /// Keypairs - pub keypairs: DuniterKeyPairs, + pub keypairs: Option<DuniterKeyPairs>, /// Run duration. Zero = infinite duration. pub run_duration_in_secs: u64, /// Sender channel of rooter thread - pub rooter_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, + pub rooter_sender: Option<mpsc::Sender<RooterThreadMessage<DursMsg>>>, /// Count the number of plugged modules pub modules_count: usize, /// Count the number of plugged network modules @@ -100,210 +119,208 @@ pub struct DuniterCore<DC: DuniterConf> { pub thread_pool: ThreadPool, } -impl DuniterCore<DuRsConf> { - /// Instantiate Duniter classic node +impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { + /// Instantiate Duniter node pub fn new( soft_name: &'static str, soft_version: &'static str, - ) -> Option<DuniterCore<DuRsConf>> { - DuniterCore::new_specialized_node(soft_name, soft_version, 0, vec![], vec![], None) - } - /// Instantiate Duniter specialize node - pub fn new_specialized_node<'a, 'b>( - soft_name: &'static str, - soft_version: &'static str, + cli_conf: &'a App<'b, 'a>, run_duration_in_secs: u64, - external_followers: Vec<mpsc::Sender<DuniterMessage>>, - sup_apps: Vec<App<'a, 'b>>, - sup_apps_fn: Option<&Fn(&str, &ArgMatches) -> ()>, - ) -> Option<DuniterCore<DuRsConf>> { + ) -> DuniterCore<'b, 'a, DuRsConf> { // Get cli conf - let yaml = load_yaml!("./cli/en.yml"); - let cli_conf = App::from_yaml(yaml); - - // Math command line arguments - let cli_args = if !sup_apps.is_empty() { + //let yaml = load_yaml!("./cli/en.yml"); + //let cli_conf = TupleApp(App::from_yaml(yaml)); + DuniterCore { + cli_conf: TupleApp(cli_conf), + cli_args: None, + plugins_cli_conf: vec![], + user_command: None, + soft_meta_datas: SoftwareMetaDatas { + soft_name, + soft_version, + profile: String::from("default"), + conf: DuRsConf::default(), + }, + keypairs: None, + run_duration_in_secs, + rooter_sender: None, + modules_count: 0, + network_modules_count: 0, + thread_pool: ThreadPool::new(*THREAD_POOL_SIZE), + } + } + /// Execute user command + pub fn match_user_command(&mut self) -> bool { + self.match_specialize_user_command(vec![], None, vec![]) + } + /// Execute specialize user command + pub fn match_specialize_user_command( + &mut self, + sup_apps: Vec<App<'a, 'b>>, + sup_apps_fn: Option<&Fn(&str, &ArgMatches) -> bool>, + external_followers: Vec<mpsc::Sender<DursMsgContent>>, + ) -> bool { + // Inject core subcommands + //let core_cli_conf = inject_core_subcommands(self.cli_conf.0.clone()); + let core_cli_conf = self.cli_conf.0.clone(); + // Inject plugins subcommands + let cli_conf = if !self.plugins_cli_conf.is_empty() { + core_cli_conf.subcommands(self.plugins_cli_conf.clone()) + } else { + core_cli_conf + }; + // Inject specialize node subcommands a Math command line arguments + self.cli_args = Some(if !sup_apps.is_empty() { cli_conf.subcommands(sup_apps).get_matches() } else { cli_conf.get_matches() - }; - + }); + let cli_args = self.cli_args.clone().expect("cli_args must be Some !"); // Get datas profile name let profile = match_profile(&cli_args); // Init logger - init_logger(profile.as_str(), soft_name, &cli_args); + init_logger(profile.as_str(), self.soft_meta_datas.soft_name, &cli_args); // Print panic! in logs - log_panics::init(); + //log_panics::init(); // Load global conf let (conf, keypairs) = duniter_conf::load_conf(profile.as_str()); info!("Success to load global conf."); - // Define SoftwareMetaDatas - let soft_meta_datas = SoftwareMetaDatas { - soft_name, - soft_version, - profile: profile.clone(), - conf: conf.clone(), - }; + // save profile and conf + self.soft_meta_datas.profile = profile.clone(); + self.soft_meta_datas.conf = conf.clone(); + + // Save keypairs + self.keypairs = Some(keypairs); /* * COMMAND LINE PROCESSING */ if let Some(matches) = cli_args.subcommand_matches("disable") { - let module_name = matches - .value_of("MODULE_NAME") - .expect("disable: you must enter a module name !") - .to_string(); + let opts = DisableOpt::from_clap(matches); change_conf::change_global_conf( &profile, conf, - ChangeGlobalConf::DisableModule(ModuleId(module_name)), + ChangeGlobalConf::DisableModule(opts.module_name), ); - None + false } else if let Some(matches) = cli_args.subcommand_matches("enable") { - let module_name = matches - .value_of("MODULE_NAME") - .expect("enable: you must enter a module name !") - .to_string(); + let opts = EnableOpt::from_clap(matches); change_conf::change_global_conf( &profile, conf, - ChangeGlobalConf::EnableModule(ModuleId(module_name)), + ChangeGlobalConf::EnableModule(opts.module_name), ); - None + false } else if let Some(matches) = cli_args.subcommand_matches("modules") { - let mut filters = HashSet::new(); - if matches.is_present("disabled") { - filters.insert(ModulesFilter::Enabled(false)); - } else if matches.is_present("enabled") { - filters.insert(ModulesFilter::Enabled(true)); - } - if matches.is_present("network") { - filters.insert(ModulesFilter::Network()); - } - if matches.is_present("secret") { - filters.insert(ModulesFilter::RequireMemberPrivKey()); - } - Some(list_modules(soft_meta_datas, keypairs, filters)) + // Store user command + self.user_command = Some(UserCommand::ListModules(ListModulesOpt::from_clap(matches))); + + // Start rooter thread + self.rooter_sender = Some(rooter::start_rooter::<DuRsConf>(0, vec![])); + true } else if let Some(_matches) = cli_args.subcommand_matches("start") { - Some(start( - soft_meta_datas, - keypairs, - run_duration_in_secs, + // Store user command + self.user_command = Some(UserCommand::Start()); + + // Start rooter thread + self.rooter_sender = Some(rooter::start_rooter::<DuRsConf>( + self.run_duration_in_secs, external_followers, - )) + )); + true } else if let Some(matches) = cli_args.subcommand_matches("sync") { - let domain_or_ip = matches - .value_of("DOMAIN_OR_IP") - .expect("sync: you must enter a domain name or ip address !") - .to_string(); - let port: u16 = matches - .value_of("PORT") - .expect("sync: you must enter a port number !") - .parse() - .expect("sync: port : you must enter an integer value !"); - let path = if let Some(path) = matches.value_of("PATH") { - Some(path.to_string()) - } else { - None - }; + let opts = SyncOpt::from_clap(matches); let sync_endpoint = SyncEndpoint { - domain_or_ip, - port, - path, + domain_or_ip: opts.host, + port: opts.port, + path: opts.path, tls: false, }; - Some(sync( - soft_meta_datas, - keypairs, + // Store sync command parameters + self.user_command = Some(UserCommand::Sync(SyncParams { sync_endpoint, - matches.is_present("cautious"), - !matches.is_present("unsafe"), - )) + cautious: opts.cautious_mode, + verif_hashs: opts.unsafe_mode, + })); + // Start rooter thread + self.rooter_sender = Some(rooter::start_rooter::<DuRsConf>(0, vec![])); + true } else if let Some(matches) = cli_args.subcommand_matches("sync_ts") { - let ts_profile = matches.value_of("TS_PROFILE").unwrap_or("duniter_default"); + let opts = SyncTsOpt::from_clap(matches); + let ts_profile = opts + .ts_profile + .unwrap_or_else(|| String::from("duniter_default")); sync_ts( profile.as_str(), &conf, - ts_profile, - matches.is_present("cautious"), - !matches.is_present("unsafe"), + &ts_profile, + opts.cautious_mode, + opts.unsafe_mode, ); - None + false } else if let Some(matches) = cli_args.subcommand_matches("dbex") { - let csv = matches.is_present("csv"); - if let Some(distances_matches) = matches.subcommand_matches("distances") { - dbex( + let opts = DbExOpt::from_clap(matches); + match opts.subcommand { + DbExSubCommand::DistanceOpt(distance_opts) => dbex( profile.as_str(), &conf, - csv, - &DBExQuery::WotQuery(DBExWotQuery::AllDistances( - distances_matches.is_present("reverse"), - )), - ); - } else if let Some(member_matches) = matches.subcommand_matches("member") { - let uid = member_matches.value_of("UID").unwrap_or(""); - dbex( + opts.csv, + &DBExQuery::WotQuery(DBExWotQuery::AllDistances(distance_opts.reverse)), + ), + DbExSubCommand::MemberOpt(member_opts) => dbex( profile.as_str(), &conf, - csv, - &DBExQuery::WotQuery(DBExWotQuery::MemberDatas(String::from(uid))), - ); - } else if let Some(members_matches) = matches.subcommand_matches("members") { - if members_matches.is_present("expire") { - dbex( - profile.as_str(), - &conf, - csv, - &DBExQuery::WotQuery(DBExWotQuery::ExpireMembers( - members_matches.is_present("reverse"), - )), - ); - } else { - dbex( - profile.as_str(), - &conf, - csv, - &DBExQuery::WotQuery(DBExWotQuery::ListMembers( - members_matches.is_present("reverse"), - )), - ); + opts.csv, + &DBExQuery::WotQuery(DBExWotQuery::MemberDatas(member_opts.uid)), + ), + DbExSubCommand::MembersOpt(members_opts) => { + if members_opts.expire { + dbex( + profile.as_str(), + &conf, + opts.csv, + &DBExQuery::WotQuery(DBExWotQuery::ExpireMembers(members_opts.reverse)), + ); + } else { + dbex( + profile.as_str(), + &conf, + opts.csv, + &DBExQuery::WotQuery(DBExWotQuery::ListMembers(members_opts.reverse)), + ); + } } - } else if let Some(balance_matches) = matches.subcommand_matches("balance") { - let address = balance_matches.value_of("ADDRESS").unwrap_or(""); - dbex( + DbExSubCommand::BalanceOpt(balance_opts) => dbex( &profile, &conf, - csv, - &DBExQuery::TxQuery(DBExTxQuery::Balance(String::from(address))), - ); + opts.csv, + &DBExQuery::TxQuery(DBExTxQuery::Balance(balance_opts.address)), + ), } - None + false } else if let Some(matches) = cli_args.subcommand_matches("reset") { + let opts = ResetOpt::from_clap(matches); let mut profile_path = match dirs::config_dir() { Some(path) => path, None => panic!("Impossible to get user config directory !"), }; - profile_path.push(".config"); profile_path.push(duniter_conf::get_user_datas_folder()); profile_path.push(profile.clone()); if !profile_path.as_path().exists() { panic!(format!("Error : {} profile don't exist !", profile)); } - match matches - .value_of("DATAS_TYPE") - .expect("cli param DATAS_TYPE is missing !") - { - "data" => { + match opts.reset_type { + ResetType::Datas => { let mut currency_datas_path = profile_path.clone(); currency_datas_path.push("g1"); fs::remove_dir_all(currency_datas_path.as_path()) .expect("Fail to remove all currency datas !"); } - "conf" => { + ResetType::Conf => { let mut conf_file_path = profile_path.clone(); conf_file_path.push("conf.json"); fs::remove_file(conf_file_path.as_path()).expect("Fail to remove conf file !"); @@ -312,45 +329,62 @@ impl DuniterCore<DuRsConf> { fs::remove_file(conf_keys_path.as_path()) .expect("Fail to remove keypairs file !"); } - "all" => { + ResetType::All => { fs::remove_dir_all(profile_path.as_path()) .expect("Fail to remove all profile datas !"); } - _ => {} } - None - } else if let Some(sup_apps_fn) = sup_apps_fn { - sup_apps_fn(profile.as_str(), &cli_args); - None + false + } else if let Some(unknow_subcommand) = cli_args.subcommand_name() { + let mut module_subcommand = true; + if let Some(sup_apps_fn) = sup_apps_fn { + if sup_apps_fn(profile.as_str(), &cli_args) { + module_subcommand = false; + } + } + if module_subcommand { + self.user_command = + Some(UserCommand::UnknowCommand(String::from(unknow_subcommand))); + true + } else { + false + } } else { - panic!("unknow sub-command !") + println!("Please use a subcommand. -h for help."); + false } } - /// Start blockchain module - pub fn start_blockchain(&self) { + /// Start core (=blockchain module) + pub fn start_core(&self) { if self.network_modules_count == 0 { panic!("You must plug at least one network layer !"); } - if let UserCommand::Start() = self.user_command { - thread::sleep(Duration::from_secs(2)); + if let Some(UserCommand::Start()) = self.user_command { // Create blockchain module channel let (blockchain_sender, blockchain_receiver): ( - mpsc::Sender<DuniterMessage>, - mpsc::Receiver<DuniterMessage>, + mpsc::Sender<DursMsg>, + mpsc::Receiver<DursMsg>, ) = mpsc::channel(); + let rooter_sender = if let Some(ref rooter_sender) = self.rooter_sender { + rooter_sender + } else { + panic!("Try to start core without rooter_sender !"); + }; + // Send blockchain sender to rooter thread - self.rooter_sender - .send(RooterThreadMessage::ModuleSender(blockchain_sender)) + rooter_sender + .send(RooterThreadMessage::ModuleSender( + BlockchainModule::name(), + blockchain_sender, + vec![ModuleRole::BlockchainDatas, ModuleRole::BlockValidation], + vec![ModuleEvent::NewBlockFromNetwork], + )) .expect("Fatal error: fail to send blockchain sender to rooter thread !"); - // Send modules_count to rooter thread - self.rooter_sender - .send(RooterThreadMessage::ModulesCount(self.modules_count + 1)) - .expect("Fatal error: fail to send modules count to rooter thread !"); - // Instantiate blockchain module and load is conf let mut blockchain_module = BlockchainModule::load_blockchain_conf( + rooter_sender.clone(), &self.soft_meta_datas.profile, &self.soft_meta_datas.conf, RequiredKeysContent::MemberKeyPair(None), @@ -362,306 +396,182 @@ impl DuniterCore<DuRsConf> { } } /// Plug a network module - pub fn plug_network<NM: NetworkModule<DuRsConf, DuniterMessage>>(&mut self) { - let enabled = enabled::<DuRsConf, DuniterMessage, NM>(&self.soft_meta_datas.conf); + pub fn plug_network<NM: NetworkModule<DuRsConf, DursMsg>>(&mut self) { + let enabled = enabled::<DuRsConf, DursMsg, NM>(&self.soft_meta_datas.conf); if enabled { - if let UserCommand::Start() = self.user_command { - self.network_modules_count += 1; - self.plug::<NM>(); - } else if let UserCommand::Sync(ref sync_endpoint) = self.user_command { - self.network_modules_count += 1; + self.network_modules_count += 1; + if let Some(UserCommand::Sync(ref network_sync)) = self.user_command { // Start module in a new thread - let rooter_sender = self.rooter_sender.clone(); + let rooter_sender = self + .rooter_sender + .clone() + .expect("Try to start a core without rooter_sender !"); let soft_meta_datas = self.soft_meta_datas.clone(); let module_conf_json = self .soft_meta_datas .conf .clone() .modules() - .get(&NM::id().to_string().as_str()) + .get(&NM::name().to_string().as_str()) .cloned(); let keypairs = self.keypairs; - let sync_endpoint = sync_endpoint.clone(); + let sync_params = network_sync.clone(); self.thread_pool.execute(move || { // Load module conf and keys - let (module_conf, required_keys) = - load_module_conf_and_keys::<NM>(module_conf_json, keypairs); + let (module_conf, required_keys) = get_module_conf_and_keys::<NM>( + module_conf_json, + keypairs.expect("Try to plug addon into a core without keypair !"), + ); NM::sync( &soft_meta_datas, required_keys, module_conf, rooter_sender, - sync_endpoint, - ).unwrap_or_else(|_| { + sync_params, + ) + .unwrap_or_else(|_| { panic!( "Fatal error : fail to load {} Module !", - NM::id().to_string() + NM::name().to_string() ) }); }); self.modules_count += 1; - info!("Success to load {} module.", NM::id().to_string()); - } - } - if let UserCommand::ListModules(ref filters) = self.user_command { - if module_valid_filters::<DuRsConf, DuniterMessage, NM>( - &self.soft_meta_datas.conf, - filters, - true, - ) { - if enabled { - println!("{}", NM::id().to_string()); - } else { - println!("{} (disabled)", NM::id().to_string()); - } + info!("Success to load {} module.", NM::name().to_string()); + } else { + self.plug_::<NM>(true); } + } else { + self.plug_::<NM>(true); } } + + /// Inject cli subcommand + pub fn inject_cli_subcommand<M: DuniterModule<DuRsConf, DursMsg>>(&mut self) { + //self.cli_conf = TupleApp(&self.cli_conf.0.clone().subcommand(M::ModuleOpt::clap())); + self.plugins_cli_conf.push(M::ModuleOpt::clap()); + } + + /// Plug a module + pub fn plug<M: DuniterModule<DuRsConf, DursMsg>>(&mut self) { + self.plug_::<M>(false); + } + /// Plug a module - pub fn plug<M: DuniterModule<DuRsConf, DuniterMessage>>(&mut self) { - let enabled = enabled::<DuRsConf, DuniterMessage, M>(&self.soft_meta_datas.conf); + fn plug_<M: DuniterModule<DuRsConf, DursMsg>>(&mut self, is_network_module: bool) { + let enabled = enabled::<DuRsConf, DursMsg, M>(&self.soft_meta_datas.conf); if enabled { - if let UserCommand::Start() = self.user_command { + if let Some(UserCommand::Start()) = self.user_command { // Start module in a new thread - let rooter_sender_clone = self.rooter_sender.clone(); + let rooter_sender_clone = self + .rooter_sender + .clone() + .expect("Try to start a core without rooter_sender !"); let soft_meta_datas = self.soft_meta_datas.clone(); let module_conf_json = self .soft_meta_datas .conf .clone() .modules() - .get(&M::id().to_string().as_str()) + .get(&M::name().to_string().as_str()) .cloned(); let keypairs = self.keypairs; self.thread_pool.execute(move || { // Load module conf and keys - let (module_conf, required_keys) = - load_module_conf_and_keys::<M>(module_conf_json, keypairs); + let (module_conf, required_keys) = get_module_conf_and_keys::<M>( + module_conf_json, + keypairs.expect("Try to plug addon into a core without keypair !"), + ); M::start( &soft_meta_datas, required_keys, module_conf, rooter_sender_clone, false, - ).unwrap_or_else(|_| { + ) + .unwrap_or_else(|_| { panic!( "Fatal error : fail to load {} Module !", - M::id().to_string() + M::name().to_string() ) }); }); self.modules_count += 1; - info!("Success to load {} module.", M::id().to_string()); + info!("Success to load {} module.", M::name().to_string()); + } else if let Some(UserCommand::UnknowCommand(ref subcommand)) = self.user_command { + if M::have_subcommand() && *subcommand == M::name().to_string() { + // Math command line arguments + if let Some(subcommand_args) = self + .cli_args + .clone() + .expect("cli_args must be Some !") + .subcommand_matches(M::name().to_string()) + { + // Load module conf and keys + let module_conf_json = self + .soft_meta_datas + .conf + .clone() + .modules() + .get(&M::name().to_string().as_str()) + .cloned(); + let (_conf, keypairs) = + duniter_conf::load_conf(self.soft_meta_datas.profile.as_str()); + let (module_conf, required_keys) = + get_module_conf_and_keys::<M>(module_conf_json, keypairs); + // Execute module subcommand + M::exec_subcommand( + &self.soft_meta_datas, + required_keys, //required_keys, + module_conf, //module_conf, + M::ModuleOpt::from_clap(subcommand_args), + ); + } + } } } - if let UserCommand::ListModules(ref filters) = self.user_command { - if module_valid_filters::<DuRsConf, DuniterMessage, M>( + if let Some(UserCommand::ListModules(ref options)) = self.user_command { + if module_valid_filters::<DuRsConf, DursMsg, M, std::collections::hash_map::RandomState>( &self.soft_meta_datas.conf, - filters, - false, + &options.get_filters(), + is_network_module, ) { if enabled { - println!("{}", M::id().to_string()); + println!("{}", M::name().to_string()); } else { - println!("{} (disabled)", M::id().to_string()); + println!("{} (disabled)", M::name().to_string()); } } } } } -/// Load module conf and keys -pub fn load_module_conf_and_keys<M: DuniterModule<DuRsConf, DuniterMessage>>( +/// Get module conf and keys +pub fn get_module_conf_and_keys<M: DuniterModule<DuRsConf, DursMsg>>( module_conf_json: Option<serde_json::Value>, keypairs: DuniterKeyPairs, ) -> (M::ModuleConf, RequiredKeysContent) { - let module_conf = if let Some(module_conf_json) = module_conf_json { + ( + get_module_conf::<M>(module_conf_json), + DuniterKeyPairs::get_required_keys_content(M::ask_required_keys(), keypairs), + ) +} + +/// get module conf +pub fn get_module_conf<M: DuniterModule<DuRsConf, DursMsg>>( + module_conf_json: Option<serde_json::Value>, +) -> M::ModuleConf { + if let Some(module_conf_json) = module_conf_json { serde_json::from_str(module_conf_json.to_string().as_str()) - .unwrap_or_else(|_| panic!("Fail to parse conf of module {}", M::id().to_string())) + .unwrap_or_else(|_| panic!("Fail to parse conf of module {}", M::name().to_string())) } else { M::ModuleConf::default() - }; - let required_keys = - DuniterKeyPairs::get_required_keys_content(M::ask_required_keys(), keypairs); - - (module_conf, required_keys) + } } /// Match cli option --profile pub fn match_profile(cli_args: &ArgMatches) -> String { - String::from(cli_args.value_of("profile").unwrap_or("default")) -} - -/// List modules -pub fn list_modules<DC: DuniterConf>( - soft_meta_datas: SoftwareMetaDatas<DC>, - keypairs: DuniterKeyPairs, - modules_filter: HashSet<ModulesFilter>, -) -> DuniterCore<DC> { - // Start rooter thread - let rooter_sender = start_rooter::<DC>(0, vec![]); - - // Instanciate DuniterCore - DuniterCore { - user_command: UserCommand::ListModules(modules_filter), - soft_meta_datas, - keypairs, - run_duration_in_secs: 0, - rooter_sender, - modules_count: 0, - network_modules_count: 0, - thread_pool: ThreadPool::new(2), - } -} - -/// Start rooter thread -pub fn start_rooter<DC: DuniterConf>( - run_duration_in_secs: u64, - external_followers: Vec<mpsc::Sender<DuniterMessage>>, -) -> mpsc::Sender<RooterThreadMessage<DuniterMessage>> { - // Create senders channel - let (rooter_sender, main_receiver): ( - mpsc::Sender<RooterThreadMessage<DuniterMessage>>, - mpsc::Receiver<RooterThreadMessage<DuniterMessage>>, - ) = mpsc::channel(); - - // Create rooter thread - thread::spawn(move || { - // Wait to receiver modules senders - let mut modules_senders: Vec<mpsc::Sender<DuniterMessage>> = Vec::new(); - let mut modules_count_expected = None; - while modules_count_expected.is_none() - || modules_senders.len() < modules_count_expected.expect("safe unwrap") + 1 - { - match main_receiver.recv_timeout(Duration::from_secs(20)) { - Ok(mess) => { - match mess { - RooterThreadMessage::ModuleSender(module_sender) => { - // Subscribe this module to all others modules - for other_module in modules_senders.clone() { - if other_module - .send(DuniterMessage::Followers(vec![module_sender.clone()])) - .is_err() - { - panic!("Fatal error : fail to send all modules senders to all modules !"); - } - } - // Subcribe this module to all external_followers - for external_follower in external_followers.clone() { - if external_follower - .send(DuniterMessage::Followers(vec![module_sender.clone()])) - .is_err() - { - panic!("Fatal error : fail to send all modules senders to all external_followers !"); - } - } - // Subscribe all other modules to this module - if module_sender - .send(DuniterMessage::Followers(modules_senders.clone())) - .is_err() - { - panic!("Fatal error : fail to send all modules senders to all modules !"); - } - // Subcribe all external_followers to this module - if module_sender - .send(DuniterMessage::Followers(external_followers.clone())) - .is_err() - { - panic!("Fatal error : fail to send all external_followers to all modules !"); - } - // Push this module to modules_senders list - modules_senders.push(module_sender); - // Log the number of modules_senders received - info!( - "Rooter thread receive {} module senders", - modules_senders.len() - ); - } - RooterThreadMessage::ModulesCount(modules_count) => { - info!("Rooter thread receive ModulesCount({})", modules_count); - if modules_senders.len() == modules_count { - break; - } else if modules_senders.len() < modules_count { - modules_count_expected = Some(modules_count); - } else { - panic!("Fatal error : Receive more modules_sender than expected !") - } - } - } - } - Err(e) => match e { - mpsc::RecvTimeoutError::Timeout => { - panic!("Fatal error : not receive all modules_senders after 20 secs !") - } - mpsc::RecvTimeoutError::Disconnected => { - panic!("Fatal error : rooter thread disconnnected !") - } - }, - } - } - info!("Receive all modules senders."); - if run_duration_in_secs > 0 { - thread::sleep(Duration::from_secs(run_duration_in_secs)); - // Send DuniterMessage::Stop() to all modules - for sender in modules_senders { - if sender.send(DuniterMessage::Stop()).is_err() { - panic!("Fail to send Stop() message to one module !") - } - } - thread::sleep(Duration::from_secs(2)); - } - }); - - rooter_sender -} - -/// Launch duniter server -pub fn start<DC: DuniterConf>( - soft_meta_datas: SoftwareMetaDatas<DC>, - keypairs: DuniterKeyPairs, - run_duration_in_secs: u64, - external_followers: Vec<mpsc::Sender<DuniterMessage>>, -) -> DuniterCore<DC> { - info!("Starting Duniter-rs..."); - - // Start rooter thread - let rooter_sender = start_rooter::<DC>(run_duration_in_secs, external_followers); - - // Instanciate DuniterCore - DuniterCore { - user_command: UserCommand::Start(), - soft_meta_datas, - keypairs, - run_duration_in_secs, - rooter_sender, - modules_count: 0, - network_modules_count: 0, - thread_pool: ThreadPool::new(2), - } -} - -/// Launch synchronisation from network -pub fn sync<DC: DuniterConf>( - soft_meta_datas: SoftwareMetaDatas<DC>, - keypairs: DuniterKeyPairs, - sync_endpoint: SyncEndpoint, - _cautious: bool, - _verif_hashs: bool, -) -> DuniterCore<DC> { - // Start rooter thread - let rooter_sender = start_rooter::<DC>(0, vec![]); - - // Instanciate DuniterCore - DuniterCore { - user_command: UserCommand::Sync(sync_endpoint), - soft_meta_datas, - keypairs, - run_duration_in_secs: 0, - rooter_sender, - modules_count: 0, - network_modules_count: 0, - thread_pool: ThreadPool::new(2), - } + String::from(cli_args.value_of("profile_name").unwrap_or("default")) } /// Launch synchronisation from a duniter-ts database @@ -689,7 +599,6 @@ pub fn init_logger(profile: &str, soft_name: &'static str, cli_args: &ArgMatches Some(path) => path, None => panic!("Fatal error : Impossible to get user config directory"), }; - log_file_path.push(".config"); if !log_file_path.as_path().exists() { fs::create_dir(log_file_path.as_path()).expect("Impossible to create ~/.config dir !"); } @@ -707,7 +616,7 @@ pub fn init_logger(profile: &str, soft_name: &'static str, cli_args: &ArgMatches log_file_path.push(format!("{}.log", soft_name)); // Get log level - let log_level = match cli_args.value_of("logs").unwrap_or("i") { + let log_level = match cli_args.value_of("logs_level").unwrap_or("i") { "e" | "error" => Level::Error, "w" | "warn" => Level::Warn, "i" | "info" => Level::Info, @@ -731,7 +640,8 @@ pub fn init_logger(profile: &str, soft_name: &'static str, cli_args: &ArgMatches log_file_path .to_str() .expect("Fatal error : fail to get log file path !"), - ).expect("Fatal error : fail to create log file path !"); + ) + .expect("Fatal error : fail to create log file path !"); } CombinedLogger::init(vec![WriteLogger::new( @@ -744,6 +654,10 @@ pub fn init_logger(profile: &str, soft_name: &'static str, cli_args: &ArgMatches log_file_path .to_str() .expect("Fatal error : fail to get log file path !"), - ).expect("Fatal error : fail to open log file !"), - )]).expect("Fatal error : fail to init logger !"); + ) + .expect("Fatal error : fail to open log file !"), + )]) + .expect("Fatal error : fail to init logger !"); + + info!("Successfully init logger"); } diff --git a/core/rooter.rs b/core/rooter.rs new file mode 100644 index 0000000000000000000000000000000000000000..2eab64f2a8360d68f0501e481ccb79332a13f374 --- /dev/null +++ b/core/rooter.rs @@ -0,0 +1,390 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Relay messages between durs modules. + +use duniter_message::*; +use duniter_module::*; +use std::collections::HashMap; +use std::sync::mpsc; +use std::sync::mpsc::RecvTimeoutError; +use std::thread; +use std::time::Duration; +use std::time::SystemTime; + +/// Start broadcasting thread +fn start_broadcasting_thread( + start_time: SystemTime, + run_duration_in_secs: u64, + receiver: &mpsc::Receiver<RooterThreadMessage<DursMsg>>, + external_followers: &[mpsc::Sender<DursMsgContent>], +) { + // Define variables + let mut modules_senders: HashMap<ModuleStaticName, mpsc::Sender<DursMsg>> = HashMap::new(); + let mut pool_msgs: HashMap<DursMsgReceiver, Vec<DursMsgContent>> = HashMap::new(); + let mut events_subscriptions: HashMap<ModuleEvent, Vec<ModuleStaticName>> = HashMap::new(); + let mut roles: HashMap<ModuleRole, Vec<ModuleStaticName>> = HashMap::new(); + + loop { + match receiver.recv_timeout(Duration::from_secs(1)) { + Ok(mess) => { + match mess { + RooterThreadMessage::ModuleSender( + module_static_name, + module_sender, + sender_roles, + events_subscription, + ) => { + // For all events + for event in events_subscription { + // Send pending message of this event + for msg in pool_msgs + .get(&DursMsgReceiver::Event(event)) + .unwrap_or(&Vec::with_capacity(0)) + { + module_sender + .send(DursMsg(DursMsgReceiver::Event(event), msg.clone())) + .unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } + // Store event subscription + events_subscriptions + .entry(event) + .or_insert_with(Vec::new) + .push(module_static_name); + } + // For all roles + for role in sender_roles { + // Send pending message for this role + for msg in pool_msgs + .get(&DursMsgReceiver::Role(role)) + .unwrap_or(&Vec::with_capacity(0)) + { + module_sender + .send(DursMsg(DursMsgReceiver::Role(role), msg.clone())) + .unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } + // Store sender roles + roles + .entry(role) + .or_insert_with(Vec::new) + .push(module_static_name); + } + // Add this sender to modules_senders + modules_senders.insert(module_static_name, module_sender); + } + RooterThreadMessage::ModuleMessage(msg) => match msg.0 { + DursMsgReceiver::One(_) => {} + DursMsgReceiver::All => { + for (module_static_name, module_sender) in &modules_senders { + module_sender.send(msg.clone()).unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } + // Detect stop message + let stop = if let DursMsgContent::Stop() = msg.1 { + true + } else { + false + }; + // Send message to external followers + for external_follower in external_followers { + external_follower.send(msg.1.clone()).expect( + "Fatal error: fail to relay DursMsg to external followers !", + ); + } + // Send message to all modules + send_msg_to_several_receivers( + msg, + &modules_senders + .keys() + .cloned() + .collect::<Vec<ModuleStaticName>>(), + &modules_senders, + ); + // Stop thread if its requested + if stop { + break; + } + } + DursMsgReceiver::Event(event) => { + // the node to be started less than 20 seconds ago, + // keep the message in memory to be able to send it back to modules not yet plugged + store_msg_in_pool( + start_time, + run_duration_in_secs, + msg.clone(), + &mut pool_msgs, + ); + // Get list of receivers + let receivers = events_subscriptions + .get(&event) + .unwrap_or(&Vec::with_capacity(0)) + .to_vec(); + // Send msg to receivers + send_msg_to_several_receivers(msg, &receivers, &modules_senders) + } + DursMsgReceiver::Role(role) => { + // If the node to be started less than 20 seconds ago, + // keep the message in memory to be able to send it back to modules not yet plugged + store_msg_in_pool( + start_time, + run_duration_in_secs, + msg.clone(), + &mut pool_msgs, + ); + // Get list of receivers + let receivers = + roles.get(&role).unwrap_or(&Vec::with_capacity(0)).to_vec(); + // Send msg to receivers + send_msg_to_several_receivers(msg, &receivers, &modules_senders) + } + }, + } + } + Err(e) => match e { + RecvTimeoutError::Timeout => continue, + RecvTimeoutError::Disconnected => { + panic!("Fatal error : rooter thread disconnnected !") + } + }, + } + } +} + +/// Send msg to several receivers +fn send_msg_to_several_receivers( + msg: DursMsg, + receivers: &[ModuleStaticName], + modules_senders: &HashMap<ModuleStaticName, mpsc::Sender<DursMsg>>, +) { + // Send message by copy To all modules that subscribed to this event + for module_static_name in &receivers[1..] { + if let Some(module_sender) = modules_senders.get(module_static_name) { + module_sender.send(msg.clone()).unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } + } + // Send message by move to the last module to be revceive + if !receivers.is_empty() { + if let Some(module_sender) = modules_senders.get(&receivers[0]) { + module_sender.send(msg).unwrap_or_else(|_| { + panic!("Fatal error: fail to relay DursMsg to {:?} !", receivers[0]) + }); + } + } +} + +/// If the node to be started less than 20 seconds ago, +/// keep the message in memory to be able to send it back to modules not yet plugged +fn store_msg_in_pool( + start_time: SystemTime, + run_duration_in_secs: u64, + msg: DursMsg, + pool_msgs: &mut HashMap<DursMsgReceiver, Vec<DursMsgContent>>, +) { + if run_duration_in_secs > 0 + && SystemTime::now() + .duration_since(start_time) + .expect("Duration error !") + .as_secs() + < 20 + { + pool_msgs.entry(msg.0).or_insert_with(Vec::new).push(msg.1); + } else if !pool_msgs.is_empty() { + // Clear pool_msgs + pool_msgs.clear(); + } +} + +/// Start rooter thread +pub fn start_rooter<DC: DuniterConf>( + run_duration_in_secs: u64, + external_followers: Vec<mpsc::Sender<DursMsgContent>>, +) -> mpsc::Sender<RooterThreadMessage<DursMsg>> { + let start_time = SystemTime::now(); + + // Create rooter channel + let (rooter_sender, rooter_receiver): ( + mpsc::Sender<RooterThreadMessage<DursMsg>>, + mpsc::Receiver<RooterThreadMessage<DursMsg>>, + ) = mpsc::channel(); + + // Create rooter thread + thread::spawn(move || { + // Create broadcasting thread channel + let (broadcasting_sender, broadcasting_receiver): ( + mpsc::Sender<RooterThreadMessage<DursMsg>>, + mpsc::Receiver<RooterThreadMessage<DursMsg>>, + ) = mpsc::channel(); + + // Create broadcasting thread + thread::spawn(move || { + start_broadcasting_thread( + start_time, + run_duration_in_secs, + &broadcasting_receiver, + &external_followers, + ); + }); + + // Define variables + let mut modules_senders: HashMap<ModuleStaticName, mpsc::Sender<DursMsg>> = HashMap::new(); + let mut pool_msgs: HashMap<ModuleStaticName, Vec<DursMsgContent>> = HashMap::new(); + + // Wait to receiver modules senders + loop { + match rooter_receiver.recv_timeout(Duration::from_secs(1)) { + Ok(mess) => { + match mess { + RooterThreadMessage::ModuleSender( + module_static_name, + module_sender, + events_subscription, + sender_roles, + ) => { + // Send pending messages destined specifically to this module + if let Some(msgs) = pool_msgs.remove(&module_static_name) { + for msg in msgs { + module_sender + .send(DursMsg( + DursMsgReceiver::One(module_static_name), + msg, + )) + .unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } + } + // Add this sender to modules_senders + modules_senders.insert(module_static_name, module_sender.clone()); + // Relay to broadcasting thread + broadcasting_sender + .send(RooterThreadMessage::ModuleSender( + module_static_name, + module_sender, + events_subscription, + sender_roles, + )) + .expect("Fail to relay message to broadcasting thread !"); + // Log the number of modules_senders received + info!( + "Rooter thread receive {} module senders", + modules_senders.len() + ); + } + RooterThreadMessage::ModuleMessage(msg) => { + trace!("Rooter thread receive ModuleMessage({:?})", msg); + match msg.0 { + DursMsgReceiver::All => { + let stop = if let DursMsgContent::Stop() = msg.1 { + true + } else { + false + }; + broadcasting_sender + .send(RooterThreadMessage::ModuleMessage(msg)) + .expect("Fail to relay message to broadcasting thread !"); + if stop { + break; + } + } + DursMsgReceiver::Role(_module_role) => broadcasting_sender + .send(RooterThreadMessage::ModuleMessage(msg)) + .expect("Fail to relay message to broadcasting thread !"), + DursMsgReceiver::Event(_module_event) => broadcasting_sender + .send(RooterThreadMessage::ModuleMessage(msg)) + .expect("Fail to relay message to broadcasting thread !"), + DursMsgReceiver::One(module_static_name) => { + if let Some(module_sender) = + modules_senders.get(&module_static_name) + { + module_sender.send(msg).unwrap_or_else(|_| { + panic!( + "Fatal error: fail to relay DursMsg to {:?} !", + module_static_name + ) + }); + } else if SystemTime::now() + .duration_since(start_time) + .expect("Duration error !") + .as_secs() + < 20 + { + pool_msgs + .entry(module_static_name) + .or_insert_with(Vec::new) + .push(msg.1); + } else { + if !pool_msgs.is_empty() { + pool_msgs = HashMap::with_capacity(0); + } + warn!( + "Message for unknow receiver : {:?}.", + module_static_name + ); + } + } + } + } + } + } + Err(e) => match e { + RecvTimeoutError::Timeout => continue, + RecvTimeoutError::Disconnected => { + panic!("Fatal error : rooter thread disconnnected !") + } + }, + } + if run_duration_in_secs > 0 + && SystemTime::now() + .duration_since(start_time) + .expect("Duration error !") + .as_secs() + > run_duration_in_secs + { + broadcasting_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::All, + DursMsgContent::Stop(), + ))) + .expect("Fail to relay stop message to broadcasting thread !"); + break; + } + } + info!("Rooter thread stop.") + }); + + rooter_sender +} diff --git a/crypto/keys/bin_signable.rs b/crypto/keys/bin_signable.rs index 3c572131ba63f4659149dd725f96f5c5165c08ad..40d2055b10eea22b39adf8112f9fe614355b5c61 100644 --- a/crypto/keys/bin_signable.rs +++ b/crypto/keys/bin_signable.rs @@ -90,7 +90,6 @@ pub trait BinSignable<'de>: Serialize + Deserialize<'de> { } else { self.compute_hash()? }; - println!("DEBUG: verified hash={:?}", hash.0); if pubkey.verify(&hash.0, &sig) { Ok(()) } else { diff --git a/crypto/keys/ed25519.rs b/crypto/keys/ed25519.rs index 3e36cc38d0b620963b1a67e02d1173dcfb5924d6..a3dda669133b7f03147d929af4571d75211d9488 100644 --- a/crypto/keys/ed25519.rs +++ b/crypto/keys/ed25519.rs @@ -66,11 +66,11 @@ impl<'de> Deserialize<'de> for Signature { where D: Deserializer<'de>, { - struct ArrayVisitor<u8> { + struct ArrayVisitor { element: PhantomData<u8>, } - impl<'de, u8> Visitor<'de> for ArrayVisitor<u8> { + impl<'de> Visitor<'de> for ArrayVisitor { type Value = Signature; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { @@ -91,7 +91,7 @@ impl<'de> Deserialize<'de> for Signature { } } - let visitor: ArrayVisitor<u8> = ArrayVisitor { + let visitor: ArrayVisitor = ArrayVisitor { element: PhantomData, }; deserializer.deserialize_tuple(64, visitor) @@ -478,13 +478,15 @@ mod tests { assert_eq!( super::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9", - ).unwrap_err(), + ) + .unwrap_err(), BaseConvertionError::InvalidKeyLendth(53, 64) ); assert_eq!( super::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9<<", - ).unwrap_err(), + ) + .unwrap_err(), BaseConvertionError::InvalidCharacter('<', 73) ); } @@ -538,14 +540,16 @@ mod tests { super::Signature::from_base64( "YmhlaW9iaHNlcGlvaGVvaXNlcGl2ZXBvdm5pc2V2c2JlaW9idmVpb3Zqc\ 2V2Z3BpaHNlamVwZ25qZXNqb2dwZWpnaW9zZXNkdnNic3JicmJyZGJyZGI=", - ).unwrap_err(), + ) + .unwrap_err(), BaseConvertionError::InvalidKeyLendth(86, 64) ); assert_eq!( super::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\ mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAgdha<<", - ).unwrap_err(), + ) + .unwrap_err(), BaseConvertionError::InvalidCharacter('<', 89) ); } @@ -558,12 +562,14 @@ mod tests { let prikey = super::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt\ 5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7", - ).unwrap(); + ) + .unwrap(); let expected_signature = super::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FG\ MMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", - ).unwrap(); + ) + .unwrap(); let message = "Version: 10 Type: Identity diff --git a/crypto/keys/mod.rs b/crypto/keys/mod.rs index b110b95eb32c5c7d91bca71f7732eccb0231a8cb..02eeab5d0e28a917e9a282b061b43824350b34df 100644 --- a/crypto/keys/mod.rs +++ b/crypto/keys/mod.rs @@ -286,11 +286,13 @@ impl PublicKey for PubKey { } fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool { match *self { - PubKey::Ed25519(ed25519_pubkey) => if let Sig::Ed25519(ed25519_sig) = signature { - ed25519_pubkey.verify(message, ed25519_sig) - } else { - panic!("Try to verify a signature with public key of a different algorithm !\nSignature={:?}\nPublickey={:?}", signature, self) - }, + PubKey::Ed25519(ed25519_pubkey) => { + if let Sig::Ed25519(ed25519_sig) = signature { + ed25519_pubkey.verify(message, ed25519_sig) + } else { + panic!("Try to verify a signature with public key of a different algorithm !\nSignature={:?}\nPublickey={:?}", signature, self) + } + } PubKey::Schnorr() => panic!("Schnorr algo not yet supported !"), } } @@ -440,11 +442,13 @@ impl KeyPair for KeyPairEnum { } fn verify(&self, message: &[u8], signature: &Sig) -> bool { match *self { - KeyPairEnum::Ed25519(ed25519_keypair) => if let Sig::Ed25519(ed25519_sig) = signature { - ed25519_keypair.verify(message, ed25519_sig) - } else { - panic!("Try to verify a signature with key pair of a different algorithm !\nSignature={:?}\nKeyPair={:?}", signature, self) - }, + KeyPairEnum::Ed25519(ed25519_keypair) => { + if let Sig::Ed25519(ed25519_sig) = signature { + ed25519_keypair.verify(message, ed25519_sig) + } else { + panic!("Try to verify a signature with key pair of a different algorithm !\nSignature={:?}\nKeyPair={:?}", signature, self) + } + } KeyPairEnum::Schnorr() => panic!("Schnorr algo not yet supported !"), } } diff --git a/crypto/lib.rs b/crypto/lib.rs index 3620eb994bb08f6ec328d1e3aa412e0b2418d565..c478012c6ae72a63dad28079f775c0bccaf3a2f7 100644 --- a/crypto/lib.rs +++ b/crypto/lib.rs @@ -16,7 +16,6 @@ //! Provide wrappers for cryptographic building blocks used by Duniter. #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(builtin_type_shadow))] #![deny( missing_docs, missing_debug_implementations, diff --git a/dal/block.rs b/dal/block.rs index 532aa9f3bf5bea74d150d03b7d036e8360ba4af5..8ca38a5388f0b3b7e21a325c3bed44d3bf363670 100644 --- a/dal/block.rs +++ b/dal/block.rs @@ -392,7 +392,7 @@ impl DALBlock { median_index = self.block.issuers_count - 1; } self.median_frame = current_frame_vec[median_index]; - + // Calculate second tiercile index let mut second_tiercile_index = match self.block.issuers_count % 3 { 1 | 2 => (self.block.issuers_count as f64 * (2.0 / 3.0)) as usize + 1, diff --git a/dal/dal_requests.rs b/dal/dal_requests.rs index bc90b8c90f8980a422ee1026eded82ee347785d7..52fc8383f1bacf147dad27372376629fd7d3951d 100644 --- a/dal/dal_requests.rs +++ b/dal/dal_requests.rs @@ -16,7 +16,7 @@ extern crate duniter_module; extern crate serde; -use self::duniter_module::ModuleReqFullId; +use self::duniter_module::ModuleReqId; use duniter_crypto::hashs::Hash; use duniter_crypto::keys::*; use duniter_documents::blockchain::v10::documents::{ @@ -25,26 +25,26 @@ use duniter_documents::blockchain::v10::documents::{ use duniter_documents::Blockstamp; use std::collections::HashMap; -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] /// Inter-module DAL request for pool data pub enum DALReqPendings { /// All pending identities with their pending certifications - AllPendingIdentities(ModuleReqFullId, usize), + AllPendingIdentities(usize), /// All pending identities without their pending certifications - AllPendingIdentitiesWithoutCerts(ModuleReqFullId, usize), + AllPendingIdentitiesWithoutCerts(usize), /// All pending datas for given pubkey - PendingWotDatasForPubkey(ModuleReqFullId, PubKey), + PendingWotDatasForPubkey(PubKey), } #[derive(Debug, Clone, PartialEq)] /// Inter-module DAL request for blockchain data pub enum DALReqBlockchain { /// Current block - CurrentBlock(ModuleReqFullId), + CurrentBlock(), /// Block by number - BlockByNumber(ModuleReqFullId, u64), + BlockByNumber(u64), /// Chunk (block pack) - Chunk(ModuleReqFullId, u64, usize), + Chunk(u64, usize), /// Usernames corresponding to the public keys in parameter UIDs(Vec<PubKey>), } @@ -77,24 +77,24 @@ pub struct PendingIdtyDatas { /// Response to a DALReqPendings request pub enum DALResPendings { /// All pending identities with their pending certifications - AllPendingIdentities(HashMap<Hash, PendingIdtyDatas>), + AllPendingIdentities(ModuleReqId, HashMap<Hash, PendingIdtyDatas>), /// All pending identities without their pending certifications - AllPendingIdentitiesWithoutCerts(HashMap<Hash, PendingIdtyDatas>), + AllPendingIdentitiesWithoutCerts(ModuleReqId, HashMap<Hash, PendingIdtyDatas>), /// All pending datas for given pubkey - PendingWotDatasForPubkey(Box<PendingIdtyDatas>), + PendingWotDatasForPubkey(ModuleReqId, Box<PendingIdtyDatas>), } #[derive(Debug, Clone)] /// Response to a DALReqBlockchain request pub enum DALResBlockchain { /// Current block - CurrentBlock(ModuleReqFullId, Box<BlockDocument>, Blockstamp), + CurrentBlock(ModuleReqId, Box<BlockDocument>, Blockstamp), /// Block by number - BlockByNumber(ModuleReqFullId, Box<BlockDocument>), + BlockByNumber(ModuleReqId, Box<BlockDocument>), /// Chunk (block pack) - Chunk(ModuleReqFullId, Vec<BlockDocument>), + Chunk(ModuleReqId, Vec<BlockDocument>), /// Usernames corresponding to the public keys in parameter - UIDs(HashMap<PubKey, Option<String>>), + UIDs(ModuleReqId, HashMap<PubKey, Option<String>>), } #[derive(Debug, Clone)] @@ -103,5 +103,5 @@ pub enum DALResponse { /// Response to a DALReqBlockchain request Blockchain(Box<DALResBlockchain>), /// Response to a DALReqPendings request - Pendings(ModuleReqFullId, Box<DALResPendings>), + Pendings(Box<DALResPendings>), } diff --git a/dal/identity.rs b/dal/identity.rs index c2af1aca008d66967f1ecb330c539bb596949234..03467a869814d51c3314612337b4d8791b9b1880 100644 --- a/dal/identity.rs +++ b/dal/identity.rs @@ -170,11 +170,13 @@ impl DALIdentity { DALIdentityState::ExpireMember(renewed_counts) => { DALIdentityState::ExplicitExpireRevoked(renewed_counts) } - DALIdentityState::Member(renewed_counts) => if explicit { - DALIdentityState::ExplicitRevoked(renewed_counts) - } else { - DALIdentityState::ImplicitRevoked(renewed_counts) - }, + DALIdentityState::Member(renewed_counts) => { + if explicit { + DALIdentityState::ExplicitRevoked(renewed_counts) + } else { + DALIdentityState::ImplicitRevoked(renewed_counts) + } + } _ => panic!("Try to revert revoke an already revoked idty !"), } }; diff --git a/dal/lib.rs b/dal/lib.rs index d7c837568b80907c8b6786a76c9e01934ab8e166..853442a607d310b8b10a2445ec0b2aa986d4d414 100644 --- a/dal/lib.rs +++ b/dal/lib.rs @@ -16,7 +16,7 @@ //! Datas Access Layer #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] +//#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] #![cfg_attr(feature = "exp", allow(warnings))] #![deny( missing_docs, diff --git a/dal/tools.rs b/dal/tools.rs index 43950523ac4bbf8c05e19257e10be6311fc0e6d0..b3509912f6ec8d926565c071b81537cc5690dcda 100644 --- a/dal/tools.rs +++ b/dal/tools.rs @@ -113,7 +113,8 @@ pub fn compute_distances<T: WebOfTrust + Sync>( step_max, x_percent, }, - ).expect("Fatal Error: compute_distance return None !"); + ) + .expect("Fatal Error: compute_distance return None !"); let mut distance = ((f64::from(distance_datas.success) / (x_percent * f64::from(distance_datas.sentries))) * 100.0) as usize; diff --git a/dal/writers/block.rs b/dal/writers/block.rs index 03c556722c7814e9ebbc790eb59c08b10b8ae4ee..d447ad41666b55d09ebb301e736b9c21a422b59a 100644 --- a/dal/writers/block.rs +++ b/dal/writers/block.rs @@ -101,7 +101,8 @@ pub fn write( forks_db .write(|db| { db.insert(ForkId(0), blockchain_meta_datas); - }).expect("Write blockchain meta datas : DALError"); + }) + .expect("Write blockchain meta datas : DALError"); } Ok(()) } diff --git a/dal/writers/dividend.rs b/dal/writers/dividend.rs index e5d64193c7dbf4de63ca53b7cb80fcc07d9bc021..648240fbecc6b8c7d9b86a8a99efe78f3b87d9d3 100644 --- a/dal/writers/dividend.rs +++ b/dal/writers/dividend.rs @@ -50,7 +50,8 @@ pub fn create_du( *pubkey, db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(*pubkey), - )).cloned() + )) + .cloned() .unwrap_or_default(), ); } @@ -66,7 +67,8 @@ pub fn create_du( *balance + *du_amount }; (*pubkey, (new_balance, utxos_indexs.clone())) - }).collect(); + }) + .collect(); // Write new members balance balances_db.write(|db| { for (pubkey, (balance, utxos_indexs)) in members_balances { diff --git a/dal/writers/transaction.rs b/dal/writers/transaction.rs index 634c471d9e7cd51dc88400239a4d1af9bd0c93b3..6fb57faaef3608f834048fe83d7b136b36b31cfb 100644 --- a/dal/writers/transaction.rs +++ b/dal/writers/transaction.rs @@ -141,7 +141,8 @@ pub fn revert_tx(dbs: &CurrencyV10DBs, dal_tx: &DALTxV10) -> Result<(), DALError SourceIndexV10::UTXO(UTXOIndexV10(hash, tx_index)), SourceAmount(tx_amout, tx_amout_base), ), - }).collect(); + }) + .collect(); // Find adress of recreated sources let recreated_adress: HashMap<UTXOConditionsGroup, (SourceAmount, HashSet<UTXOIndexV10>)> = dbs.utxos_db.read(|db| { @@ -256,7 +257,8 @@ pub fn apply_and_write_tx( SourceIndexV10::UTXO(UTXOIndexV10(hash, tx_index)), SourceAmount(tx_amout, tx_amout_base), ), - }).collect(); + }) + .collect(); // Find adress of consumed sources let consumed_adress: HashMap<UTXOConditionsGroup, (SourceAmount, HashSet<UTXOIndexV10>)> = dbs.utxos_db.read(|db| { @@ -423,7 +425,8 @@ mod tests { ).unwrap()); let block = Blockstamp::from_string( "50-00001DAA4559FEDB8320D1040B0F22B631459F36F237A0D9BC1EB923C12A12E7", - ).unwrap(); + ) + .unwrap(); let builder = TransactionDocumentBuilder { currency: "g1", blockstamp: &block, @@ -432,7 +435,8 @@ mod tests { inputs: &vec![ TransactionInput::parse_from_str( "1000:0:D:2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ:1", - ).expect("fail to parse input !"), + ) + .expect("fail to parse input !"), ], unlocks: &vec![ TransactionInputUnlocks::parse_from_str("0:SIG(0)") @@ -441,10 +445,12 @@ mod tests { outputs: &vec![ TransactionOutput::parse_from_str( "1:0:SIG(Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm)", - ).expect("fail to parse output !"), + ) + .expect("fail to parse output !"), TransactionOutput::parse_from_str( "999:0:SIG(2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ)", - ).expect("fail to parse output !"), + ) + .expect("fail to parse output !"), ], comment: "TEST", hash: None, @@ -472,15 +478,18 @@ mod tests { BlockId(1), &vec![tx_doc.issuers()[0], tortue_pubkey], false, - ).expect("Fail to create first g1 UD !"); + ) + .expect("Fail to create first g1 UD !"); // Check members balance let cgeek_new_balance = currency_dbs .balances_db .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tx_doc.issuers()[0]), - )).cloned() - }).expect("Fail to read cgeek new balance") + )) + .cloned() + }) + .expect("Fail to read cgeek new balance") .expect("Error : cgeek is not referenced in balances_db !"); assert_eq!(cgeek_new_balance.0, SourceAmount(TxAmount(1000), TxBase(0))); let tortue_new_balance = currency_dbs @@ -488,8 +497,10 @@ mod tests { .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tortue_pubkey), - )).cloned() - }).expect("Fail to read receiver new balance") + )) + .cloned() + }) + .expect("Fail to read receiver new balance") .expect("Error : receiver is not referenced in balances_db !"); assert_eq!( tortue_new_balance.0, @@ -503,8 +514,10 @@ mod tests { .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tx_doc.issuers()[0]), - )).cloned() - }).expect("Fail to read cgeek new balance") + )) + .cloned() + }) + .expect("Fail to read cgeek new balance") .expect("Error : cgeek is not referenced in balances_db !"); assert_eq!(cgeek_new_balance.0, SourceAmount(TxAmount(999), TxBase(0))); @@ -514,8 +527,10 @@ mod tests { .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tortue_pubkey), - )).cloned() - }).expect("Fail to read receiver new balance") + )) + .cloned() + }) + .expect("Fail to read receiver new balance") .expect("Error : receiver is not referenced in balances_db !"); assert_eq!( receiver_new_balance.0, @@ -529,7 +544,8 @@ mod tests { tx_doc: tx_doc.clone(), sources_destroyed: HashSet::with_capacity(0), }, - ).expect("Fail to revert first g1 tx"); + ) + .expect("Fail to revert first g1 tx"); // Check issuer new balance let cgeek_new_balance = currency_dbs @@ -537,8 +553,10 @@ mod tests { .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tx_doc.issuers()[0]), - )).cloned() - }).expect("Fail to read cgeek new balance") + )) + .cloned() + }) + .expect("Fail to read cgeek new balance") .expect("Error : cgeek is not referenced in balances_db !"); assert_eq!(cgeek_new_balance.0, SourceAmount(TxAmount(1000), TxBase(0))); @@ -548,8 +566,10 @@ mod tests { .read(|db| { db.get(&UTXOConditionsGroup::Single( TransactionOutputCondition::Sig(tortue_pubkey), - )).cloned() - }).expect("Fail to read receiver new balance") + )) + .cloned() + }) + .expect("Fail to read receiver new balance") .expect("Error : receiver is not referenced in balances_db !"); assert_eq!( receiver_new_balance.0, diff --git a/documents/blockchain/mod.rs b/documents/blockchain/mod.rs index 4ddea4f316c2dcbec5c72265242e2da8d3e1bdfd..64edf826a48de9a18793acf829dde9dd8735e0bd 100644 --- a/documents/blockchain/mod.rs +++ b/documents/blockchain/mod.rs @@ -202,7 +202,8 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 ed25519::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\ mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", - ).unwrap(), + ) + .unwrap(), ); // incorrect pair @@ -215,7 +216,8 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 ed25519::Signature::from_base64( "1eubHHbuNfilHHH0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\ mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", - ).unwrap(), + ) + .unwrap(), ); { diff --git a/documents/blockchain/v10/documents/certification.rs b/documents/blockchain/v10/documents/certification.rs index 0d2b889e0f0dd89cee75dc4ab0904af685a7b93c..e03213f00917646239df20f8d8270860efa8c172 100644 --- a/documents/blockchain/v10/documents/certification.rs +++ b/documents/blockchain/v10/documents/certification.rs @@ -301,7 +301,8 @@ mod tests { let identity_blockstamp = Blockstamp::from_string( "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", - ).unwrap(); + ) + .unwrap(); let identity_sig = Sig::Ed25519(ed25519::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", @@ -309,7 +310,8 @@ mod tests { let blockstamp = Blockstamp::from_string( "36-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B865", - ).unwrap(); + ) + .unwrap(); let builder = CertificationDocumentBuilder { currency: "duniter_unit_test_currency", @@ -378,11 +380,11 @@ CertTimestamp: 167884-0001DFCA28002A8C96575E53B8CEF8317453A7B0BA255542CCF0EC8AB5 println!("Doc : {:?}", doc); assert_eq!(doc.verify_signatures(), VerificationResult::Valid()); /*assert_eq!( - doc.generate_compact_text(), - "2sZF6j2PkxBDNAqUde7Dgo5x3crkerZpQ4rBqqJGn8QT:\ - 7jzkd8GiFnpys4X7mP78w2Y3y3kwdK6fVSLEaojd3aH9:99956:\ - Hkps1QU4HxIcNXKT8YmprYTVByBhPP1U2tIM7Z8wENzLKIWAvQClkAvBE7pW9dnVa18sJIJhVZUcRrPAZfmjBA==" - );*/ + doc.generate_compact_text(), + "2sZF6j2PkxBDNAqUde7Dgo5x3crkerZpQ4rBqqJGn8QT:\ + 7jzkd8GiFnpys4X7mP78w2Y3y3kwdK6fVSLEaojd3aH9:99956:\ + Hkps1QU4HxIcNXKT8YmprYTVByBhPP1U2tIM7Z8wENzLKIWAvQClkAvBE7pW9dnVa18sJIJhVZUcRrPAZfmjBA==" + );*/ } else { panic!("Wrong document type"); } diff --git a/documents/blockchain/v10/documents/identity.rs b/documents/blockchain/v10/documents/identity.rs index efa612facf7dca786bd8a87c2588a8305a94b949..4eacf71e517e38cf909d46a1c5ccc4ef4a621dfc 100644 --- a/documents/blockchain/v10/documents/identity.rs +++ b/documents/blockchain/v10/documents/identity.rs @@ -254,19 +254,22 @@ mod tests { ed25519::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5G\ iERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7", - ).unwrap(), + ) + .unwrap(), ); let sig = Sig::Ed25519( ed25519::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGM\ MmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", - ).unwrap(), + ) + .unwrap(), ); let block = Blockstamp::from_string( "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", - ).unwrap(); + ) + .unwrap(); let builder = IdentityDocumentBuilder { currency: "duniter_unit_test_currency", diff --git a/documents/blockchain/v10/documents/membership.rs b/documents/blockchain/v10/documents/membership.rs index 2d30391a8c2431b6e5f6ef6665bb7cc3e88bda5f..3e3fb554a114a3b3bca72af5167c073e4795680a 100644 --- a/documents/blockchain/v10/documents/membership.rs +++ b/documents/blockchain/v10/documents/membership.rs @@ -29,7 +29,8 @@ lazy_static! { Membership: (?P<membership>(IN|OUT))\n\ UserID: (?P<ity_user>[[:alnum:]_-]+)\n\ CertTS: (?P<ity_block>[0-9]+-[0-9A-F]{64})\n$" - ).unwrap(); + ) + .unwrap(); } /// Type of a Membership. @@ -320,19 +321,22 @@ mod tests { ed25519::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5G\ iERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7", - ).unwrap(), + ) + .unwrap(), ); let sig = Sig::Ed25519( ed25519::Signature::from_base64( "s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkEl\ AyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw==", - ).unwrap(), + ) + .unwrap(), ); let block = Blockstamp::from_string( "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", - ).unwrap(); + ) + .unwrap(); let builder = MembershipDocumentBuilder { currency: "duniter_unit_test_currency", diff --git a/documents/blockchain/v10/documents/mod.rs b/documents/blockchain/v10/documents/mod.rs index 1cb541650b0479fc316bee80c4a27391db113044..3e3d2137834cf3b39e400e49c0858e4b84306538 100644 --- a/documents/blockchain/v10/documents/mod.rs +++ b/documents/blockchain/v10/documents/mod.rs @@ -49,7 +49,8 @@ lazy_static! { Currency: (?P<currency>[[:alnum:] _-]+)\n\ (?P<body>(?:.*\n)+?))\ (?P<sigs>([[:alnum:]+/=]+\n)*([[:alnum:]+/=]+))$" - ).unwrap(); + ) + .unwrap(); static ref SIGNATURES_REGEX: Regex = Regex::new("[[:alnum:]+/=]+\n?").unwrap(); } @@ -321,7 +322,8 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r 2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX 2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk" - ).count(), + ) + .count(), 3 ); @@ -331,7 +333,8 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN " 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r 2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk" - ).count(), + ) + .count(), 2 ); } diff --git a/documents/blockchain/v10/documents/revocation.rs b/documents/blockchain/v10/documents/revocation.rs index 41032871f1e1a3236e62e31d4b86906057162a40..2b059615dd288fe146d215be1dfb0bbe1382554c 100644 --- a/documents/blockchain/v10/documents/revocation.rs +++ b/documents/blockchain/v10/documents/revocation.rs @@ -252,7 +252,8 @@ mod tests { ed25519::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5G\ iERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7", - ).unwrap(), + ) + .unwrap(), ); let sig = Sig::Ed25519(ed25519::Signature::from_base64( @@ -261,7 +262,8 @@ mod tests { let identity_blockstamp = Blockstamp::from_string( "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", - ).unwrap(); + ) + .unwrap(); let identity_sig = Sig::Ed25519(ed25519::Signature::from_base64( "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==", diff --git a/documents/blockchain/v10/documents/transaction.rs b/documents/blockchain/v10/documents/transaction.rs index 30b0207acc95b7e366f3736b2f0b677fdb3866ab..94006b10d83835b2bff23022c92aeffeaa6d087c 100644 --- a/documents/blockchain/v10/documents/transaction.rs +++ b/documents/blockchain/v10/documents/transaction.rs @@ -825,7 +825,8 @@ mod tests { ed25519::PrivateKey::from_base58( "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5G\ iERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7", - ).unwrap(), + ) + .unwrap(), ); let sig = Sig::Ed25519(ed25519::Signature::from_base64( @@ -834,7 +835,8 @@ mod tests { let block = Blockstamp::from_string( "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", - ).unwrap(); + ) + .unwrap(); let builder = TransactionDocumentBuilder { currency: "duniter_unit_test_currency", @@ -844,7 +846,8 @@ mod tests { inputs: &vec![ TransactionInput::parse_from_str( "10:0:D:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:0", - ).expect("fail to parse input !"), + ) + .expect("fail to parse input !"), ], unlocks: &vec![ TransactionInputUnlocks::parse_from_str("0:SIG(0)") @@ -853,7 +856,8 @@ mod tests { outputs: &vec![ TransactionOutput::parse_from_str( "10:0:SIG(FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa)", - ).expect("fail to parse output !"), + ) + .expect("fail to parse output !"), ], comment: "test", hash: None, @@ -885,7 +889,8 @@ mod tests { let block = Blockstamp::from_string( "60-00001FE00410FCD5991EDD18AA7DDF15F4C8393A64FA92A1DB1C1CA2E220128D", - ).unwrap(); + ) + .unwrap(); let builder = TransactionDocumentBuilder { currency: "g1", @@ -895,7 +900,8 @@ mod tests { inputs: &vec![ TransactionInput::parse_from_str( "950:0:T:2CF1ACD8FE8DC93EE39A1D55881C50D87C55892AE8E4DB71D4EBAB3D412AA8FD:1", - ).expect("fail to parse input !"), + ) + .expect("fail to parse input !"), ], unlocks: &vec![ TransactionInputUnlocks::parse_from_str("0:SIG(0)") @@ -904,10 +910,12 @@ mod tests { outputs: &vec![ TransactionOutput::parse_from_str( "30:0:SIG(38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE)", - ).expect("fail to parse output !"), + ) + .expect("fail to parse output !"), TransactionOutput::parse_from_str( "920:0:SIG(FEkbc4BfJukSWnCU6Hed6dgwwTuPFTVdgz5LpL4iHr9J)", - ).expect("fail to parse output !"), + ) + .expect("fail to parse output !"), ], comment: "Pour cesium merci", hash: None, diff --git a/message/lib.rs b/message/lib.rs index b4bc903f3361139e416e199d6cb3c1ea6bdfbfcc..c2143f494df34a1343bd7dd6a9955490963562bf 100644 --- a/message/lib.rs +++ b/message/lib.rs @@ -37,40 +37,55 @@ extern crate duniter_network; extern crate serde; extern crate serde_json; -use std::sync::mpsc; - use duniter_crypto::hashs::Hash; use duniter_crypto::keys::Sig; use duniter_dal::dal_event::DALEvent; use duniter_dal::dal_requests::{DALRequest, DALResponse}; use duniter_documents::blockchain::BlockchainProtocol; use duniter_documents::BlockId; -use duniter_module::{ModuleId, ModuleMessage}; -use duniter_network::{NetworkEvent, NetworkRequest}; +use duniter_module::*; +use duniter_network::{NetworkEvent, NetworkResponse, OldNetworkRequest}; + +#[derive(Debug, Clone)] +/// Message exchanged between Durs modules +pub struct DursMsg(pub DursMsgReceiver, pub DursMsgContent); + +impl ModuleMessage for DursMsg {} + +/// The recipient of a message +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum DursMsgReceiver { + /// Message for all modules + All, + /// Message for one specific module + One(ModuleStaticName), + /// Message for all modules who play a specific role + Role(ModuleRole), + /// Message for all modules that are subscribed to a specific type of event + Event(ModuleEvent), +} #[derive(Debug, Clone)] -/// Message exchanged between Duniter-rs modules -pub enum DuniterMessage { +/// Content of message exchanged between Durs modules +pub enum DursMsgContent { + /// Request + Request(DursReq), /// Brut text message Text(String), /// Brut binary message Binary(Vec<u8>), /// New configuration of a module to save - SaveNewModuleConf(ModuleId, serde_json::Value), - /// Subscriptions to the module feed - Followers(Vec<mpsc::Sender<DuniterMessage>>), - /// Blockchain datas request - DALRequest(DALRequest), + SaveNewModuleConf(ModuleName, serde_json::Value), /// Response of DALRequest DALResponse(Box<DALResponse>), /// Blockchain event DALEvent(DALEvent), /// Request to the network module - NetworkRequest(NetworkRequest), + OldNetworkRequest(OldNetworkRequest), /// Network event NetworkEvent(NetworkEvent), - /// Request to the pow module - ProverRequest(BlockId, Hash), + /// Response of OldNetworkRequest + NetworkResponse(NetworkResponse), /// Pow module response ProverResponse(BlockId, Sig, u64), /// Client API event @@ -79,4 +94,28 @@ pub enum DuniterMessage { Stop(), } -impl ModuleMessage for DuniterMessage {} +#[derive(Debug, Clone)] +/// Durs modules requests +pub struct DursReq { + /// Requester + pub requester: ModuleStaticName, + /// Request unique id + pub id: ModuleReqId, + /// Request content + pub content: DursReqContent, +} + +#[derive(Debug, Clone)] +/// Modules request content +pub enum DursReqContent { + /// Network request (Not yet implemented) + NetworkRequest(), + /// Blockchain datas request + DALRequest(DALRequest), + /// Request to the pow module + ProverRequest(BlockId, Hash), + /// Brut text request + Text(String), + /// Brut binary request + Binary(Vec<u8>), +} diff --git a/module/Cargo.toml b/module/Cargo.toml index 37f5d5afb9f318f097c5a50404ed2961a1c68bef..89d17afb5c1a09de22449253c27b7d618e9d6f6b 100644 --- a/module/Cargo.toml +++ b/module/Cargo.toml @@ -14,6 +14,7 @@ duniter-documents = { path = "../documents" } serde = "1.0.*" serde_derive = "1.0.*" serde_json = "1.0.*" +structopt= "0.2.*" [features] # Treat warnings as a build error. diff --git a/module/lib.rs b/module/lib.rs index 2122c1a2afa8ffb0882174378d6eaed223d31da1..009c00acb55eb5cf4c9db8db54dbf851fbc5e37d 100644 --- a/module/lib.rs +++ b/module/lib.rs @@ -17,7 +17,6 @@ //! as well as the DuniterModule trait that all modules must implement. #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] #![deny( missing_docs, missing_debug_implementations, @@ -37,6 +36,7 @@ extern crate duniter_crypto; extern crate duniter_documents; extern crate serde; extern crate serde_json; +extern crate structopt; use duniter_crypto::keys::{KeyPair, KeyPairEnum}; use duniter_documents::CurrencyName; @@ -45,12 +45,36 @@ use serde::ser::{Serialize, Serializer}; use std::collections::HashSet; use std::fmt::Debug; use std::sync::mpsc; +//use structopt::clap::ArgMatches; +use structopt::StructOpt; + +#[derive(Copy, Clone, Deserialize, Debug, PartialEq, Eq, Hash, Serialize)] +/// Store module name in static lifetime +pub struct ModuleStaticName(pub &'static str); + +impl ToString for ModuleStaticName { + fn to_string(&self) -> String { + String::from(self.0) + } +} #[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash, Serialize)] -/// Store module identifier -pub struct ModuleId(pub String); +/// Store module name +pub struct ModuleName(pub String); + +impl From<ModuleStaticName> for ModuleName { + fn from(source: ModuleStaticName) -> Self { + ModuleName(String::from(source.0)) + } +} + +impl<'a> From<&'a str> for ModuleName { + fn from(source: &str) -> Self { + ModuleName(String::from(source)) + } +} -impl ToString for ModuleId { +impl ToString for ModuleName { fn to_string(&self) -> String { self.0.clone() } @@ -69,10 +93,10 @@ impl Serialize for ModuleReqId { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] /// Several modules can simultaneously send requests with the same identifier. /// To identify each request in a unique way, we must therefore also take into account the identifier of the module performing the request. -pub struct ModuleReqFullId(pub ModuleId, pub ModuleReqId); +pub struct ModuleReqFullId(pub ModuleStaticName, pub ModuleReqId); impl ToString for ModuleReqFullId { fn to_string(&self) -> String { @@ -91,15 +115,17 @@ pub trait DuniterConf: Clone + Debug + Default + PartialEq + Serialize + Deseria /// Get node id fn my_node_id(&self) -> u32; /// Disable a module - fn disable(&mut self, module: ModuleId); + fn disable(&mut self, module: ModuleName); /// Enable a module - fn enable(&mut self, module: ModuleId); + fn enable(&mut self, module: ModuleName); /// Get disabled modules - fn disabled_modules(&self) -> HashSet<ModuleId>; + fn disabled_modules(&self) -> HashSet<ModuleName>; /// Get enabled modules - fn enabled_modules(&self) -> HashSet<ModuleId>; + fn enabled_modules(&self) -> HashSet<ModuleName>; /// Get modules conf fn modules(&self) -> serde_json::Value; + /// Change module conf + fn set_module_conf(&mut self, module_id: String, new_module_conf: serde_json::Value); } /// Sofware meta datas @@ -119,6 +145,58 @@ pub struct SoftwareMetaDatas<DC: DuniterConf> { /// provided that this type implements the ModuleMessage trait. pub trait ModuleMessage: Clone + Debug {} +/// List of the different roles that can be assigned to a module. +/// This role list allows a module to send a message to all modules playing a specific role without knowing their name. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ModuleRole { + /// Manages the blockchain data (include forks datas) + BlockchainDatas, + /// Checks if a block complies with the entire blockchain protocol + BlockValidation, + /// Generates the content of the next block + BlockGeneration, + /// Manage pending data for the wot + WotPool, + /// Manage pending data for the currency (transactions and scripts) + CurrencyPool, + /// Manages the network between nodes implementing the DUP protocol + InterNodesNetwork, + /// Communicates with client software + ClientsNetwork, + /// Communicates with the node user + UserInterface, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +///List of the different types of events that can be generated by a module. +/// This list allows the different modules to subscribe only to the types of events that interest them +pub enum ModuleEvent { + /// A new block has been received from the network + NewBlockFromNetwork, + /// A new transaction has been received from a client software. + NewTxFromNetwork, + /// A new wot document has been received from a network. + NewWotDocFromNetwork, + /// A new valid block has been added to the local blockchain + NewValidBlock, + /// A new valid block issued by the local node has been added to the local blockchain + NewValidBlockFromSelf, + /// A new non-isolated fork is in the local database + NewFork, + /// Blockchain rooling back + RevertBlocks, + /// A new transaction has been integrated into the local waiting room + NewTxinPool, + /// A new wot document has been integrated into the local waiting room + NewWotDocInPool, + /// A new valid HEAD has been received from the network + NewValidHeadFromNetwork, + /// Change in connections with other nodes (disconnection of a connection or establishment of a new connection) + ConnectionsChangeNodeNetwork, + /// A new valid peer record has been received from the network + NewValidPeerFromNodeNetwork, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] /// Type returned by module initialization function pub enum ModuleInitError { @@ -132,9 +210,14 @@ pub enum ModuleInitError { /// Type sent by each module to the rooter during initialization pub enum RooterThreadMessage<M: ModuleMessage> { /// Channel on which the module listens - ModuleSender(mpsc::Sender<M>), - /// When the number of plugged modules is known, the rooter thread must be informed of the number of modules it must connect between them. - ModulesCount(usize), + ModuleSender( + ModuleStaticName, + mpsc::Sender<M>, + Vec<ModuleRole>, + Vec<ModuleEvent>, + ), + /// Module message + ModuleMessage(M), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -186,8 +269,8 @@ pub fn enabled<DC: DuniterConf, Mess: ModuleMessage, M: DuniterModule<DC, Mess>> let enabled_modules = conf.enabled_modules(); match M::priority() { ModulePriority::Essential() => true, - ModulePriority::Recommended() => !disabled_modules.contains(&M::id()), - ModulePriority::Optional() => enabled_modules.contains(&M::id()), + ModulePriority::Recommended() => !disabled_modules.contains(&ModuleName::from(M::name())), + ModulePriority::Optional() => enabled_modules.contains(&ModuleName::from(M::name())), } } @@ -204,9 +287,14 @@ pub enum ModulesFilter { } /// Returns true only if the module checks all filters -pub fn module_valid_filters<DC: DuniterConf, Mess: ModuleMessage, M: DuniterModule<DC, Mess>>( +pub fn module_valid_filters< + DC: DuniterConf, + Mess: ModuleMessage, + M: DuniterModule<DC, Mess>, + S: ::std::hash::BuildHasher, +>( conf: &DC, - filters: &HashSet<ModulesFilter>, + filters: &HashSet<ModulesFilter, S>, network_module: bool, ) -> bool { if filters.contains(&ModulesFilter::Network()) && !network_module { @@ -230,13 +318,26 @@ pub fn module_valid_filters<DC: DuniterConf, Mess: ModuleMessage, M: DuniterModu pub trait DuniterModule<DC: DuniterConf, M: ModuleMessage> { /// Module configuration type ModuleConf: Clone + Debug + Default + DeserializeOwned + Send + Serialize + Sync; + /// Module subcommand options + type ModuleOpt: StructOpt; - /// Returns the module identifier - fn id() -> ModuleId; + /// Returns the module name + fn name() -> ModuleStaticName; /// Returns the module priority fn priority() -> ModulePriority; /// Indicates which keys the module needs fn ask_required_keys() -> RequiredKeys; + /// Define if module have a cli subcommand + fn have_subcommand() -> bool { + false + } + /// Execute injected subcommand + fn exec_subcommand( + soft_meta_datas: &SoftwareMetaDatas<DC>, + keys: RequiredKeysContent, + module_conf: Self::ModuleConf, + subcommand_args: Self::ModuleOpt, + ) -> (); /// Launch the module fn start( soft_meta_datas: &SoftwareMetaDatas<DC>, diff --git a/network/lib.rs b/network/lib.rs index 90eef25982cbe2bf9e28aa371235379316eec110..4a0ed49cb6d8d5f695c5857712e7a8bb7efc7098 100644 --- a/network/lib.rs +++ b/network/lib.rs @@ -85,10 +85,21 @@ pub trait NetworkModule<DC: DuniterConf, M: ModuleMessage>: ApiModule<DC, M> { keys: RequiredKeysContent, module_conf: <Self as DuniterModule<DC, M>>::ModuleConf, main_sender: mpsc::Sender<RooterThreadMessage<M>>, - sync_endpoint: SyncEndpoint, + sync_params: SyncParams, ) -> Result<(), ModuleInitError>; } +/// SyncParams +#[derive(Debug, Clone)] +pub struct SyncParams { + /// Synchronisation endpoint + pub sync_endpoint: SyncEndpoint, + /// Cautious flag + pub cautious: bool, + /// VERIF_HASHS flag + pub verif_hashs: bool, +} + #[derive(Debug, Clone)] /// Synchronisation endpoint pub struct SyncEndpoint { @@ -246,12 +257,12 @@ pub enum NetworkConsensusError { Fork(), } -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] /// Type containing a request addressed to the network module -pub enum NetworkRequest { +pub enum OldNetworkRequest { /// Get a current block of a specific node GetCurrent(ModuleReqFullId, NodeFullId), - //GetBlock(ModuleReqFullId, NodeFullId, u64), + //GetBlock(NodeFullId, u64), /// Get a blocks chunk from specified node GetBlocks(ModuleReqFullId, NodeFullId, u32, u32), /// Get pending wot documents from specified node @@ -264,16 +275,16 @@ pub enum NetworkRequest { GetEndpoints(ModuleReqFullId), } -impl NetworkRequest { +impl OldNetworkRequest { /// Get request full identitifier pub fn get_req_full_id(&self) -> ModuleReqFullId { match *self { - NetworkRequest::GetCurrent(ref req_id, _) - | NetworkRequest::GetBlocks(ref req_id, _, _, _) - | NetworkRequest::GetRequirementsPending(ref req_id, _, _) - | NetworkRequest::GetConsensus(ref req_id) - | NetworkRequest::GetHeadsCache(ref req_id) - | NetworkRequest::GetEndpoints(ref req_id) => req_id.clone(), + OldNetworkRequest::GetCurrent(ref req_id, _) + | OldNetworkRequest::GetBlocks(ref req_id, _, _, _) + | OldNetworkRequest::GetRequirementsPending(ref req_id, _, _) + | OldNetworkRequest::GetConsensus(ref req_id) + | OldNetworkRequest::GetHeadsCache(ref req_id) + | OldNetworkRequest::GetEndpoints(ref req_id) => *req_id, } } /// Get request identitifier @@ -284,7 +295,7 @@ impl NetworkRequest { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] /// Type returned when the network module does not get a satisfying answer to a request -pub enum NetworkRequestError { +pub enum OldNetworkRequestError { /// Receiving an invalid format response WrongFormat(), /// Unknow error @@ -321,7 +332,7 @@ impl NetworkResponse { | NetworkResponse::Chunk(ref req_id, _, _) | NetworkResponse::PendingDocuments(ref req_id, _) | NetworkResponse::Consensus(ref req_id, _) - | NetworkResponse::HeadsCache(ref req_id, _) => req_id.clone(), + | NetworkResponse::HeadsCache(ref req_id, _) => *req_id, } } /// Get request identifier @@ -333,8 +344,6 @@ impl NetworkResponse { #[derive(Debug, Clone)] /// Type containing a network event, each time a network event occurs it's relayed to all modules pub enum NetworkEvent { - /// Receiving a response to a network request - ReqResponse(Box<NetworkResponse>), /// A connection has changed state(`u32` is the new state, `Option<String>` est l'uid du noeud) ConnectionStateChange(NodeFullId, u32, Option<String>, String), /// Receiving Pending Documents diff --git a/network/network_head_v3.rs b/network/network_head_v3.rs index 99ac157f48bfa8165809f07a4b5aec9d041977e2..b227b94b1d4ce0f0195a2e32fee488f5e0af62dd 100644 --- a/network/network_head_v3.rs +++ b/network/network_head_v3.rs @@ -166,7 +166,8 @@ mod tests { pubkey: PubKey::Ed25519(keypair1().public_key()), blockstamp: Blockstamp::from_string( "50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370", - ).unwrap(), + ) + .unwrap(), software: String::from("durs"), soft_version: String::from("0.1.0-a0.1"), signature: None, diff --git a/network/network_peer.rs b/network/network_peer.rs index 8a62a434ed2aa3730b27c2f5b8fb91714a7cdbc1..d0b7bf9f30acc55155456c3811f43129bd857364 100644 --- a/network/network_peer.rs +++ b/network/network_peer.rs @@ -194,7 +194,8 @@ mod tests { node_id: NodeId(0), blockstamp: Blockstamp::from_string( "50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370", - ).unwrap(), + ) + .unwrap(), endpoints: vec![ EndpointEnum::V2(create_endpoint_v2()), EndpointEnum::V2(create_second_endpoint_v2()), diff --git a/src/main.rs b/src/main.rs index b4e8bb10093c4f7d188cacdf4991f96a19b3aefd..14bb6220dfe44e2388defddf5221acae6e052b93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,42 +29,101 @@ )] extern crate duniter_core; -#[cfg(feature = "tui")] +#[cfg(unix)] extern crate duniter_tui; extern crate durs_ws2p_v1_legacy; //extern crate durs_ws2p; +extern crate structopt; -pub use duniter_core::DuRsConf; -pub use duniter_core::DuniterCore; -#[cfg(feature = "tui")] +pub use duniter_core::{cli::DursOpt, DuRsConf, DuniterCore, UserCommand}; +#[cfg(unix)] pub use duniter_tui::TuiModule; pub use durs_ws2p_v1_legacy::WS2PModule; //pub use durs_ws2p::WS2Pv2Module; +use structopt::StructOpt; /// Main function +#[cfg(unix)] +#[cfg(not(target_arch = "arm"))] fn main() { // Get software name and version let soft_name = env!("CARGO_PKG_NAME"); let soft_version = env!("CARGO_PKG_VERSION"); - // Run duniter core - if let Some(mut duniter_core) = DuniterCore::<DuRsConf>::new(soft_name, soft_version) { + // Instantiate duniter core + let clap_app = DursOpt::clap(); + let mut duniter_core = DuniterCore::<DuRsConf>::new(soft_name, soft_version, &clap_app, 0); + + // Inject plugins subcommands + //duniter_core.inject_cli_subcommand::<GvaModule>(); + duniter_core.inject_cli_subcommand::<TuiModule>(); + duniter_core.inject_cli_subcommand::<WS2PModule>(); + + // Match user command + if duniter_core.match_user_command() { + // Plug all plugins + //duniter_core.plug::<GuiModule>(); + //duniter_core.plug::<GvaModule>(); + //duniter_core.plug::<PoolModule>(); + //duniter_core.plug::<PowModule>(); + duniter_core.plug::<TuiModule>(); + duniter_core.plug_network::<WS2PModule>(); + duniter_core.start_core(); + } +} +#[cfg(unix)] +#[cfg(target_arch = "arm")] +fn main() { + // Get software name and version + let soft_name = env!("CARGO_PKG_NAME"); + let soft_version = env!("CARGO_PKG_VERSION"); + + // Instantiate duniter core + let clap_app = DursOpt::clap(); + let mut duniter_core = DuniterCore::<DuRsConf>::new(soft_name, soft_version, &clap_app, 0); + + // Inject plugins subcommands + //duniter_core.inject_cli_subcommand::<DasaModule>(); + //duniter_core.inject_cli_subcommand::<GvaModule>(); + duniter_core.inject_cli_subcommand::<TuiModule>(); + duniter_core.inject_cli_subcommand::<WS2PModule>(); + + // Match user command + if duniter_core.match_user_command() { + // Plug all plugins //duniter_core.plug::<DasaModule>(); //duniter_core.plug::<GuiModule>(); //duniter_core.plug::<GvaModule>(); //duniter_core.plug::<PoolModule>(); //duniter_core.plug::<PowModule>(); - plug_tui_module(&mut duniter_core); + duniter_core.plug::<TuiModule>(); duniter_core.plug_network::<WS2PModule>(); - //duniter_core.plug_network::<WS2Pv2Module>(); - duniter_core.start_blockchain(); - }; + duniter_core.start_core(); + } } +#[cfg(windows)] +fn main() { + // Get software name and version + let soft_name = env!("CARGO_PKG_NAME"); + let soft_version = env!("CARGO_PKG_VERSION"); + + // Instantiate duniter core + let clap_app = DursOpt::clap(); + let mut duniter_core = DuniterCore::<DuRsConf>::new(soft_name, soft_version, &clap_app, 0); + + // Inject plugins subcommands + //duniter_core.inject_cli_subcommand::<GvaModule>(); + duniter_core.inject_cli_subcommand::<WS2PModule>(); -/// Plug TUI Module -#[cfg(feature = "tui")] -fn plug_tui_module(duniter_core: &mut DuniterCore<DuRsConf>) { - duniter_core.plug::<TuiModule>(); + // Match user command + if duniter_core.match_user_command() { + // Plug all plugins + //duniter_core.plug::<DasaModule>(); + //duniter_core.plug::<GuiModule>(); + //duniter_core.plug::<GvaModule>(); + //duniter_core.plug::<PoolModule>(); + //duniter_core.plug::<PowModule>(); + duniter_core.plug_network::<WS2PModule>(); + duniter_core.start_core(); + } } -#[cfg(not(feature = "tui"))] -fn plug_tui_module(_duniter_core: &mut DuniterCore<DuRsConf>) {} diff --git a/tui/Cargo.toml b/tui/Cargo.toml index 3e7c9c00f52d8fac2bfa0437175a75f03c07df5b..044e90e971096e286a320ecc45cd311b4df6e86a 100644 --- a/tui/Cargo.toml +++ b/tui/Cargo.toml @@ -20,6 +20,7 @@ log = "0.4.*" serde = "1.0.*" serde_derive = "1.0.*" serde_json = "1.0.*" +structopt= "0.2.*" termion = "1.5.*" [features] diff --git a/tui/lib.rs b/tui/lib.rs index 67fa4b46af949ecf2a5d8e3978028d00230eb8c5..18cd3a7f4d6f259f1e635e9510fa9517d53f9925 100644 --- a/tui/lib.rs +++ b/tui/lib.rs @@ -33,6 +33,8 @@ extern crate log; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate structopt; extern crate duniter_conf; extern crate duniter_crypto; @@ -42,11 +44,12 @@ extern crate duniter_message; extern crate duniter_module; extern crate duniter_network; extern crate serde; +extern crate serde_json; extern crate termion; use duniter_conf::DuRsConf; use duniter_dal::dal_event::DALEvent; -use duniter_message::DuniterMessage; +use duniter_message::*; use duniter_module::*; use duniter_network::network_head::NetworkHead; use duniter_network::{NetworkEvent, NodeFullId}; @@ -61,13 +64,17 @@ use termion::input::{MouseTerminal, TermRead}; use termion::raw::{IntoRawMode, RawTerminal}; use termion::{clear, color, cursor, style}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] /// Tui Module Configuration (For future use) -pub struct TuiConf {} +pub struct TuiConf { + test_fake_conf_field: String, +} impl Default for TuiConf { fn default() -> Self { - TuiConf {} + TuiConf { + test_fake_conf_field: String::from("default"), + } } } @@ -75,7 +82,7 @@ impl Default for TuiConf { /// Format of messages received by the tui module pub enum TuiMess { /// Message from another module - DuniterMessage(Box<DuniterMessage>), + DursMsg(Box<DursMsg>), /// Message from stdin (user event) TermionEvent(Event), } @@ -84,6 +91,17 @@ pub enum TuiMess { /// Tui module pub struct TuiModule {} +#[derive(StructOpt, Debug, Clone)] +#[structopt( + name = "tui", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// Tui subcommand options +pub struct TuiOpt { + /// Change test conf fake field + pub new_conf_field: String, +} + #[derive(Debug, Clone)] /// Network connexion (data to display) pub struct Connection { @@ -99,7 +117,7 @@ pub struct Connection { /// Data that the Tui module needs to cache pub struct TuiModuleDatas { /// Sender of all other modules - pub followers: Vec<mpsc::Sender<DuniterMessage>>, + pub followers: Vec<mpsc::Sender<DursMsgContent>>, /// HEADs cache content pub heads_cache: HashMap<NodeFullId, NetworkHead>, /// Position of the 1st head displayed on the screen @@ -164,7 +182,8 @@ impl TuiModuleDatas { color::Bg(color::Black), clear::All, cursor::Goto(1, 1) - ).unwrap(); + ) + .unwrap(); // Draw headers let mut line = 1; @@ -174,7 +193,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::White), out_established_conns.len() - ).unwrap(); + ) + .unwrap(); line += 1; write!( stdout, @@ -182,7 +202,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::White), style::Italic, - ).unwrap(); + ) + .unwrap(); // Draw inter-nodes established connections if out_established_conns.is_empty() { @@ -193,7 +214,8 @@ impl TuiModuleDatas { cursor::Goto(2, line), color::Fg(color::Red), style::Bold, - ).unwrap(); + ) + .unwrap(); } else { for (ref node_full_id, ref uid, ref url) in out_established_conns { line += 1; @@ -209,7 +231,8 @@ impl TuiModuleDatas { node_full_id.to_human_string(), uid_string, url, - ).unwrap(); + ) + .unwrap(); } } @@ -226,7 +249,8 @@ impl TuiModuleDatas { out_trying_conns_count, out_denial_conns_count, out_disconnected_conns_count, - ).unwrap(); + ) + .unwrap(); // Draw separated line line += 1; @@ -240,7 +264,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::White), separated_line, - ).unwrap(); + ) + .unwrap(); // Draw HEADs line += 1; @@ -250,7 +275,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::White), heads.len() - ).unwrap(); + ) + .unwrap(); line += 1; if heads_index > 0 { write!( @@ -258,14 +284,16 @@ impl TuiModuleDatas { "{}{}/\\", cursor::Goto(35, line), color::Fg(color::Green), - ).unwrap(); + ) + .unwrap(); } else { write!( stdout, "{}{}/\\", cursor::Goto(35, line), color::Fg(color::Black), - ).unwrap(); + ) + .unwrap(); } line += 1; write!( @@ -284,7 +312,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::Blue), head.to_human_string(w as usize), - ).unwrap(); + ) + .unwrap(); } else { write!( stdout, @@ -292,7 +321,8 @@ impl TuiModuleDatas { cursor::Goto(1, line), color::Fg(color::Green), head.to_human_string(w as usize), - ).unwrap(); + ) + .unwrap(); } } else { break; @@ -305,14 +335,16 @@ impl TuiModuleDatas { "{}{}\\/", cursor::Goto(35, line), color::Fg(color::Green), - ).unwrap(); + ) + .unwrap(); } else { write!( stdout, "{}{}\\/", cursor::Goto(35, line), color::Fg(color::Black), - ).unwrap(); + ) + .unwrap(); } // Draw footer @@ -335,7 +367,8 @@ impl TuiModuleDatas { color::Bg(color::Blue), color::Fg(color::White), runtime_str, - ).unwrap(); + ) + .unwrap(); write!( stdout, "{}{}{}q : quit{}", @@ -343,7 +376,8 @@ impl TuiModuleDatas { color::Bg(color::Blue), color::Fg(color::White), cursor::Hide, - ).unwrap(); + ) + .unwrap(); // Flush stdout (i.e. make the output appear). stdout.flush().unwrap(); @@ -356,11 +390,12 @@ impl Default for TuiModule { } } -impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { +impl DuniterModule<DuRsConf, DursMsg> for TuiModule { type ModuleConf = TuiConf; + type ModuleOpt = TuiOpt; - fn id() -> ModuleId { - ModuleId(String::from("tui")) + fn name() -> ModuleStaticName { + ModuleStaticName("tui") } fn priority() -> ModulePriority { ModulePriority::Recommended() @@ -368,11 +403,35 @@ impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { fn ask_required_keys() -> RequiredKeys { RequiredKeys::None() } + fn have_subcommand() -> bool { + true + } + fn exec_subcommand( + soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, + _keys: RequiredKeysContent, + module_conf: Self::ModuleConf, + subcommand_args: TuiOpt, + ) -> () { + let mut conf = soft_meta_datas.conf.clone(); + let new_tui_conf = TuiConf { + test_fake_conf_field: subcommand_args.new_conf_field.clone(), + }; + conf.set_module_conf( + Self::name().to_string(), + serde_json::value::to_value(new_tui_conf).expect("Fail to jsonifie TuiConf !"), + ); + duniter_conf::write_conf_file(&soft_meta_datas.profile, &conf) + .expect("Fail to write new Tui conf file ! "); + println!( + "Succesfully exec tui subcommand whit terminal name : {} and conf={:?}!", + subcommand_args.new_conf_field, module_conf + ) + } fn start( _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: Self::ModuleConf, - main_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, + main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, load_conf_only: bool, ) -> Result<(), ModuleInitError> { let start_time = SystemTime::now(); //: DateTime<Utc> = Utc::now(); @@ -397,32 +456,47 @@ impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { // Create proxy channel let (proxy_sender, proxy_receiver): ( - mpsc::Sender<DuniterMessage>, - mpsc::Receiver<DuniterMessage>, + mpsc::Sender<DursMsg>, + mpsc::Receiver<DursMsg>, ) = mpsc::channel(); - // Launch a proxy thread that transform DuniterMessage() to TuiMess::DuniterMessage(DuniterMessage()) + // Launch a proxy thread that transform DursMsgContent() to TuiMess::DursMsgContent(DursMsgContent()) let tui_sender_clone = tui_sender.clone(); thread::spawn(move || { // Send proxy sender to main main_sender - .send(RooterThreadMessage::ModuleSender(proxy_sender)) + .send(RooterThreadMessage::ModuleSender( + TuiModule::name(), + proxy_sender, + vec![ModuleRole::UserInterface], + vec![ + ModuleEvent::NewValidBlock, + ModuleEvent::ConnectionsChangeNodeNetwork, + ModuleEvent::NewValidHeadFromNetwork, + ModuleEvent::NewValidPeerFromNodeNetwork, + ], + )) .expect("Fatal error : tui module fail to send is sender channel !"); debug!("Send tui sender to main thread."); loop { match proxy_receiver.recv() { - Ok(message) => match tui_sender_clone - .send(TuiMess::DuniterMessage(Box::new(message.clone()))) - { - Ok(_) => { - if let DuniterMessage::Stop() = message { - break; - }; - } - Err(_) => { - debug!("tui proxy : fail to relay DuniterMessage to tui main thread !") + Ok(message) => { + let stop = if let DursMsg(_, DursMsgContent::Stop()) = message { + true + } else { + false + }; + match tui_sender_clone.send(TuiMess::DursMsg(Box::new(message))) { + Ok(_) => { + if stop { + break; + }; + } + Err(_) => { + debug!("tui proxy : fail to relay DursMsg to tui main thread !") + } } - }, + } Err(e) => { warn!("{}", e); break; @@ -455,7 +529,8 @@ impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { tui_sender .send(TuiMess::TermionEvent( c.expect("error to read stdin event !"), - )).expect("Fatal error : tui stdin thread module fail to send message !"); + )) + .expect("Fatal error : tui stdin thread module fail to send message !"); trace!("Send stdin event to tui main thread."); } }); @@ -466,79 +541,69 @@ impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { // Get messages match tui_receiver.recv_timeout(Duration::from_millis(250)) { Ok(ref message) => match *message { - TuiMess::DuniterMessage(ref duniter_message) => { - match *duniter_message.deref() { - DuniterMessage::Stop() => { - writeln!( - stdout, - "{}{}{}{}{}", - color::Fg(color::Reset), - cursor::Goto(1, 1), - color::Bg(color::Reset), - cursor::Show, - clear::All, - ).unwrap(); - let _result_stop_propagation: Result< + TuiMess::DursMsg(ref duniter_message) => match (*duniter_message.deref()).1 { + DursMsgContent::Stop() => { + writeln!( + stdout, + "{}{}{}{}{}", + color::Fg(color::Reset), + cursor::Goto(1, 1), + color::Bg(color::Reset), + cursor::Show, + clear::All, + ) + .unwrap(); + let _result_stop_propagation: Result< (), - mpsc::SendError<DuniterMessage>, + mpsc::SendError<DursMsgContent>, > = tui .followers .iter() - .map(|f| f.send(DuniterMessage::Stop())) + .map(|f| f.send(DursMsgContent::Stop())) .collect(); - break; + break; + } + DursMsgContent::DALEvent(ref dal_event) => match *dal_event { + DALEvent::StackUpValidBlock(ref _block, ref _blockstamp) => {} + DALEvent::RevertBlocks(ref _blocks) => {} + _ => {} + }, + DursMsgContent::NetworkEvent(ref network_event) => match *network_event { + NetworkEvent::ConnectionStateChange( + ref node_full_id, + ref status, + ref uid, + ref url, + ) => { + if let Some(conn) = tui.connections_status.get(&node_full_id) { + if *status == 12 && (*conn).status != 12 { + tui.established_conns_count += 1; + } else if *status != 12 + && (*conn).status == 12 + && tui.established_conns_count > 0 + { + tui.established_conns_count -= 1; + } + }; + tui.connections_status.insert( + *node_full_id, + Connection { + status: *status, + url: url.clone(), + uid: uid.clone(), + }, + ); } - DuniterMessage::Followers(ref new_followers) => { - info!("Tui module receive followers !"); - for new_follower in new_followers { - debug!("TuiModule : push one follower."); - tui.followers.push(new_follower.clone()); - } + NetworkEvent::ReceiveHeads(ref heads) => { + heads + .iter() + .map(|h| tui.heads_cache.insert(h.node_full_id(), h.clone())) + .for_each(drop); } - DuniterMessage::DALEvent(ref dal_event) => match *dal_event { - DALEvent::StackUpValidBlock(ref _block, ref _blockstamp) => {} - DALEvent::RevertBlocks(ref _blocks) => {} - _ => {} - }, - DuniterMessage::NetworkEvent(ref network_event) => match *network_event - { - NetworkEvent::ConnectionStateChange( - ref node_full_id, - ref status, - ref uid, - ref url, - ) => { - if let Some(conn) = tui.connections_status.get(&node_full_id) { - if *status == 12 && (*conn).status != 12 { - tui.established_conns_count += 1; - } else if *status != 12 - && (*conn).status == 12 - && tui.established_conns_count > 0 - { - tui.established_conns_count -= 1; - } - }; - tui.connections_status.insert( - *node_full_id, - Connection { - status: *status, - url: url.clone(), - uid: uid.clone(), - }, - ); - } - NetworkEvent::ReceiveHeads(ref heads) => { - heads - .iter() - .map(|h| { - tui.heads_cache.insert(h.node_full_id(), h.clone()) - }).for_each(drop); - } - _ => {} - }, _ => {} - } - } + }, + _ => {} + }, TuiMess::TermionEvent(ref term_event) => match *term_event { Event::Key(Key::Char('q')) => { // Exit @@ -550,14 +615,15 @@ impl DuniterModule<DuRsConf, DuniterMessage> for TuiModule { color::Bg(color::Reset), cursor::Show, clear::All, - ).unwrap(); + ) + .unwrap(); let _result_stop_propagation: Result< (), - mpsc::SendError<DuniterMessage>, + mpsc::SendError<DursMsgContent>, > = tui .followers .iter() - .map(|f| f.send(DuniterMessage::Stop())) + .map(|f| f.send(DursMsgContent::Stop())) .collect(); break; } diff --git a/wotb/data/rusty.rs b/wotb/data/rusty.rs index 35cbaed96401f739d2673e3301cd3785ce9dec9e..22cdd86612fa5e8fd2e51d02f17195572e1844a7 100644 --- a/wotb/data/rusty.rs +++ b/wotb/data/rusty.rs @@ -199,7 +199,8 @@ impl WebOfTrust for RustyWebOfTrust { n.enabled && n.issued_count >= sentry_requirement && n.links_source.len() >= sentry_requirement - }).map(|(i, _)| NodeId(i)) + }) + .map(|(i, _)| NodeId(i)) .collect() } @@ -211,7 +212,8 @@ impl WebOfTrust for RustyWebOfTrust { n.enabled && (n.issued_count < sentry_requirement || n.links_source.len() < sentry_requirement) - }).map(|(i, _)| NodeId(i)) + }) + .map(|(i, _)| NodeId(i)) .collect() } } diff --git a/wotb/lib.rs b/wotb/lib.rs index d8d324e9552b69f7c2688554470d43f2e88e2c08..3926037bfc22061f3f942d610f0fc797807c2337 100644 --- a/wotb/lib.rs +++ b/wotb/lib.rs @@ -497,7 +497,8 @@ mod tests { &wot, &[0b0000_0000, 0b0000_0001, 0b0000_0001, 0b0000_0000], "test.wot" - ).unwrap(), + ) + .unwrap(), () ); diff --git a/wotb/operations/distance.rs b/wotb/operations/distance.rs index 14105d595399b71915c84cb088c6a90fdaa7954c..46949ad205c0760554d1ee0f4267bd44196f2c0b 100644 --- a/wotb/operations/distance.rs +++ b/wotb/operations/distance.rs @@ -93,7 +93,8 @@ impl<T: WebOfTrust + Sync> DistanceCalculator<T> for RustyDistanceCalculator { .filter(|source| !area.contains(source)) .cloned() .collect::<HashSet<_>>() - }).reduce(HashSet::new, |mut acc, sources| { + }) + .reduce(HashSet::new, |mut acc, sources| { for source in sources { acc.insert(source); } diff --git a/ws2p-messages/lib.rs b/ws2p-messages/lib.rs index e7e0e9c602a46089e16d8c4df5875a3b8a73bcbd..1588f275e38dd34b9485c3882b096dee74deb6c8 100644 --- a/ws2p-messages/lib.rs +++ b/ws2p-messages/lib.rs @@ -109,7 +109,8 @@ mod tests { node_id: NodeId(0), blockstamp: Blockstamp::from_string( "50-000005B1CEB4EC5245EF7E33101A330A1C9A358EC45A25FC13F78BB58C9E7370", - ).unwrap(), + ) + .unwrap(), endpoints: vec![create_endpoint_v11(), create_second_endpoint_v11()], sig: None, } @@ -168,14 +169,15 @@ mod tests { let blockstamp = Blockstamp::from_string( "36-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B865", - ).unwrap(); + ) + .unwrap(); CompactCertificationDocument { issuer: PubKey::Ed25519( ed25519::PublicKey::from_base58("4tNQ7d9pj2Da5wUVoW9mFn7JjuPoowF977au8DdhEjVR") .unwrap(), ), - target: target, + target, block_number: blockstamp.id, signature: sig, } diff --git a/ws2p-messages/v2/connect.rs b/ws2p-messages/v2/connect.rs index 3ed23827ad012a8215e1887c8ccb28e2778cb215..f1ad97ae6b54c8ba0dd310dc63f7c6e75df6e385 100644 --- a/ws2p-messages/v2/connect.rs +++ b/ws2p-messages/v2/connect.rs @@ -98,14 +98,16 @@ mod tests { let connect_msg = WS2Pv2ConnectMsg { challenge: Hash::from_hex( "000007722B243094269E548F600BD34D73449F7578C05BD370A6D301D20B5F10", - ).unwrap(), + ) + .unwrap(), api_features: WS2PFeatures(vec![7u8]), flags_queries: WS2PConnectFlags(vec![]), peer_card: Some(peer), chunkstamp: Some( Blockstamp::from_string( "499-000011BABEEE1020B1F6B2627E2BC1C35BCD24375E114349634404D2C266D84F", - ).unwrap(), + ) + .unwrap(), ), }; test_ws2p_message(WS2Pv0MessagePayload::Connect(Box::new(connect_msg))); diff --git a/ws2p-messages/v2/ok.rs b/ws2p-messages/v2/ok.rs index e442e373aac0b413b0f4b81b8075692a0cbe8858..e480524975988f82afe27642ea6e986f7a02a1e9 100644 --- a/ws2p-messages/v2/ok.rs +++ b/ws2p-messages/v2/ok.rs @@ -59,14 +59,17 @@ mod tests { sync_target: Some(WS2Pv2SyncTarget { target_blockstamp: Blockstamp::from_string( "500-000011BABEEE1020B1F6B2627E2BC1C35BCD24375E114349634404D2C266D84F", - ).unwrap(), + ) + .unwrap(), chunks_hash: vec![ Hash::from_hex( "000007722B243094269E548F600BD34D73449F7578C05BD370A6D301D20B5F10", - ).unwrap(), + ) + .unwrap(), Hash::from_hex( "0000095FD4C8EA96DE2844E3A4B62FD18761E9B4C13A74FAB716A4C81F438D91", - ).unwrap(), + ) + .unwrap(), ], }), }; diff --git a/ws2p-messages/v2/req_responses.rs b/ws2p-messages/v2/req_responses.rs index 0a46a21d786298cc88cee8dc4de059d161b88238..ed81adbc5cfc62e6d4d2dd133284877f4e025aff 100644 --- a/ws2p-messages/v2/req_responses.rs +++ b/ws2p-messages/v2/req_responses.rs @@ -88,7 +88,8 @@ mod tests { fn test_ws2p_message_req_res_current() { let blockstamp = Blockstamp::from_string( "499-000011BABEEE1020B1F6B2627E2BC1C35BCD24375E114349634404D2C266D84F", - ).unwrap(); + ) + .unwrap(); let response = WS2Pv2ReqRes { id: 28, body: WS2Pv2ReqResBody::Current(blockstamp), diff --git a/ws2p-messages/v2/requests.rs b/ws2p-messages/v2/requests.rs index 3290ceaa4006473e64f16727e244e09aaad7292a..e160f7e126a4683348e8a04db77cf103b41c0e19 100644 --- a/ws2p-messages/v2/requests.rs +++ b/ws2p-messages/v2/requests.rs @@ -81,7 +81,8 @@ mod tests { fn test_ws2p_message_request() { let chunkstamp = Blockstamp::from_string( "499-000011BABEEE1020B1F6B2627E2BC1C35BCD24375E114349634404D2C266D84F", - ).unwrap(); + ) + .unwrap(); let request = WS2Pv2Request { id: 27, body: WS2Pv2RequestBody::ChunkByHash(chunkstamp), diff --git a/ws2p-v1-legacy/Cargo.toml b/ws2p-v1-legacy/Cargo.toml index b8c414717834e5e1b7dff2cf2d3c9122fabe720a..3df5308efa61a620d54d3d7a78dba9913c5e322f 100644 --- a/ws2p-v1-legacy/Cargo.toml +++ b/ws2p-v1-legacy/Cargo.toml @@ -27,6 +27,7 @@ sqlite = "0.23.*" serde = "1.0.*" serde_derive = "1.0.*" serde_json = "1.0.*" +structopt= "0.2.*" ws = { version = "0.7.*", features = ["permessage-deflate"] } [features] diff --git a/ws2p-v1-legacy/clippy.toml b/ws2p-v1-legacy/clippy.toml new file mode 100644 index 0000000000000000000000000000000000000000..e02f006add50da81398cc2451bd748c47c7bdf9d --- /dev/null +++ b/ws2p-v1-legacy/clippy.toml @@ -0,0 +1 @@ +cyclomatic-complexity-threshold = 75 \ No newline at end of file diff --git a/ws2p-v1-legacy/datas.rs b/ws2p-v1-legacy/datas.rs index b163718542c8cc13d1df5f11654cf618eccac28f..6658c6232df2a20ea8c1c6a1cd9904578bc6b848 100644 --- a/ws2p-v1-legacy/datas.rs +++ b/ws2p-v1-legacy/datas.rs @@ -17,7 +17,7 @@ use constants::*; use duniter_crypto::keys::*; use duniter_dal::dal_requests::DALRequest; use duniter_documents::Blockstamp; -use duniter_message::DuniterMessage; +use duniter_message::*; use duniter_network::network_endpoint::*; use duniter_network::network_head::*; use duniter_network::*; @@ -27,7 +27,7 @@ use *; #[derive(Debug)] pub struct WS2PModuleDatas { - pub followers: Vec<mpsc::Sender<DuniterMessage>>, + pub rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, pub currency: Option<String>, pub key_pair: Option<KeyPairEnum>, pub conf: WS2PConf, @@ -38,10 +38,12 @@ pub struct WS2PModuleDatas { ), pub ws2p_endpoints: HashMap<NodeFullId, (EndpointEnum, WS2PConnectionState)>, pub websockets: HashMap<NodeFullId, WsSender>, - pub requests_awaiting_response: HashMap<ModuleReqId, (NetworkRequest, NodeFullId, SystemTime)>, + pub requests_awaiting_response: + HashMap<ModuleReqId, (OldNetworkRequest, NodeFullId, SystemTime)>, pub heads_cache: HashMap<NodeFullId, NetworkHead>, pub my_head: Option<NetworkHead>, pub uids_cache: HashMap<PubKey, String>, + pub count_dal_requests: u32, } impl WS2PModuleDatas { @@ -58,27 +60,59 @@ impl WS2PModuleDatas { } Ok(conn) } - pub fn send_dal_request(&self, req: &DALRequest) { - for follower in &self.followers { - if follower - .send(DuniterMessage::DALRequest(req.clone())) - .is_err() - { - // handle error - } + pub fn send_dal_request(&mut self, req: &DALRequest) { + self.count_dal_requests += 1; + if self.count_dal_requests == std::u32::MAX { + self.count_dal_requests = 0; } + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::Role(ModuleRole::BlockchainDatas), + DursMsgContent::Request(DursReq { + requester: WS2PModule::name(), + id: ModuleReqId(self.count_dal_requests), + content: DursReqContent::DALRequest(req.clone()), + }), + ))) + .expect("Fail to send message to rooter !"); + } + pub fn send_network_req_response( + &self, + requester: ModuleStaticName, + response: NetworkResponse, + ) { + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::One(requester), + DursMsgContent::NetworkResponse(response), + ))) + .expect("Fail to send message to rooter !"); } pub fn send_network_event(&self, event: &NetworkEvent) { - for follower in &self.followers { - match follower.send(DuniterMessage::NetworkEvent(event.clone())) { - Ok(_) => { - debug!("Send NetworkEvent to one follower."); - } - Err(_) => { - warn!("Fail to send NetworkEvent to one follower !"); + let module_event = match event { + NetworkEvent::ConnectionStateChange(_, _, _, _) => { + ModuleEvent::ConnectionsChangeNodeNetwork + } + NetworkEvent::ReceiveDocuments(network_docs) => { + if !network_docs.is_empty() { + match network_docs[0] { + NetworkDocument::Block(_) => ModuleEvent::NewBlockFromNetwork, + NetworkDocument::Transaction(_) => ModuleEvent::NewTxFromNetwork, + _ => ModuleEvent::NewWotDocFromNetwork, + } + } else { + return; } } - } + NetworkEvent::ReceiveHeads(_) => ModuleEvent::NewValidHeadFromNetwork, + NetworkEvent::ReceivePeers(_) => ModuleEvent::NewValidPeerFromNodeNetwork, + }; + self.rooter_sender + .send(RooterThreadMessage::ModuleMessage(DursMsg( + DursMsgReceiver::Event(module_event), + DursMsgContent::NetworkEvent(event.clone()), + ))) + .expect("Fail to send network event to rooter !"); } pub fn get_network_consensus(&self) -> Result<Blockstamp, NetworkConsensusError> { let mut count_known_blockstamps = 0; @@ -184,7 +218,8 @@ impl WS2PModuleDatas { &endpoint .node_full_id() .expect("WS2P: Fail to get ep.node_full_id() !"), - ).expect("WS2P: Fail to get_mut() a ws2p_endpoint !") + ) + .expect("WS2P: Fail to get_mut() a ws2p_endpoint !") .1 = WS2PConnectionState::NeverTry; } None => { @@ -267,12 +302,13 @@ impl WS2PModuleDatas { .expect("WS2P: Fail to get mut ep !") .1 = new_con_state; if let WS2PConnectionState::AckMessOk = self.ws2p_endpoints[&ws2p_full_id].1 { - trace!("DEBUG : Send: {:#?}", r); + trace!("Send: {:#?}", r); self.websockets .get_mut(&ws2p_full_id) .unwrap_or_else(|| { panic!("Fatal error : no websocket for {} !", ws2p_full_id) - }).0 + }) + .0 .send(Message::text(r)) .expect("WS2P: Fail to send Message in websocket !"); } @@ -327,7 +363,7 @@ impl WS2PModuleDatas { { return WS2PSignal::ReqResponse( req_id, - ws2p_request.clone(), + *ws2p_request, *recipient_fulld_id, response, ); @@ -409,15 +445,15 @@ impl WS2PModuleDatas { /*pub fn send_request_to_all_connections( &mut self, - ws2p_request: &NetworkRequest, + ws2p_request: &OldNetworkRequest, ) -> Result<(), SendRequestError> { let mut count_successful_sending: usize = 0; let mut errors: Vec<ws::Error> = Vec::new(); match *ws2p_request { - NetworkRequest::GetCurrent(req_full_id, _receiver) => { + OldNetworkRequest::GetCurrent(req_full_id, _receiver) => { for (ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { if let WS2PConnectionState::Established = state { - let ws2p_request = NetworkRequest::GetCurrent( + let ws2p_request = OldNetworkRequest::GetCurrent( ModuleReqFullId( req_full_id.0, ModuleReqId( @@ -435,41 +471,41 @@ impl WS2PModuleDatas { } } } - /* NetworkRequest::GetBlock(req_full_id, number) => {} */ - NetworkRequest::GetBlocks(_req_full_id, _receiver, _count, _from_number) => {} - NetworkRequest::GetRequirementsPending(req_full_id, _receiver, min_cert) => { - for (ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { - if let WS2PConnectionState::Established = state { - let ws2p_request = NetworkRequest::GetRequirementsPending( - ModuleReqFullId( - req_full_id.0, - ModuleReqId(self.requests_awaiting_response.len() as u32), - ), - ws2p_full_id, - min_cert, - ); - match self.send_request_to_specific_node(&ws2p_full_id, &ws2p_request) { - Ok(_) => count_successful_sending += 1, - Err(e) => errors.push(e), - }; - } - } - } - _ => { - return Err(SendRequestError::RequestTypeMustNotBeTransmitted()); - } - } - debug!("count_successful_sending = {}", count_successful_sending); - if !errors.is_empty() { - return Err(SendRequestError::WSError(count_successful_sending, errors)); - } - Ok(()) + /* OldNetworkRequest::GetBlock(req_full_id, number) => {} */ + OldNetworkRequest::GetBlocks(_req_full_id, _receiver, _count, _from_number) => {} + OldNetworkRequest::GetRequirementsPending(req_full_id, _receiver, min_cert) => { + for (ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { + if let WS2PConnectionState::Established = state { + let ws2p_request = OldNetworkRequest::GetRequirementsPending( + ModuleReqFullId( + req_full_id.0, + ModuleReqId(self.requests_awaiting_response.len() as u32), + ), + ws2p_full_id, + min_cert, + ); + match self.send_request_to_specific_node(&ws2p_full_id, &ws2p_request) { + Ok(_) => count_successful_sending += 1, + Err(e) => errors.push(e), + }; + } + } + } + _ => { + return Err(SendRequestError::RequestTypeMustNotBeTransmitted()); + } + } + debug!("count_successful_sending = {}", count_successful_sending); + if !errors.is_empty() { + return Err(SendRequestError::WSError(count_successful_sending, errors)); + } + Ok(()) }*/ pub fn send_request_to_specific_node( &mut self, receiver_ws2p_full_id: &NodeFullId, - ws2p_request: &NetworkRequest, + ws2p_request: &OldNetworkRequest, ) -> ws::Result<()> { self.websockets .get_mut(receiver_ws2p_full_id) @@ -480,11 +516,7 @@ impl WS2PModuleDatas { ))?; self.requests_awaiting_response.insert( ws2p_request.get_req_id(), - ( - ws2p_request.clone(), - *receiver_ws2p_full_id, - SystemTime::now(), - ), + (*ws2p_request, *receiver_ws2p_full_id, SystemTime::now()), ); debug!( "send request {} to {}", diff --git a/ws2p-v1-legacy/lib.rs b/ws2p-v1-legacy/lib.rs index e9fc2140de438ded492a9c8ec97c5e9115d13274..8cb51d201479890a1242383585c7bb774e6c2f7b 100644 --- a/ws2p-v1-legacy/lib.rs +++ b/ws2p-v1-legacy/lib.rs @@ -16,7 +16,6 @@ //! WebSocketToPeer API for the Duniter project. #![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] #![deny( missing_debug_implementations, missing_copy_implementations, @@ -36,6 +35,8 @@ extern crate log; extern crate serde_derive; #[macro_use] extern crate serde_json; +#[macro_use] +extern crate structopt; extern crate byteorder; extern crate duniter_conf; @@ -70,7 +71,7 @@ use duniter_crypto::keys::*; use duniter_dal::dal_event::DALEvent; use duniter_dal::dal_requests::{DALReqBlockchain, DALRequest, DALResBlockchain, DALResponse}; use duniter_documents::Blockstamp; -use duniter_message::DuniterMessage; +use duniter_message::*; use duniter_module::*; use duniter_network::network_endpoint::*; use duniter_network::network_head::*; @@ -106,23 +107,27 @@ impl Default for WS2PConf { PubKey::Ed25519( ed25519::PublicKey::from_base58( "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", - ).unwrap(), + ) + .unwrap(), ), 0, 0, 1u16, - ).unwrap(), + ) + .unwrap(), EndpointEnum::parse_from_raw( "WS2P b48824f0 g1.monnaielibreoccitanie.org 443 /ws2p", PubKey::Ed25519( ed25519::PublicKey::from_base58( "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef", - ).unwrap(), + ) + .unwrap(), ), 0, 0, 1u16, - ).unwrap(), + ) + .unwrap(), ], } } @@ -141,7 +146,12 @@ pub enum WS2PSignal { PeerCard(NodeFullId, serde_json::Value, Vec<EndpointEnum>), Heads(NodeFullId, Vec<NetworkHead>), Document(NodeFullId, NetworkDocument), - ReqResponse(ModuleReqId, NetworkRequest, NodeFullId, serde_json::Value), + ReqResponse( + ModuleReqId, + OldNetworkRequest, + NodeFullId, + serde_json::Value, + ), Empty, NoConnection, } @@ -163,7 +173,7 @@ pub struct WS2PModule {} #[derive(Debug)] pub enum WS2PThreadSignal { - DuniterMessage(Box<DuniterMessage>), + DursMsg(Box<DursMsg>), WS2PConnectionMessage(WS2PConnectionMessage), } @@ -190,7 +200,7 @@ pub enum WS2PFeaturesParseError { UnknowApiFeature(String), } -impl ApiModule<DuRsConf, DuniterMessage> for WS2PModule { +impl ApiModule<DuRsConf, DursMsg> for WS2PModule { type ParseErr = WS2PFeaturesParseError; /// Parse raw api features fn parse_raw_api_features(str_features: &str) -> Result<ApiFeatures, Self::ParseErr> { @@ -212,13 +222,13 @@ impl ApiModule<DuRsConf, DuniterMessage> for WS2PModule { } } -impl NetworkModule<DuRsConf, DuniterMessage> for WS2PModule { +impl NetworkModule<DuRsConf, DursMsg> for WS2PModule { fn sync( _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _main_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, - _sync_endpoint: SyncEndpoint, + _main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + _sync_params: SyncParams, ) -> Result<(), ModuleInitError> { println!("Downlaod blockchain from network..."); println!("Error : not yet implemented !"); @@ -226,11 +236,20 @@ impl NetworkModule<DuRsConf, DuniterMessage> for WS2PModule { } } -impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { +#[derive(StructOpt, Debug, Copy, Clone)] +#[structopt( + name = "ws2p", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// WS2Pv1 subcommand options +pub struct WS2POpt {} + +impl DuniterModule<DuRsConf, DursMsg> for WS2PModule { type ModuleConf = WS2PConf; + type ModuleOpt = WS2POpt; - fn id() -> ModuleId { - ModuleId(String::from("ws2p")) + fn name() -> ModuleStaticName { + ModuleStaticName("ws2p") } fn priority() -> ModulePriority { ModulePriority::Essential() @@ -238,11 +257,22 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { fn ask_required_keys() -> RequiredKeys { RequiredKeys::NetworkKeyPair() } + fn have_subcommand() -> bool { + true + } + fn exec_subcommand( + _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, + _keys: RequiredKeysContent, + _module_conf: Self::ModuleConf, + _subcommand_args: WS2POpt, + ) -> () { + println!("Succesfully exec ws2p subcommand !") + } fn start( soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, keys: RequiredKeysContent, conf: WS2PConf, - rooter_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, + rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, load_conf_only: bool, ) -> Result<(), ModuleInitError> { // Get start time @@ -250,7 +280,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { // Define WS2PModuleDatas let mut ws2p_module = WS2PModuleDatas { - followers: Vec::new(), + rooter_sender: rooter_sender.clone(), key_pair: None, currency: None, conf, @@ -262,6 +292,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { heads_cache: HashMap::new(), my_head: None, uids_cache: HashMap::new(), + count_dal_requests: 0, }; // load conf @@ -287,27 +318,41 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { // Create proxy channel let (proxy_sender, proxy_receiver): ( - mpsc::Sender<DuniterMessage>, - mpsc::Receiver<DuniterMessage>, + mpsc::Sender<DursMsg>, + mpsc::Receiver<DursMsg>, ) = mpsc::channel(); let proxy_sender_clone = proxy_sender.clone(); - // Launch a proxy thread that transform DuniterMessage to WS2PThreadSignal(DuniterMessage) + // Launch a proxy thread that transform DursMsg to WS2PThreadSignal(DursMsg) thread::spawn(move || { // Send proxy sender to main rooter_sender - .send(RooterThreadMessage::ModuleSender(proxy_sender_clone)) + .send(RooterThreadMessage::ModuleSender( + WS2PModule::name(), + proxy_sender_clone, + vec![ModuleRole::InterNodesNetwork], + vec![ + ModuleEvent::NewValidBlock, + ModuleEvent::NewWotDocInPool, + ModuleEvent::NewTxinPool, + ], + )) .expect("Fatal error : ws2p module fail to send is sender channel !"); debug!("Send ws2p sender to main thread."); loop { match proxy_receiver.recv() { Ok(message) => { + let stop = if let DursMsgContent::Stop() = message.1 { + true + } else { + false + }; ws2p_sender_clone - .send(WS2PThreadSignal::DuniterMessage(Box::new(message.clone()))) + .send(WS2PThreadSignal::DursMsg(Box::new(message))) .expect( - "Fatal error : fail to relay DuniterMessage to ws2p main thread !", + "Fatal error : fail to relay DursMsgContent to ws2p main thread !", ); - if let DuniterMessage::Stop() = message { + if stop { break; }; } @@ -362,10 +407,10 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { .recv_timeout(Duration::from_millis(200)) { Ok(message) => match message { - WS2PThreadSignal::DuniterMessage(ref duniter_mesage) => { - match *duniter_mesage.deref() { - DuniterMessage::Stop() => break, - DuniterMessage::Followers(ref new_followers) => { + WS2PThreadSignal::DursMsg(ref duniter_mesage) => { + match (*duniter_mesage.deref()).1 { + DursMsgContent::Stop() => break, + /*DursMsgContent::Followers(ref new_followers) => { info!("WS2P module receive followers !"); for new_follower in new_followers { debug!("WS2PModule : push one follower."); @@ -375,7 +420,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { ws2p_module.send_dal_request( &DALRequest::BlockchainRequest( DALReqBlockchain::CurrentBlock(ModuleReqFullId( - WS2PModule::id(), + WS2PModule::name(), ModuleReqId(0), )), ), @@ -398,9 +443,9 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { ); } } - } - DuniterMessage::NetworkRequest(ref request) => match *request { - NetworkRequest::GetBlocks( + }*/ + DursMsgContent::OldNetworkRequest(ref request) => match *request { + OldNetworkRequest::GetBlocks( ref req_id, ref receiver, ref count, @@ -437,11 +482,8 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { let _blocks_request_result = ws2p_module .send_request_to_specific_node( &real_receiver, - &NetworkRequest::GetBlocks( - req_id.clone(), - *receiver, - *count, - *from, + &OldNetworkRequest::GetBlocks( + *req_id, *receiver, *count, *from, ), ); } @@ -449,19 +491,16 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { let _blocks_request_result = ws2p_module .send_request_to_specific_node( &receiver, - &NetworkRequest::GetBlocks( - req_id.clone(), - *receiver, - *count, - *from, + &OldNetworkRequest::GetBlocks( + *req_id, *receiver, *count, *from, ), ); } } - NetworkRequest::GetEndpoints(ref _request) => {} + OldNetworkRequest::GetEndpoints(ref _request) => {} _ => {} }, - DuniterMessage::DALEvent(ref dal_event) => match *dal_event { + DursMsgContent::DALEvent(ref dal_event) => match *dal_event { DALEvent::StackUpValidBlock(ref _block, ref blockstamp) => { current_blockstamp = *blockstamp; debug!( @@ -497,14 +536,16 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { "body": { "heads": [my_json_head] } - }).to_string(), + }) + .to_string(), )) - }).collect(); + }) + .collect(); } DALEvent::RevertBlocks(ref _blocks) => {} _ => {} }, - DuniterMessage::DALResponse(ref dal_res) => match *dal_res.deref() { + DursMsgContent::DALResponse(ref dal_res) => match *dal_res.deref() { DALResponse::Blockchain(ref dal_res_bc) => { match *dal_res_bc.deref() { DALResBlockchain::CurrentBlock( @@ -535,7 +576,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { ]), ); } - DALResBlockchain::UIDs(ref uids) => { + DALResBlockchain::UIDs(ref _req_id, ref uids) => { // Add uids to heads for head in ws2p_module.heads_cache.values_mut() { if let Some(uid_option) = uids.get(&head.pubkey()) { @@ -582,7 +623,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { _ => {} } } - DALResponse::Pendings(_, _) => {} + DALResponse::Pendings(_) => {} }, _ => {} } @@ -596,11 +637,11 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { WS2PSignal::ConnectionEstablished(ws2p_full_id) => { let req_id = ModuleReqId(ws2p_module.requests_awaiting_response.len() as u32); - let module_id = WS2PModule::id(); + let module_id = WS2PModule::name(); let _current_request_result = ws2p_module .send_request_to_specific_node( &ws2p_full_id, - &NetworkRequest::GetCurrent( + &OldNetworkRequest::GetCurrent( ModuleReqFullId(module_id, req_id), ws2p_full_id, ), @@ -699,7 +740,8 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { new_head.set_uid(uid); } new_head - }).collect(), + }) + .collect(), )); } WS2PSignal::Document(ws2p_full_id, network_doc) => { @@ -710,22 +752,28 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { } WS2PSignal::ReqResponse(req_id, req, recipient_full_id, response) => { match req { - NetworkRequest::GetCurrent(ref _req_id, _receiver) => { + OldNetworkRequest::GetCurrent(ref _req_id, _receiver) => { info!( "WS2PSignal::ReceiveCurrent({}, {:?}, {:#?})", req_id.0, req, response ); if let Some(block) = parse_json_block(&response) { - ws2p_module.send_network_event(&NetworkEvent::ReqResponse( - Box::new(NetworkResponse::CurrentBlock( - ModuleReqFullId(WS2PModule::id(), req_id), + ws2p_module.send_network_req_response( + req.get_req_full_id().0, + NetworkResponse::CurrentBlock( + ModuleReqFullId(WS2PModule::name(), req_id), recipient_full_id, Box::new(block), - )), - )); + ), + ); } } - NetworkRequest::GetBlocks(ref _req_id, _receiver, _count, from) => { + OldNetworkRequest::GetBlocks( + ref _req_id, + _receiver, + _count, + from, + ) => { info!("WS2PSignal::ReceiveChunk({}, {:?})", req_id.0, req); if response.is_array() { let mut chunk = Vec::new(); @@ -742,7 +790,7 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { ); } } - NetworkRequest::GetRequirementsPending( + OldNetworkRequest::GetRequirementsPending( _req_id, _receiver, min_cert, @@ -831,9 +879,9 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { request_blocks_from += 1; } info!("get chunks from all connections..."); - let module_id = WS2PModule::id(); + let module_id = WS2PModule::name(); let _blocks_request_result = - ws2p_module.send_request_to_all_connections(&NetworkRequest::GetBlocks( + ws2p_module.send_request_to_all_connections(&OldNetworkRequest::GetBlocks( ModuleReqFullId(module_id, ModuleReqId(0 as u32)), NodeFullId::default(), 50, @@ -849,9 +897,9 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { && SystemTime::now().duration_since(start_time).unwrap() > Duration::new(10, 0) { /*info!("get pending_identities from all connections..."); - let _blocks_request_result = ws2p_module.send_request_to_all_connections( - &NetworkRequest::GetRequirementsPending(ModuleReqId(0 as u32), 5), - );*/ + let _blocks_request_result = ws2p_module.send_request_to_all_connections( + &OldNetworkRequest::GetRequirementsPending(ModuleReqId(0 as u32), 5), + );*/ last_identities_request = SystemTime::now(); } // Write pending endpoints @@ -863,14 +911,14 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2PModule { ws2p_module.ws2p_endpoints.get(&ep_full_id) { /*let dal_endpoint = duniter_dal::endpoint::DALEndpoint::new( - state.clone() as u32, - ep.node_uuid().unwrap().0, - ep.pubkey(), - duniter_dal::endpoint::string_to_api(&ep.api().0).unwrap(), - 1, - ep.to_string(), - received_time.duration_since(UNIX_EPOCH).unwrap(), - );*/ + state.clone() as u32, + ep.node_uuid().unwrap().0, + ep.pubkey(), + duniter_dal::endpoint::string_to_api(&ep.api().0).unwrap(), + 1, + ep.to_string(), + received_time.duration_since(UNIX_EPOCH).unwrap(), + );*/ ws2p_db::write_endpoint( &db, &ep, @@ -1111,7 +1159,8 @@ mod tests { 1, current_time.as_secs(), 1, - ).expect("Failt to parse test endpoint !"); + ) + .expect("Failt to parse test endpoint !"); ws2p_db::write_endpoint(&db, &endpoint, 1, current_time.as_secs()); let mut written_endpoints = @@ -1128,8 +1177,8 @@ mod tests { #[test] fn ws2p_requests() { - let module_id = WS2PModule::id(); - let request = NetworkRequest::GetBlocks( + let module_id = WS2PModule::name(); + let request = OldNetworkRequest::GetBlocks( ModuleReqFullId(module_id, ModuleReqId(58)), NodeFullId::default(), 50, diff --git a/ws2p-v1-legacy/parsers/blocks.rs b/ws2p-v1-legacy/parsers/blocks.rs index 4a8fdc0c972d65508a139f1dd5c7e82be21e0256..ae3aa8dd3ea4b0475bc84275974742830f653e52 100644 --- a/ws2p-v1-legacy/parsers/blocks.rs +++ b/ws2p-v1-legacy/parsers/blocks.rs @@ -19,11 +19,13 @@ fn parse_previous_hash(block_number: BlockId, source: &serde_json::Value) -> Opt Ok(hash) => Some(hash), Err(_) => None, }, - None => if block_number.0 > 0 { - None - } else { - Some(Hash::default()) - }, + None => { + if block_number.0 > 0 { + None + } else { + Some(Hash::default()) + } + } } } diff --git a/ws2p-v1-legacy/parsers/identities.rs b/ws2p-v1-legacy/parsers/identities.rs index 3de01344f5e9d5d4c1f4c17417b64add3d11b84e..ef62335415055c325cef050850d8957efc949fb9 100644 --- a/ws2p-v1-legacy/parsers/identities.rs +++ b/ws2p-v1-legacy/parsers/identities.rs @@ -20,7 +20,8 @@ pub fn parse_identities(currency: &str, json_datas: &str) -> Option<Vec<Identity .map(|i| { i.clone() .expect("Fatal error : Fail to parse identity from local DB !") - }).collect(), + }) + .collect(), ); } None @@ -50,7 +51,8 @@ pub fn parse_identities_from_json_value( } else { Err(IdentityParseError::WrongFormat()) } - }).collect() + }) + .collect() } pub fn parse_compact_identity( diff --git a/ws2p-v1-legacy/parsers/memberships.rs b/ws2p-v1-legacy/parsers/memberships.rs index 1d9c76bdbea1fc8b4dc70c5bdc0760a709fcdccd..a193d5e64ea9ed393bd606eb63b85fd4a29d77a2 100644 --- a/ws2p-v1-legacy/parsers/memberships.rs +++ b/ws2p-v1-legacy/parsers/memberships.rs @@ -25,11 +25,13 @@ pub fn parse_memberships( currency, membership_type, raw_memberships.as_array().unwrap(), - ).iter() + ) + .iter() .map(|m| { m.clone() .expect("Fatal error : Fail to parse membership from local DB !") - }).collect(), + }) + .collect(), ); } None @@ -62,5 +64,6 @@ pub fn parse_memberships_from_json_value( } else { Err(MembershipParseError::WrongFormat()) } - }).collect() + }) + .collect() } diff --git a/ws2p-v1-legacy/parsers/mod.rs b/ws2p-v1-legacy/parsers/mod.rs index 4865af2852d5b8bc7d4e1040da072e78313533a0..7796b278e480cfc8e02a2530a9d2366ca0d5f949 100644 --- a/ws2p-v1-legacy/parsers/mod.rs +++ b/ws2p-v1-legacy/parsers/mod.rs @@ -58,7 +58,8 @@ mod tests { currency: "g1", blockstamp: &Blockstamp::from_string( "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1", - ).unwrap(), + ) + .unwrap(), locktime: &0, issuers: &vec![PubKey::Ed25519( ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2") @@ -67,12 +68,14 @@ mod tests { inputs: &vec![ TransactionInput::parse_from_str( "1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496", - ).unwrap(), + ) + .unwrap(), ], outputs: &vec![ TransactionOutput::parse_from_str( "1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)", - ).unwrap(), + ) + .unwrap(), ], unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], comment: "Merci pour la calligraphie ;) de Liam", @@ -118,7 +121,8 @@ mod tests { currency: "g1", blockstamp: &Blockstamp::from_string( "58-00005B9167EBA1E32C6EAD42AE7F72D8F14B765D3C9E47D233B553D47C5AEE0C", - ).unwrap(), + ) + .unwrap(), locktime: &0, issuers: &vec![PubKey::Ed25519( ed25519::PublicKey::from_base58("FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD") @@ -127,15 +131,18 @@ mod tests { inputs: &vec![ TransactionInput::parse_from_str( "1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1", - ).unwrap(), + ) + .unwrap(), ], outputs: &vec![ TransactionOutput::parse_from_str( "3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)", - ).unwrap(), + ) + .unwrap(), TransactionOutput::parse_from_str( "997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)", - ).unwrap(), + ) + .unwrap(), ], unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], comment: "Un petit cafe ;-)", diff --git a/ws2p-v1-legacy/parsers/transactions.rs b/ws2p-v1-legacy/parsers/transactions.rs index fdd1dd353470e270e33ee7fb3f76642cd59d3db9..2484034c468f51e66c5fbbf16fb938b818ddb128 100644 --- a/ws2p-v1-legacy/parsers/transactions.rs +++ b/ws2p-v1-legacy/parsers/transactions.rs @@ -114,7 +114,8 @@ Merci pour la calligraphie ;) de Liam$\ currency: "g1", blockstamp: &Blockstamp::from_string( "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1", - ).unwrap(), + ) + .unwrap(), locktime: &0, issuers: &vec![PubKey::Ed25519( ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2") @@ -123,12 +124,14 @@ Merci pour la calligraphie ;) de Liam$\ inputs: &vec![ TransactionInput::parse_from_str( "1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496", - ).unwrap(), + ) + .unwrap(), ], outputs: &vec![ TransactionOutput::parse_from_str( "1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)", - ).unwrap(), + ) + .unwrap(), ], unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], comment: "Merci pour la calligraphie ;) de Liam", diff --git a/ws2p-v1-legacy/ws2p_connection.rs b/ws2p-v1-legacy/ws2p_connection.rs index cdc43a9160acc32f788add3e952dbea8331d5def..11969541bf44553b647af4e5210b996361b651eb 100644 --- a/ws2p-v1-legacy/ws2p_connection.rs +++ b/ws2p-v1-legacy/ws2p_connection.rs @@ -479,45 +479,52 @@ impl WS2PConnectionMetaDatas { } if let Some(body) = m.get("body") { match body.get("name") { - Some(s) => if s.is_string() { - match s.as_str().unwrap() { - "BLOCK" => match body.get("block") { - Some(block) => { - if let Some(network_block) = parse_json_block(&block) { - return WS2PConnectionMessagePayload::Document( - NetworkDocument::Block(network_block), - ); - } else { - info!("WS2PSignal: receive invalid block (wrong format)."); - }; - } - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - "HEAD" => match body.get("heads") { - Some(heads) => match heads.as_array() { - Some(heads_array) => { - return WS2PConnectionMessagePayload::Heads(heads_array.clone()) + Some(s) => { + if s.is_string() { + match s.as_str().unwrap() { + "BLOCK" => match body.get("block") { + Some(block) => { + if let Some(network_block) = parse_json_block(&block) { + return WS2PConnectionMessagePayload::Document( + NetworkDocument::Block(network_block), + ); + } else { + info!("WS2PSignal: receive invalid block (wrong format)."); + }; } None => return WS2PConnectionMessagePayload::WrongFormatMessage, }, - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - "PEER" => return self.parse_and_check_peer_message(body), - "CERTIFICATION" => { - trace!("WS2P : Receive CERTIFICATION from {}.", self.node_full_id()); - /*return WS2PConnectionMessagePayload::Document( - NetworkDocument::Certification(_) - );*/ - } - _ => { - /*trace!( - "WS2P : Receive Unknow Message from {}.", - self.node_full_id() - );*/ - return WS2PConnectionMessagePayload::UnknowMessage; - } - }; - }, + "HEAD" => match body.get("heads") { + Some(heads) => match heads.as_array() { + Some(heads_array) => { + return WS2PConnectionMessagePayload::Heads( + heads_array.clone(), + ) + } + None => return WS2PConnectionMessagePayload::WrongFormatMessage, + }, + None => return WS2PConnectionMessagePayload::WrongFormatMessage, + }, + "PEER" => return self.parse_and_check_peer_message(body), + "CERTIFICATION" => { + trace!( + "WS2P : Receive CERTIFICATION from {}.", + self.node_full_id() + ); + /*return WS2PConnectionMessagePayload::Document( + NetworkDocument::Certification(_) + );*/ + } + _ => { + /*trace!( + "WS2P : Receive Unknow Message from {}.", + self.node_full_id() + );*/ + return WS2PConnectionMessagePayload::UnknowMessage; + } + }; + } + } None => { warn!("WS2P Error : invalid format : Body must contain a field name !"); return WS2PConnectionMessagePayload::WrongFormatMessage; diff --git a/ws2p-v1-legacy/ws2p_db.rs b/ws2p-v1-legacy/ws2p_db.rs index 725347be2659331e049b69db1e96218b38b16bda..88f165a7d7f76f2a2f68eeb017add0e1d841e558 100644 --- a/ws2p-v1-legacy/ws2p_db.rs +++ b/ws2p-v1-legacy/ws2p_db.rs @@ -121,7 +121,8 @@ pub fn write_endpoint( "UPDATE endpoints SET status={} WHERE hash_full_id='{}'", endpoint.status(), hash_full_id - )).expect("Fail to parse SQL request update endpoint status !"); + )) + .expect("Fail to parse SQL request update endpoint status !"); } } else if let EndpointEnum::V1(ref ep_v10) = *endpoint { db diff --git a/ws2p-v1-legacy/ws2p_requests.rs b/ws2p-v1-legacy/ws2p_requests.rs index 722b0154b8a156a119774775671c41ab1a6f7eb6..72b988418355e759653d73b74a7e0a95a3a51d67 100644 --- a/ws2p-v1-legacy/ws2p_requests.rs +++ b/ws2p-v1-legacy/ws2p_requests.rs @@ -3,14 +3,14 @@ extern crate duniter_network; extern crate serde; extern crate serde_json; -use duniter_network::NetworkRequest; +use duniter_network::OldNetworkRequest; -pub fn network_request_to_json(request: &NetworkRequest) -> serde_json::Value { +pub fn network_request_to_json(request: &OldNetworkRequest) -> serde_json::Value { let (request_id, request_type, request_params) = match *request { - NetworkRequest::GetCurrent(ref req_full_id, _receiver) => { + OldNetworkRequest::GetCurrent(ref req_full_id, _receiver) => { (req_full_id.1, "CURRENT", json!({})) } - NetworkRequest::GetBlocks(ref req_full_id, _receiver, count, from_mumber) => ( + OldNetworkRequest::GetBlocks(ref req_full_id, _receiver, count, from_mumber) => ( req_full_id.1, "BLOCKS_CHUNK", json!({ @@ -18,18 +18,18 @@ pub fn network_request_to_json(request: &NetworkRequest) -> serde_json::Value { "fromNumber": from_mumber }), ), - NetworkRequest::GetRequirementsPending(ref req_full_id, _receiver, min_cert) => ( + OldNetworkRequest::GetRequirementsPending(ref req_full_id, _receiver, min_cert) => ( req_full_id.1, "WOT_REQUIREMENTS_OF_PENDING", json!({ "minCert": min_cert }), ), - NetworkRequest::GetConsensus(_) => { + OldNetworkRequest::GetConsensus(_) => { panic!("GetConsensus() request must be not convert to json !"); } - NetworkRequest::GetHeadsCache(_) => { + OldNetworkRequest::GetHeadsCache(_) => { panic!("GetHeadsCache() request must be not convert to json !"); } - NetworkRequest::GetEndpoints(_) => { + OldNetworkRequest::GetEndpoints(_) => { panic!("GetEndpoints() request must be not convert to json !"); } }; diff --git a/ws2p/Cargo.toml b/ws2p/Cargo.toml index 80b49ca3e9700da74ad3117e684ea2540a6b8a8b..9180eefb609fd93b2c9ed855006124170d7d4a3b 100644 --- a/ws2p/Cargo.toml +++ b/ws2p/Cargo.toml @@ -18,6 +18,7 @@ durs-ws2p-messages = { path = "../ws2p-messages" } log = "0.4.*" serde = "1.0.*" serde_derive = "1.0.*" +structopt= "0.2.*" [features] # Treat warnings as a build error. diff --git a/ws2p/lib.rs b/ws2p/lib.rs index 14796e5e671c0ad96115c82caf6ce6794e36deba..cbb708c44d2d9d2a6e321a0b5650fcae8efa6274 100644 --- a/ws2p/lib.rs +++ b/ws2p/lib.rs @@ -31,6 +31,8 @@ extern crate log; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate structopt; extern crate duniter_conf; extern crate duniter_crypto; @@ -44,7 +46,7 @@ mod constants; use constants::*; use duniter_conf::DuRsConf; use duniter_crypto::keys::*; -use duniter_message::DuniterMessage; +use duniter_message::DursMsg; use duniter_module::*; use duniter_network::network_endpoint::*; use duniter_network::*; @@ -69,23 +71,27 @@ impl Default for WS2PConf { PubKey::Ed25519( ed25519::PublicKey::from_base58( "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", - ).unwrap(), + ) + .unwrap(), ), 0, 0, 1u16, - ).unwrap(), + ) + .unwrap(), EndpointEnum::parse_from_raw( "WS2P b48824f0 g1.monnaielibreoccitanie.org 443 /ws2p", PubKey::Ed25519( ed25519::PublicKey::from_base58( "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef", - ).unwrap(), + ) + .unwrap(), ), 0, 0, 1u16, - ).unwrap(), + ) + .unwrap(), ], } } @@ -108,7 +114,7 @@ pub enum WS2PFeaturesParseError { UnknowApiFeature(String), } -impl ApiModule<DuRsConf, DuniterMessage> for WS2Pv2Module { +impl ApiModule<DuRsConf, DursMsg> for WS2Pv2Module { type ParseErr = WS2PFeaturesParseError; /// Parse raw api features fn parse_raw_api_features(str_features: &str) -> Result<ApiFeatures, Self::ParseErr> { @@ -134,23 +140,32 @@ impl ApiModule<DuRsConf, DuniterMessage> for WS2Pv2Module { } } -impl NetworkModule<DuRsConf, DuniterMessage> for WS2Pv2Module { +impl NetworkModule<DuRsConf, DursMsg> for WS2Pv2Module { fn sync( _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _main_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, - _sync_endpoint: SyncEndpoint, + _main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + _sync_params: SyncParams, ) -> Result<(), ModuleInitError> { unimplemented!() } } -impl DuniterModule<DuRsConf, DuniterMessage> for WS2Pv2Module { +#[derive(StructOpt, Debug, Copy, Clone)] +#[structopt( + name = "ws2p", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// WS2P subcommand options +pub struct WS2POpt {} + +impl DuniterModule<DuRsConf, DursMsg> for WS2Pv2Module { type ModuleConf = WS2PConf; + type ModuleOpt = WS2POpt; - fn id() -> ModuleId { - ModuleId(String::from("ws2p")) + fn name() -> ModuleStaticName { + ModuleStaticName("ws2p") } fn priority() -> ModulePriority { ModulePriority::Essential() @@ -158,11 +173,22 @@ impl DuniterModule<DuRsConf, DuniterMessage> for WS2Pv2Module { fn ask_required_keys() -> RequiredKeys { RequiredKeys::NetworkKeyPair() } + fn have_subcommand() -> bool { + true + } + fn exec_subcommand( + _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, + _keys: RequiredKeysContent, + _module_conf: Self::ModuleConf, + _subcommand_args: WS2POpt, + ) -> () { + println!("Succesfully exec ws2p subcommand !") + } fn start( _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _rooter_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, + _rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, _load_conf_only: bool, ) -> Result<(), ModuleInitError> { unimplemented!()